Guide de Spring Cloud Kubernetes

1. Vue d'ensemble

Lorsque nous développons une solution de microservices, Spring Cloud et Kubernetes sont des solutions optimales, car ils fournissent des composants pour résoudre les défis les plus courants. Cependant, si nous décidons de choisir Kubernetes comme principal gestionnaire de conteneurs et plate-forme de déploiement pour notre solution, nous pouvons toujours utiliser les fonctionnalités intéressantes de Spring Cloud principalement via le projet Spring Cloud Kubernetes.

Ce projet relativement nouveau fournit sans aucun doute une intégration facile avec Kubernetes pour les applications Spring Boot. Avant de commencer, il peut être utile de voir comment déployer une application Spring Boot sur Minikube, un environnement Kubernetes local .

Dans ce tutoriel, nous allons:

  • Installez Minikube sur notre machine locale
  • Développer un exemple d'architecture de microservices avec deux applications Spring Boot indépendantes communiquant via REST
  • Configurer l'application sur un cluster à un nœud à l'aide de Minikube
  • Déployer l'application à l'aide des fichiers de configuration YAML

2. Scénario

Dans notre exemple, nous utilisons le scénario d'agents de voyages proposant diverses offres à des clients qui interrogeront le service d'agents de voyages de temps en temps. Nous allons l'utiliser pour démontrer:

  • découverte de services via Spring Cloud Kubernetes
  • gestion de la configuration et injection de Kubernetes ConfigMaps et secrets aux pods d'application à l'aide de Spring Cloud Kubernetes Config
  • équilibrage de charge à l' aide du ruban Spring Cloud Kubernetes

3. Configuration de l'environnement

Tout d'abord, nous devons installer Minikube sur notre machine locale et de préférence un pilote VM tel que VirtualBox. Il est également recommandé de regarder Kubernetes et ses principales fonctionnalités avant de suivre la configuration de cet environnement.

Commençons par le cluster Kubernetes à nœud unique local:

minikube start --vm-driver=virtualbox

Cette commande crée une machine virtuelle qui exécute un cluster Minikube à l'aide du pilote VirtualBox. Le contexte par défaut dans kubectl sera désormais minikube . Cependant, pour pouvoir basculer entre les contextes, nous utilisons:

kubectl config use-context minikube

Après avoir démarré Minikube, nous pouvons nous connecter au tableau de bord Kubernetes pour accéder aux journaux et surveiller nos services, pods, ConfigMaps et Secrets facilement:

minikube dashboard 

3.1. Déploiement

Tout d'abord, prenons notre exemple de GitHub.

À ce stade, nous pouvons soit exécuter le script «deployment-travel-client.sh» depuis le dossier parent, soit exécuter chaque instruction une par une pour bien comprendre la procédure:

### 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. Découverte des services

Ce projet nous fournit une implémentation de l' interface ServiceDiscovery dans Kubernetes. Dans un environnement de microservices, plusieurs pods exécutent généralement le même service. Kubernetes expose le service comme une collection de points de terminaison pouvant être récupérés et atteints à partir d'une application Spring Boot s'exécutant dans un pod du même cluster Kubernetes.

Par exemple, dans notre exemple, nous avons plusieurs répliques du service d'agent de voyages, accessible depuis notre service client en tant que // service -agence-de-voyage: 8080 . Cependant, cela se traduirait en interne par l'accès à différents pods tels que travel-agency-service-7c9cfff655-4hxnp .

Le ruban Spring Cloud Kubernetes utilise cette fonctionnalité pour équilibrer la charge entre les différents points de terminaison d'un service.

Nous pouvons facilement utiliser Service Discovery en ajoutant la dépendance spring-cloud-starter-kubernetes à notre application cliente:

 org.springframework.cloud spring-cloud-starter-kubernetes 

En outre, nous devons ajouter @EnableDiscoveryClient et injecter le DiscoveryClient dans le ClientController en utilisant @Autowired dans notre 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

En règle générale, les microservices nécessitent une sorte de gestion de la configuration . Par exemple, dans les applications Spring Cloud, nous utiliserions un serveur Spring Cloud Config.

Cependant, nous pouvons y parvenir en utilisant ConfigMaps fournis par Kubernetes - à condition que nous ayons l'intention de l'utiliser uniquement pour des informations non sensibles et non chiffrées. Alternativement, si les informations que nous souhaitons partager sont sensibles, nous devrions opter pour l'utilisation de Secrets à la place.

