Configurer son environnement de cloud avec Minikube, Kubernetes et Docker Compose en local (suite)
Chaque semaine, retrouvez sur notre blog un article relatif à notre série « Guide pratique dédié à la sécurisation d’une application Java Spring Boot et son déploiement dans le Cloud AWS ». L’objectif est de réaliser, pas à pas, la configuration d’un environnement sécurisé, la création d’une API et in fine, son déploiement dans le cloud.
Introduction
Pour rappel, la semaine dernière nous avons effectué les étapes nécessaires pour déployer une application Spring Boot sur un cluster Kubernetes local, en utilisant Minikube et Docker Compose. Nous avons notamment couvert la configuration initiale, la containerisation de l’application Spring Boot et le déploiement avec Kubernetes. Cet article est donc la suite de ce que nous avons commencé jeudi dernier. Aujourd’hui, nous allons aborder le déploiement continu (CI/CD), les tests, la surveillance des pods et la gestion des logs avec Grafana et Prometheus, tout en intégrant Keycloak pour la gestion des identités et des accès.
Pourquoi utiliser le cloud ?
Avant de passer à la configuration, rappelons rapidement pourquoi il est intéressant d’utiliser le cloud :
- Évolutivité : le cloud permet de redimensionner les ressources rapidement et facilement.
- Flexibilité : vous pouvez déployer vos applications partout dans le monde avec une simple commande. Vos utilisateurs peuvent ainsi bénéficier d’une expérience ultra-rapide, peu importe où ils se trouvent.
- Coût-efficacité : vous payez uniquement pour ce que vous utilisez. Pas besoin d’investir dans du matériel coûteux qui restera peut-être inutilisé la moitié du temps.
- Sécurité : les fournisseurs de cloud offrent des solutions de sécurité avancées, protégeant vos données contre les cybermenaces avec des mises à jour régulières et des protocoles de sécurité robustes.
- Automatisation : enfin, vous pouvez automatiser les tâches répétitives et fastidieuses avec des services comme CI/CD, qui garantissent des déploiements continus sans effort.
Déploiement Continu (CI/CD)
Passons dès à présent au premier point de cet article : le déploiement continu (CI/CD). Pour vous décrire son rôle simplement, c’est comme avoir un robot qui fait tout le travail pour vous, de la compilation du code à son déploiement en production. Cela améliore l’efficacité et réduit les risques d’erreurs humaines. Qui n’aimerait pas ça ?
Configuration d’un pipeline CI/CD
Création du fichier de workflow
La première étape de la configuration d’un pipeline CI/CD est la création d’un fichier de workflow avec la commande : .github/workflows/ci-cd-pipeline.yml. Ce fichier contiendra toutes les instructions que nos robots devront suivre pour automatiser le déploiement (voir ci-dessous).
Explications des termes importants :
- on: push: : ce bloc déclenche le workflow à chaque fois qu’il y a un push sur la branche main. Voyez cela comme un détecteur de mouvement pour votre code.
- jobs: build: : définit un job nommé build qui s’exécute sur une machine virtuelle ubuntu-latest. C’est votre robot principal.
- steps: : liste les différentes étapes que le robot doit suivre.
- actions/checkout@v2 : cette action permet au robot de récupérer le code source.
- actions/setup-java@v2 : le robot installe JDK 17, l’outil nécessaire pour construire votre application Java.
- mvn clean install : cette commande Maven compile votre application. Le robot assemble toutes les pièces pour créer votre chef-d’œuvre.
- docker build et docker push : ces commandes construisent et poussent une image Docker. Imaginez que le robot met votre application dans un conteneur de haute technologie prêt à être expédié.
- kubectl apply : cette commande déploie les ressources Kubernetes. Le robot place votre application dans son nouvel habitat dans le cluster Kubernetes.
Automatisation des tests :
Pour vous assurer que votre application fonctionne correctement, ajoutez une étape pour exécuter les tests avant de construire l’image Docker. Cela permet notamment à votre équipe de robots de vérifier chaque composant avant de l’assembler.
Configuration des secrets :
Les secrets Docker et Kubernetes sont ajoutés dans les secrets GitHub pour protéger vos informations sensibles. Voyez cela comme un coffre-fort sécurisé où vos robots gardent les clés.
Tests et surveillance des pods
Pour garantir que votre application fonctionne correctement en production, il est crucial de mettre en place des tests et des outils de surveillance. On peut voir cela comme un système d’alerte précoce pour repérer les bogues et les problèmes avant qu’ils ne deviennent critiques.
Configuration des tests pour les pods Kubernetes
Tests unitaires et d’intégration :
Les tests unitaires et d’intégration sont vos premières lignes de défense contre les bogues. Ils vérifient que chaque composant de votre application fonctionne correctement de manière isolée et en combinaison avec d’autres composants. Utilisez des frameworks de tests comme JUnit pour les tests unitaires et Spring Boot Test pour les tests d’intégration.
Exemple de test unitaire avec JUnit :
Explications des termes importants :
- @SpringBootTest : annotation indiquant que l’environnement de test doit démarrer avec la configuration Spring Boot complète. On peut voir cela comme une simulation de votre application dans un environnement sécurisé.
- @Test : annotation JUnit indiquant une méthode de test. C’est comme une tâche spécifique que votre robot doit vérifier.
- assertEquals : méthode JUnit pour vérifier que deux valeurs sont égales. Ici, c’est comme comparer deux plans pour s’assurer qu’ils correspondent exactement.
Surveillance des pods
Il faut garder à l’esprit que la surveillance des pods est essentielle pour garantir que votre application reste opérationnelle et performante en production. Utiliser des outils de surveillance permet donc de vérifier l’état de vos pods et détecter les problèmes potentiels avant qu’ils ne deviennent critiques.
Utilisation de kubectl :
Utilisez kubectl pour vérifier l’état des pods. Cette commande est votre terminal de diagnostic, ce qui donne un aperçu complet de la santé de votre application.
kubectl get pods
Exemple de vérification de l’état d’un pod spécifique :
kubectl describe pod <pod-name>
Explications des termes importants :
- kubectl get pods : cette commande permet de lister tous les pods dans le cluster Kubernetes.
- kubectl describe pod <pod-name> : cette commande permet d’obtenir des détails sur un pod spécifique, y compris son état et ses événements récents.
Utilisation de Grafana et Prometheus
Grafana et Prometheus sont comme les Tony Stark et Jarvis du monitoring et de la visualisation des métriques (vous avez la ref ?). Ils surveillent vos applications et infrastructures Kubernetes et affichent toutes les informations importantes sur des tableaux de bord stylisés. Voyons comment transformer vos données brutes en visualisations esthétiques et informatives.
Configuration des tests pour les pods Kubernetes
Création des fichiers Docker pour Prometheus et Grafana
- Dockerfile pour Prometheus
- Dockerfile pour Grafana
Fichier de configuration Prometheus (prometheus.yml) :
Explications des termes importants :
- FROM prom/prometheus:latest : indique l’image de base utilisée pour construire l’image Docker. C’est comme le choix du modèle de votre robot.
- ADD prometheus.yml /etc/prometheus/ : copie le fichier de configuration prometheus.yml dans le conteneur Docker. C’est comme charger le cerveau de votre robot avec des instructions spécifiques.
- scrape_interval : intervalle de temps entre deux collectes de métriques par Prometheus. Ici, c’est la fréquence à laquelle votre robot fait un rapport.
- targets : liste des endpoints que Prometheus surveille. Ce sont les systèmes que votre robot garde sous surveillance constante.
Création du fichier docker-compose.yml :
Pour déployer Prometheus et Grafana ensemble, nous utiliserons Docker Compose.
Explications des termes importants :
- version: ‘3.8’ : version du format de fichier docker-compose. C’est comme la version du logiciel qui contrôle vos robots.
- services : définit les services à déployer.
- prometheus : configuration du service Prometheus.
- build : chemin vers le Dockerfile. C’est l’atelier où votre robot est construit.
- ports : mapping des ports entre l’hôte et le conteneur. C’est comme configurer les ports de communication de votre robot.
- volumes : volumes montés pour la persistance des données. Voyez ça comme à la mémoire de votre robot.
- grafana : configuration du service Grafana.
- volumes : volume pour stocker les données Grafana.
- prometheus : configuration du service Prometheus.
Lancement des services avec Docker Compose :
Placez les fichiers Dockerfile et prometheus.yml dans les répertoires appropriés (./prometheus et ./grafana).
Exécutez la commande suivante pour lancer les services :
docker-compose up -d
Explications des termes importants :
- docker-compose up -d : cette commande permet de démarrer les services définis dans le fichier docker-compose en arrière-plan (-d pour détaché). C’est comme activer vos robots et les mettre en mode surveillance.
Déploiement de Grafana et Prometheus dans Kubernetes avec Minikube
Pour surveiller votre application dans Kubernetes, vous pouvez déployer Prometheus et Grafana directement dans le cluster.
Création des fichiers de déploiement Kubernetes pour Grafana et Prometheus
Fichier de déploiement pour Prometheus (prometheus-deployment.yaml) :
Commençons par configurer Prometheus, qui veillera sur les métriques de notre application.
Explications des termes importants :
- apiVersion : version de l’API Kubernetes utilisée.
- kind: Deployment : type de ressource Kubernetes.
- metadata : informations sur la ressource (nom, namespace). C’est l’identifiant unique de notre module de surveillance.
- spec : spécifications du déploiement.
- replicas : nombre de réplicas du pod. Nous avons une sentinelle en service, mais vous pouvez en avoir plusieurs pour plus de redondance.
- selector : sélecteur pour identifier les pods gérés par ce déploiement. Chaque sentinelle a un identifiant unique pour les reconnaître.
- template : modèle pour les pods.
- containers : définition des conteneurs dans le pod.
- name : nom du conteneur.
- image : image Docker utilisée. C’est l’apparence et les fonctionnalités de notre sentinelle.
- args : arguments passés au conteneur. Les instructions spécifiques que notre sentinelle doit suivre.
- volumeMounts : volumes montés dans le conteneur. C’est comme charger la base de données d’instructions.
- volumes : volumes utilisés par les pods. Les disques durs où nos sentinelles stockent leurs données.
- containers : définition des conteneurs dans le pod.
Fichier de service pour Prometheus (prometheus-service.yaml) :
Ensuite, nous définissons comment les autres systèmes peuvent communiquer avec Prometheus.
Explications des termes importants :
- kind: Service : type de ressource pour exposer les pods. C’est comme installer des antennes pour que Prometheus puisse communiquer avec d’autres modules.
- selector : sélecteur pour associer le service aux pods. Identifie les pods qui font partie de ce service.
- ports : ports exposés par le service. Les canaux de communication ouverts pour échanger des données.
Fichier de configMap pour Prometheus (prometheus-config.yaml) :
Le configMap définit les paramètres de configuration que notre sentinelle utilise pour collecter les données.
Explications des termes importants :
- kind: ConfigMap : type de ressource pour stocker des configurations non sensibles. C’est comme à un manuel d’instructions pour vos robots.
- data : données de configuration. Il s’agit des directives détaillées que Prometheus suit pour surveiller les métriques.
Fichier de déploiement pour Grafana (grafana-deployment.yaml) :
Passons à Grafana, notre outil de visualisation qui permet de voir les métriques collectées par Prometheus sous forme de tableaux de bord esthétiques et interactifs.
Explications des termes importants :
- type: NodePort : type de service exposant un port sur chaque nœud du cluster. C’est comme attribuer une porte d’entrée spécifique pour accéder à Grafana.
- nodePort : port spécifique exposé par le nœud. C’est la porte d’entrée de notre module de visualisation.
Déploiement dans Minikube
Il est temps de lancer notre mission ! Pour cela, appliquons les configurations pour déployer Prometheus et Grafana dans notre cluster Kubernetes. Lancez les commandes suivantes :
kubectl apply -f prometheus-config.yaml
kubectl apply -f prometheus-deployment.yaml
kubectl apply -f prometheus-service.yaml
kubectl apply -f grafana-deployment.yaml
Explications des termes importants :
- kubectl apply : commande pour appliquer une configuration sur un cluster Kubernetes. C’est comme donner des ordres à nos robots pour qu’ils se mettent en place et commencent leur surveillance.
Intégration de Keycloak pour la gestion des identités et des accès
Keycloak sécurise vos applications et services avec une efficacité redoutable. Est-il encore nécessaire de le rappeler ? Quoi qu’il en soit, pensez Keycloak comme un gardien, garantissant que seuls les utilisateurs autorisés peuvent entrer.
Configuration de Keycloak dans Docker Compose
Tout d’abord, commençons par jeter un coup d’œil à notre précédente configuration du fichier Docker Compose de l’application.
Explications des termes importants :
- DB_VENDOR, DB_ADDR, DB_DATABASE, DB_USER, DB_PASSWORD : variables d’environnement pour configurer la base de données PostgreSQL utilisée par Keycloak. C’est un peu comme une salle des archives, où toutes les informations importantes sont stockées.
- KEYCLOAK_USER, KEYCLOAK_PASSWORD : identifiants administrateur par défaut pour Keycloak.
Comment Keycloak gère-t-il les accès ?
Keycloak utilise OAuth2 et OpenID Connect pour gérer les accès aux ressources de votre application.
- OAuth2 : Keycloak délivre des tokens d’accès qui permettent aux utilisateurs d’accéder aux ressources sans révéler leurs mots de passe.
- OpenID Connect : extension d’OAuth2 qui ajoute une couche de gestion d’identité. Il permet à Keycloak de délivrer des tokens d’identité contenant des informations sur l’utilisateur.
Scénarios d’utilisation de Keycloak
Vous l’aurez compris au fil de ces épisodes, Keycloak est une solution puissante pour gérer les identités et les accès dans vos applications. Pour approfondir cet aspect, voici quelques scénarios où Keycloak peut véritablement transformer votre infrastructure de sécurité :
Centre de Commandement pour l’Authentification Unique (SSO) :
Keycloak permet un SSO fluide entre vos applications et services divers. Pour les applications Spring Boot, Keycloak agit comme le sage vieux conseiller qui connaît tous les visiteurs par leur nom (ou plutôt par leur token) en utilisant OpenID Connect.
Renforcement des microservices :
Chaque microservice est comme une tour de guet. Avec Keycloak, chaque tour a son propre garde qui vérifie les badges (tokens JWT) de tout le monde avant de les laisser entrer. Cela signifie que même si un intrus se faufile dans l’enceinte, il ne pourra pas accéder aux tours sans le bon badge.
L’API Gateway, le grand portail :
L’API Gateway agit comme le grand portail équipé de la technologie Keycloak. Avant que les requêtes n’atteignent les précieuses ressources de vos services en aval, elles doivent prouver leur valeur en présentant un token valide. C’est une façon de centraliser la défense, laissant vos services se concentrer sur leurs tâches sans se soucier des indésirables.
Naviguer avec agilité :
Utiliser Keycloak dans un environnement cloud hybride, c’est un peu comme avoir un réseau de téléporteurs entre différentes zones. Peu importe où vous êtes, cloud privé ou public, Keycloak assure que vos identités soient gérées uniformément, permettant une transition fluide et sécurisée pour tous vos utilisateurs.
Architecture à tolérance zéro
Avec Keycloak en jeu, adopter une architecture à tolérance zéro est comme équiper chaque garde d’une forteresse d’une vision thermique pour voir à travers les ruses des intrus. Chaque demande est scrutée et authentifiée avec rigueur, assurant que seuls les véritables alliés accèdent aux ressources.
Un royaume « Multi-tenancy »
Si votre application sert différents individus (tenants), Keycloak se positionne comme un médiateur. Il gère les accès en fonction du groupe auquel chaque utilisateur appartient. Cela permet une gestion des accès différenciée et efficace, maintenue par une instance centrale de Keycloak.
Les bonnes pratiques pour le développement et le déploiement en production
1. Sécurisez vos endpoints : utilisez OAuth2, JWT et Keycloak pour protéger vos API. La configuration de sécurité inclut des restrictions d’accès basées sur les rôles définis dans Keycloak.
2. Configurez des réplicas dans Kubernetes : pour assurer la scalabilité, configurez des réplicas dans vos fichiers de déploiement Kubernetes.
Exemple :
Explications des termes importants :
- replicas: 2 : nombre de réplicas du pod pour assurer la haute disponibilité.
3. Automatisez les déploiements : utilisez des pipelines CI/CD pour automatiser les déploiements et réduire les erreurs humaines. Assurez-vous que chaque changement dans le code déclenche automatiquement les tests et les déploiements.
4. Surveillance proactive : utilisez des outils comme Prometheus et Grafana pour surveiller en temps réel la santé et la performance de vos applications. Configurez des alertes pour être informé immédiatement de tout problème potentiel.
5. Gestion centralisée des identités : intégrez Keycloak pour gérer les identités et les accès de manière centralisée. Cela simplifie la gestion des utilisateurs et renforce la sécurité de votre application.
6. Backup régulier : assurez-vous de mettre en place des stratégies de sauvegarde régulières pour protéger vos données contre les pertes potentielles.
Options de configuration avec Kubernetes et Minikube
Kubernetes c’est un peu comme… le maître d’orchestre de la gestion des conteneurs. Au final, il permet de définir des déploiements, des services, des volumes et bien plus encore avec une grande précision. Du côté de Minikube, vous pouvez simuler un cluster Kubernetes sur votre propre machine pour effectuer des tests. Il offre une plateforme locale puissante pour expérimenter et affiner des configurations avant de les déployer à grande échelle.
Déploiements : avant toute chose, il faut définir des réplicas pour assurer la haute disponibilité.
Exemple de fichier YAML pour un déploiement avec réplicas :
Services : ensuite, il est nécessaire d’exposer les applications au réseau avec des LoadBalancers.
Ci-dessous, un exemple de fichier YAML pour un service de type LoadBalancer :
ConfigMaps et secrets : il est possible de gérer les configurations et les informations sensibles de manière sécurisée.
Ci-dessous, un exemple de fichier YAML pour un ConfigMap :
Voici également un exemple de fichier YAML pour un secret :
Tester en local avant le grand départ vers le cloud
Avant de déployer votre application sur des environnements Cloud comme AWS, nous vous conseillons d’abord de tester vos configurations en local en utilisant Minikube. Cela vous permettra notamment de détecter et de corriger les erreurs potentielles dans un environnement contrôlé, sans risquer des interruptions de service coûteuses. Pensez qu’en local, vous pouvez facilement itérer sur vos configurations, ajuster les ressources allouées et optimiser les performances.
Tests de charge : en premier lieu, vous pouvez vérifier le comportement de votre application sous différentes charges. Voici un exemple de commande pour exécuter un test de charge avec Apache Benchmark :
ab -n 1000 -c 10 http://localhost:8080/
Résilience des pods : il est intéressant d’ajuster les configurations des pods pour améliorer leur résilience. Pour ce faire, voici un exemple de fichier YAML pour configurer des probes de liveness et readiness :
Autoscaling : un autre test consiste à configurer des stratégies de mise à l’échelle automatique pour répondre dynamiquement à la demande. Ci dessous, un exemple de fichier YAML pour configurer un HorizontalPodAutoscaler :
Une fois vos configurations validées en local, vous pouvez migrer vers le Cloud avec confiance, en sachant que vos déploiements ont été rigoureusement testés.
Conclusion
Félicitations ! La session de configuration de l’environnement cloud avec Minikube, Kubernetes et Docker Compose en local est maintenant terminée. À ce stade, vous devriez avoir acquis une compréhension avancée du déploiement d’une application Spring Boot sur Kubernetes dans un environnement de production.
Pour rappel, nous avons couvert dans cet épisode la configuration d’un pipeline CI/CD, les tests et la surveillance des pods, la gestion des logs, et l’utilisation de Grafana et Prometheus pour le monitoring en utilisant Docker Compose et des fichiers de déploiement Kubernetes. Nous avons également intégré Keycloak pour la gestion des identités et des accès.
Au delà du cas pratique que nous vous proposons, suivre ces bonnes pratiques permet d’assurer que votre application est déployée de manière fiable et efficace avec une surveillance et une gestion appropriées pour répondre aux exigences de production. La semaine prochaine, nous clôturerons ce guide en déployant notre application Spring Boot dans le cloud.