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 .