Dans notre exemple, nous utilisons ConfigMaps sur l' application Spring Boot du service client . Créons un client-config. yaml pour définir le ConfigMap du client-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

Il est important que le nom du ConfigMap corresponde au nom de l'application tel que spécifié dans notre fichier «application.properties». Dans ce cas, c'est le service client . Ensuite, nous devons créer le ConfigMap pour le service client sur Kubernetes:

kubectl create -f client-config.yaml

Maintenant, créons une classe de configuration ClientConfig avec @Configuration et @ConfigurationProperties et injectons-la dans ClientController :

@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(), "", ""); } }

Si nous ne spécifions pas de ConfigMap, nous devrions nous attendre à voir le message par défaut, qui est défini dans la classe. Cependant, lorsque nous créons le ConfigMap, ce message par défaut est remplacé par cette propriété.

Additionally, every time we decide to update the ConfigMap, the message on the page changes accordingly:

kubectl edit configmap client-service

6. Secrets

Let's look at how Secrets work by looking at the specification of MongoDB connection settings in our example. We're going to create environment variables on Kubernetes, which will then be injected into the Spring Boot application.

6.1. Create a Secret

The first step is to create a secret.yaml file, encoding the username and password to Base 64:

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

Let's apply the Secret configuration on the Kubernetes cluster:

kubectl apply -f secret.yaml

6.2. Create a MongoDB Service

We should now create the MongoDB service and the deployment travel-agency-deployment.yaml file. In particular, in the deployment part, we'll use the Secret username and password that we defined previously:

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

By default, the mongo:latest image will create a user with username and password on a database named admin.

6.3. Setup MongoDB on Travel Agency Service

It's important to update the application properties to add the database related information. While we can freely specify the database name admin, here we're hiding the most sensitive information such as the username and the password:

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}

Now, let's take a look at our travel-agency-deployment property file to update the services and deployments with the username and password information required to connect to the mongodb-service.

Here's the relevant section of the file, with the part related to the MongoDB connection:

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

7. Communication with Ribbon

In a microservices environment, we generally need the list of pods where our service is replicated in order to perform load-balancing. This is accomplished by using a mechanism provided by Spring Cloud Kubernetes Ribbon. This mechanism can automatically discover and reach all the endpoints of a specific service, and subsequently, it populates a Ribbon ServerList with information about the endpoints.

Let's start by adding the spring-cloud-starter-kubernetes-ribbon dependency to our client-service pom.xml file:

 org.springframework.cloud spring-cloud-starter-kubernetes-ribbon 

The next step is to add the annotation @RibbonClient to our client-service application:

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

When the list of the endpoints is populated, the Kubernetes client will search the registered endpoints living in the current namespace/project matching the service name defined using the @RibbonClient annotation.

We also need to enable the ribbon client in the application properties:

ribbon.http.client.enabled=true

8. Additional Features

8.1. Hystrix

Hystrix helps in building a fault-tolerant and resilient application. Its main aims are fail fast and rapid recovery.

In particular, in our example, we're using Hystrix to implement the circuit breaker pattern on the client-server by annotating the Spring Boot application class with @EnableCircuitBreaker.

Additionally, we're using the fallback functionality by annotating the method TravelAgencyService.getDeals() with @HystrixCommand(). This means that in case of fallback the getFallBackName() will be called and “Fallback” message returned:

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

8.2. Pod Health Indicator

We can take advantage of Spring Boot HealthIndicator and Spring Boot Actuator to expose health-related information to the user.

In particular, the Kubernetes health indicator provides:

  • pod name
  • IP address
  • namespace
  • service account
  • node name
  • un indicateur qui indique si l'application Spring Boot est interne ou externe à Kubernetes

9. Conclusion

Dans cet article, nous fournissons un aperçu complet du projet Spring Cloud Kubernetes.

Alors pourquoi devrions-nous l'utiliser? Si nous recherchons Kubernetes en tant que plate-forme de microservices tout en appréciant les fonctionnalités de Spring Cloud, Spring Cloud Kubernetes nous offre le meilleur des deux mondes.

Le code source complet de l'exemple est disponible à l'adresse over sur GitHub.