Guia para Kubernetes do Spring Cloud
1. Visão geral
Quando construímos uma solução de microsserviços,Spring CloudeKubernetes são soluções ideais, pois fornecem componentes para resolver os desafios mais comuns. No entanto, se decidirmos escolher o Kubernetes como o principal gerenciador de contêineres e plataforma de implantação para nossa solução, ainda podemos usar os recursos interessantes do Spring Cloud principalmente por meio do projetoSpring Cloud Kubernetes.
Este projeto relativamente novo, sem dúvida, fornece fácil integração com o Kubernetes para aplicativosSpring Boot. Antes de começar, pode ser útil ver como implantar umSpring Boot application on Minikube, um ambiente Kubernetes local.
Neste tutorial, vamos:
-
Instale o Minikube em nossa máquina local
-
Desenvolva um exemplo de arquitetura de microsserviços com dois aplicativos Spring Boot independentes se comunicando através do REST
-
Configure o aplicativo em um cluster de um nó usando o Minikube
-
Implante o aplicativo usando arquivos de configuraçãoYAML
2. Cenário
Em nosso exemplo, estamos usando o cenário de agentes de viagens que oferecem várias ofertas a clientes que consultam o serviço de agentes de viagens de tempos em tempos. Vamos usá-lo para demonstrar:
-
service discovery por meio do Spring Cloud Kubernetes
-
configuration managemente injetar ConfigMaps e segredos do Kubernetes em pods de aplicativos usando o Spring Cloud Kubernetes Config
-
load balancing usando Spring Cloud Kubernetes Ribbon
3. Configuração do ambiente
Em primeiro lugar, precisamosinstall Minikube on our local machinee preferencialmente um driver VM comoVirtualBox. Também é recomendado olhar paraKubernetese seus principais recursos antes de seguir a configuração deste ambiente.
Vamos começar o cluster Kubernetes de nó único local:
minikube start --vm-driver=virtualbox
Este comando cria uma máquina virtual que executa um cluster do Minikube usando o driver do VirtualBox. O contexto padrão emkubectl agora seráminikube. No entanto, para poder alternar entre contextos, usamos:
kubectl config use-context minikube
Depois de iniciar o Minikube, podemosconnect to the Kubernetes dashboard para acessar os logs e monitorar nossos serviços, pods, ConfigMaps e Secrets facilmente:
minikube dashboard
3.1. Desdobramento, desenvolvimento
Em primeiro lugar, vamos pegar nosso exemplo deGitHub.
Nesse ponto, podemos executar o script "deployment-travel-client.sh" na pasta pai ou executar cada instrução uma por uma para obter uma boa compreensão do procedimento:
### 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. Descoberta de serviço
Este projeto nos fornece uma implementação para a interfaceServiceDiscovery no Kubernetes. Em um ambiente de microsserviços, geralmente existem vários pods executando o mesmo serviço. Kubernetes exposes the service as a collection of endpoints que podem ser buscados e alcançados de dentro de um aplicativo Spring Boot em execução em um pod no mesmo cluster Kubernetes.
Por exemplo, em nosso exemplo, temos várias réplicas do serviço do agente de viagens, que é acessado de nosso serviço ao cliente comohttp://travel-agency-service:8080. No entanto, isso internamente se traduziria em acessar pods diferentes, comotravel-agency-service-7c9cfff655-4hxnp.
O Spring Cloud Kubernetes Ribbon usa esse recurso para balancear a carga entre os diferentes endpoints de um serviço.
Podemos usar facilmente o Service Discovery adicionando a dependênciaspring-cloud-starter-kubernetes em nosso aplicativo cliente:
org.springframework.cloud
spring-cloud-starter-kubernetes
Além disso, devemos adicionar@EnableDiscoveryCliente injetarDiscoveryClient emClientController usando@Autowired em nossa classe:
@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. ConfigMaps
Normalmente,microservices require some kind of configuration management. Por exemplo, nos aplicativos Spring Cloud, usaríamos um servidor de configuração do Spring Cloud.
No entanto, podemos conseguir isso usandoConfigMaps fornecido pelo Kubernetes - desde que pretendamos usá-lo apenas para informações não confidenciais e não criptografadas. Alternativamente, se as informações que queremos compartilhar são confidenciais, devemos optar por usarSecrets.
Em nosso exemplo, estamos usando ConfigMaps no aplicativo Spring Bootclient-service. Vamos criar um arquivo syamlclient-config.para definir o ConfigMap declient-service:
apiVersion: v1 by d
kind: ConfigMap
metadata:
name: client-service
data:
application.properties: |-
bean.message=Testing reload! Message from backend is: %s
Services : %s
It’s important that the name of the ConfigMap matches the name of the application conforme especificado em nosso arquivo “application.properties”. Nesse caso, éclient-service. Em seguida, devemos criar o ConfigMap paraclient-service no Kubernetes:
kubectl create -f client-config.yaml
Agora, vamos criar uma classe de configuraçãoClientConfig com@Configuratione@ConfigurationProperties e injetar emClientController:
@Configuration
@ConfigurationProperties(prefix = "bean")
public class ClientConfig {
private String message = "Message from backend is: %s
Services : %s";
// getters and setters
}
@RestController
public class ClientController {
@Autowired
private ClientConfig config;
@GetMapping
public String load() {
return String.format(config.getMessage(), "", "");
}
}
Se não especificarmos um ConfigMap, devemos esperar ver a mensagem padrão, que é definida na classe. No entanto, quando criamos o ConfigMap, essa mensagem padrão é substituída por essa propriedade.
Além disso, sempre que decidimos atualizar o ConfigMap, a mensagem na página muda de acordo:
kubectl edit configmap client-service
6. Segredos
Vejamos comoSecrets funciona examinando a especificação das configurações de conexão do MongoDB em nosso exemplo. Vamos criar variáveis de ambiente no Kubernetes, que serão injetadas no aplicativo Spring Boot.
6.1. Crie um segredo
A primeira etapa é criar um arquivosecret.yaml, codificandousernameepassword paraBase 64:
apiVersion: v1
kind: Secret
metadata:
name: db-secret
data:
username: dXNlcg==
password: cDQ1NXcwcmQ=
Vamos aplicar a configuração do Secret no cluster Kubernetes:
kubectl apply -f secret.yaml
6.2. Crie um serviço MongoDB
Agora devemos criar o serviço MongoDB e o arquivo de implantaçãotravel-agency-deployment.yaml. Em particular, na parte de implantação, usaremos o segredousernameepassword que definimos anteriormente:
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
Por padrão, a imagemmongo:latest criará um usuário comusernameepassword em um banco de dados chamadoadmin.
6.3. Configurar o MongoDB no serviço da agência de viagens
É importante atualizar as propriedades do aplicativo para adicionar as informações relacionadas ao banco de dados. Embora possamos especificar livremente o nome do banco de dadosadmin, aqui estamos ocultando as informações mais confidenciais, comousernameepassword:
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}
Agora, vamos dar uma olhada em nosso arquivo de propriedadetravel-agency-deployment para atualizar os serviços e implantações com as informações de nome de usuário e senha necessárias para se conectar aomongodb-service.
Esta é a seção relevante do arquivo, com a parte relacionada à conexão MongoDB:
env:
- name: MONGO_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: MONGO_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
7. Comunicação com fita
Em um ambiente de microsserviços, geralmente precisamos da lista de pods em que nosso serviço é replicado para executar o balanceamento de carga. Isso é feito usando um mecanismo fornecido pelo Spring Cloud Kubernetes Ribbon. Este mecanismo podeautomatically discover and reach all the endpoints of a specific service e, subsequentemente, ele preenche um RibbonServerList com informações sobre os terminais.
Vamos começar adicionando a dependênciaspring-cloud-starter-kubernetes-ribbon ao nosso arquivoclient-service pom.xml:
org.springframework.cloud
spring-cloud-starter-kubernetes-ribbon
A próxima etapa é adicionar a anotação@RibbonClient ao nosso aplicativoclient-service:
@RibbonClient(name = "travel-agency-service")
Quando a lista de endpoints for preenchida, o cliente Kubernetes pesquisará os endpoints registrados que vivem no namespace / projeto atual que corresponde ao nome do serviço definido usando a anotação@RibbonClient.
Também precisamos habilitar o cliente da faixa de opções nas propriedades do aplicativo:
ribbon.http.client.enabled=true
8. Características adicionais
8.1. Hystrix
Hystrixhelps in building a fault-tolerant and resilient application. Seus principais objetivos são falhas e recuperação rápida.
Em particular, em nosso exemplo, estamos usando Hystrix para implementar o padrão de disjuntor emclient-server anotando a classe de aplicativo Spring Boot com@EnableCircuitBreaker.
Além disso, estamos usando a funcionalidade de fallback, anotando o métodoTravelAgencyService.getDeals() com@HystrixCommand(). Isso significa que em caso de fallback ogetFallBackName() será chamado e a mensagem “Fallback” retornada:
@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. Indicador de integridade do pod
Podemos tirar proveito do Spring BootHealthIndicatoreSpring Boot Actuator para expor informações relacionadas à saúde para o usuário.
Em particular, o indicador de saúde Kubernetes fornece:
-
nome do pod
-
endereço de IP
-
namespace
-
conta de serviço
-
nome do nó
-
um sinalizador que indica se o aplicativo Spring Boot é interno ou externo ao Kubernetes
9. Conclusão
Neste artigo, fornecemos uma visão geral completa do projeto Spring Cloud Kubernetes.
Então, por que devemos usá-lo? Se torcemos pelo Kubernetes como uma plataforma de microsserviços, mas ainda apreciamos os recursos do Spring Cloud, o Spring Cloud Kubernetes nos oferece o melhor dos dois mundos.
O código-fonte completo do exemplo está disponívelover on GitHub.