Перейти к основному содержимому

Руководство по Spring Cloud Kubernetes

· 8 мин. чтения

1. Обзор

Когда мы создаем решение для микросервисов, и Spring Cloud , и Kubernetes являются оптимальными решениями, поскольку они предоставляют компоненты для решения наиболее распространенных задач. Однако, если мы решим выбрать Kubernetes в качестве основного менеджера контейнеров и платформы развертывания для нашего решения, мы все равно сможем использовать интересные функции Spring Cloud в основном через проект Spring Cloud Kubernetes .

Этот относительно новый проект, несомненно, обеспечивает простую интеграцию с Kubernetes для приложений Spring Boot . Перед началом может быть полезно посмотреть, как развернуть приложение Spring Boot в Minikube , локальной среде Kubernetes .

В этом уроке мы:

  • Установите Minikube на нашу локальную машину
  • Разработайте пример архитектуры микросервисов с двумя независимыми приложениями Spring Boot, взаимодействующими через REST.
  • Настройте приложение в кластере с одним узлом с помощью Minikube.
  • Разверните приложение с помощью конфигурационных файлов YAML .

2. Сценарий

В нашем примере мы используем сценарий турагентов, предлагающих различные предложения клиентам, которые время от времени будут запрашивать услуги турагентов. Мы будем использовать его для демонстрации:

  • обнаружение сервисов через Spring Cloud Kubernetes
  • управление конфигурацией и внедрение Kubernetes ConfigMaps и секретов в модули приложений с помощью Spring Cloud Kubernetes Config
  • балансировка нагрузки с использованием ленты Spring Cloud Kubernetes

3. Настройка среды

Прежде всего, нам нужно установить Minikube на нашу локальную машину и, желательно, драйвер виртуальной машины, такой как VirtualBox . Также рекомендуется ознакомиться с Kubernetes и его основными функциями, прежде чем следовать этой настройке среды.

Запустим локальный одноузловой кластер Kubernetes:

minikube start --vm-driver=virtualbox

Эта команда создает виртуальную машину, на которой работает кластер Minikube с использованием драйвера VirtualBox. Контекст по умолчанию в kubectl теперь будет minikube . Однако, чтобы иметь возможность переключаться между контекстами, мы используем:

kubectl config use-context minikube

После запуска Minikube мы можем подключиться к панели управления Kubernetes , чтобы получить доступ к журналам и легко отслеживать наши службы, модули, ConfigMaps и секреты:

minikube dashboard

3.1. Развертывание

Во-первых, давайте возьмем наш пример с GitHub .

На этом этапе мы можем либо запустить скрипт «deployment-travel-client.sh» из родительской папки, либо выполнить каждую инструкцию одну за другой, чтобы получить представление о процедуре:

### build the repository
mvn clean install

### set docker env
eval $(minikube docker-env)

### build the docker images on minikube
cd travel-agency-service
docker build -t travel-agency-service .
cd ../client-service
docker build -t client-service .
cd ..

### secret and mongodb
kubectl delete -f travel-agency-service/secret.yaml
kubectl delete -f travel-agency-service/mongo-deployment.yaml

kubectl create -f travel-agency-service/secret.yaml
kubectl create -f travel-agency-service/mongo-deployment.yaml

### travel-agency-service
kubectl delete -f travel-agency-service/travel-agency-deployment.yaml
kubectl create -f travel-agency-service/travel-agency-deployment.yaml

### client-service
kubectl delete configmap client-service
kubectl delete -f client-service/client-service-deployment.yaml

kubectl create -f client-service/client-config.yaml
kubectl create -f client-service/client-service-deployment.yaml

# Check that the pods are running
kubectl get pods

4. Обнаружение службы

Этот проект предоставляет нам реализацию интерфейса ServiceDiscovery в Kubernetes. В среде микросервисов обычно существует несколько модулей, выполняющих одну и ту же службу. Kubernetes предоставляет сервис как набор конечных точек , которые можно получить и получить из приложения Spring Boot, работающего в модуле в том же кластере Kubernetes.

Например, в нашем примере у нас есть несколько реплик службы турагента, доступ к которым осуществляется из нашей клиентской службы по адресу http://travel-agency-service:8080 . Однако внутри это приведет к доступу к различным модулям, таким как travel-agency-service-7c9cfff655-4hxnp .

Лента Spring Cloud Kubernetes использует эту функцию для балансировки нагрузки между различными конечными точками службы.

Мы можем легко использовать Service Discovery, добавив зависимость spring-cloud-starter-kubernetes в наше клиентское приложение:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes</artifactId>
</dependency>

Кроме того, мы должны добавить @EnableDiscoveryClient и внедрить DiscoveryClient в ClientController , используя @Autowired в нашем классе:

@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
public class ClientController {
@Autowired
private DiscoveryClient discoveryClient;
}

5. Карты конфигурации

Как правило, микросервисы требуют некоторого управления конфигурацией . Например, в приложениях Spring Cloud мы будем использовать сервер конфигурации Spring Cloud.

Однако мы можем добиться этого, используя ConfigMaps , предоставляемые Kubernetes, при условии, что мы намерены использовать их только для неконфиденциальной незашифрованной информации. В качестве альтернативы, если информация, которой мы хотим поделиться, является конфиденциальной, мы должны вместо этого использовать секреты .

В нашем примере мы используем ConfigMaps в клиентском приложении Spring Boot. Давайте создадим клиент-конфиг. yaml для определения ConfigMap клиентской службы :

apiVersion: v1 by d
kind: ConfigMap
metadata:
name: client-service
data:
application.properties: |-
bean.message=Testing reload! Message from backend is: %s <br/> Services : %s

Важно, чтобы имя ConfigMap совпадало с именем приложения , указанным в нашем файле «application.properties». В данном случае это клиент-сервис . Далее нам нужно создать ConfigMap для клиент-сервиса в Kubernetes:

kubectl create -f client-config.yaml

Теперь давайте создадим класс конфигурации ClientConfig с @Configuration и @ConfigurationProperties и внедрим его в ClientController :

@Configuration
@ConfigurationProperties(prefix = "bean")
public class ClientConfig {

private String message = "Message from backend is: %s <br/> Services : %s";

// getters and setters
}
@RestController
public class ClientController {

@Autowired
private ClientConfig config;

@GetMapping
public String load() {
return String.format(config.getMessage(), "", "");
}
}

Если мы не укажем ConfigMap, то мы должны ожидать увидеть сообщение по умолчанию, которое установлено в классе. Однако когда мы создаем ConfigMap, это сообщение по умолчанию переопределяется этим свойством.

Кроме того, каждый раз, когда мы решаем обновить ConfigMap, сообщение на странице меняется соответствующим образом:

kubectl edit configmap client-service

6. Секреты

Давайте посмотрим, как работают секреты , взглянув на спецификацию настроек подключения MongoDB в нашем примере. Мы собираемся создать переменные среды в Kubernetes, которые затем будут внедрены в приложение Spring Boot.

6.1. Создать секрет

Первый шаг — создать файл secret.yaml , закодировав имя пользователя и пароль в Base 64 :

apiVersion: v1
kind: Secret
metadata:
name: db-secret
data:
username: dXNlcg==
password: cDQ1NXcwcmQ=

Применим конфигурацию Secret к кластеру Kubernetes:

kubectl apply -f secret.yaml

6.2. Создать службу MongoDB

Теперь мы должны создать службу MongoDB и файл развертывания travel-agency-deployment.yaml . В частности, в части развертывания мы будем использовать секретное имя пользователя и пароль , которые мы определили ранее:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mongo
spec:
replicas: 1
template:
metadata:
labels:
service: mongo
name: mongodb-service
spec:
containers:
- args:
- mongod
- --smallfiles
image: mongo:latest
name: mongo
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password

По умолчанию образ mongo:latest создаст пользователя с именем пользователя и паролем в базе данных с именем admin.

6.3. Настройка MongoDB в службе туристического агентства

Важно обновить свойства приложения, чтобы добавить информацию, связанную с базой данных. Хотя мы можем свободно указать имя базы данных admin , здесь мы скрываем наиболее важную информацию, такую как имя пользователя и пароль :

spring.cloud.kubernetes.reload.enabled=true
spring.cloud.kubernetes.secrets.name=db-secret
spring.data.mongodb.host=mongodb-service
spring.data.mongodb.port=27017
spring.data.mongodb.database=admin
spring.data.mongodb.username=${MONGO_USERNAME}
spring.data.mongodb.password=${MONGO_PASSWORD}

Теперь давайте посмотрим на наш файл свойств travel-agency-deployment , чтобы обновить службы и развертывания с помощью информации об имени пользователя и пароле, необходимой для подключения к mongodb-service .

Вот соответствующий раздел файла с частью, связанной с подключением к MongoDB:

env:
- name: MONGO_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: MONGO_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password

7. Связь с лентой

В среде микросервисов нам обычно нужен список модулей, в которых реплицируется наш сервис, чтобы выполнить балансировку нагрузки. Это достигается с помощью механизма, предоставляемого лентой Spring Cloud Kubernetes. Этот механизм может автоматически обнаруживать и получать доступ ко всем конечным точкам определенной службы , а затем заполняет Ribbon ServerList информацией о конечных точках.

Начнем с добавления зависимости spring-cloud-starter-kubernetes-ribbon в наш файл pom.xml client-service :

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
</dependency>

Следующим шагом будет добавление аннотации @RibbonClient в наше клиентское приложение:

@RibbonClient(name = "travel-agency-service")

Когда список конечных точек заполнен, клиент Kubernetes будет искать зарегистрированные конечные точки, находящиеся в текущем пространстве имен/проекте, соответствующие имени службы, определенному с помощью аннотации @RibbonClient .

Также нам необходимо включить ленточный клиент в свойствах приложения:

ribbon.http.client.enabled=true

8. Дополнительные возможности

8.1. Хайстрикс

Hystrix помогает создавать отказоустойчивые и отказоустойчивые приложения. Его основными целями являются отказоустойчивость и быстрое восстановление.

В частности, в нашем примере мы используем Hystrix для реализации шаблона прерывателя цепи на клиент-сервере , аннотируя класс приложения Spring Boot с помощью @EnableCircuitBreaker .

Кроме того, мы используем резервную функцию, аннотируя метод TravelAgencyService.getDeals() с помощью @HystrixCommand() . Это означает, что в случае отката будет вызвана функция getFallBackName() и возвращено сообщение «Fallback»:

@HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = { 
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") })
public String getDeals() {
return this.restTemplate.getForObject("http://travel-agency-service:8080/deals", String.class);
}

private String getFallbackName() {
return "Fallback";
}

8.2. Индикатор работоспособности модуля

Мы можем воспользоваться преимуществами Spring Boot HealthIndicator и Spring Boot Actuator , чтобы предоставить пользователю информацию, связанную со здоровьем.

В частности, индикатор работоспособности Kubernetes обеспечивает:

  • имя модуля
  • айпи адрес
  • пространство имен
  • сервисный аккаунт
  • имя узла
  • флаг, указывающий, является ли приложение Spring Boot внутренним или внешним по отношению к Kubernetes.

9. Заключение

В этой статье мы предоставляем подробный обзор проекта Spring Cloud Kubernetes.

Так почему мы должны его использовать? Если мы поддерживаем Kubernetes как платформу микросервисов, но по-прежнему ценим возможности Spring Cloud, то Spring Cloud Kubernetes дает нам лучшее из обоих миров.

Полный исходный код примера доступен на GitHub .