Ce tutoriel explique comment configurer un pipeline de livraison continue à l'aide de Jenkins et de Google Kubernetes Engine (GKE), comme décrit dans le schéma suivant.
Objectifs
- Comprendre un exemple d'application
- Déployer une application sur GKE
- Importer du code dans Cloud Source Repositories
- Créer des pipelines de déploiement dans Jenkins
- Déployer des environnements de développement
- Déployer une version Canary
- Déployer des environnements de production
Coûts
Ce tutoriel utilise des composants facturables de Google Cloud, dont :
- Instance
- Google Kubernetes Engine
- Cloud Build
Utilisez le simulateur de coût pour générer une estimation des coûts en fonction de l'utilisation que vous prévoyez pour ce tutoriel. Les nouveaux utilisateurs de GCP peuvent bénéficier d'un essai gratuit.
Avant de commencer
- Connectez-vous à votre compte Google.
Si vous n'en possédez pas déjà un, vous devez en créer un.
-
Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.
-
Assurez-vous que la facturation est activée pour votre projet Cloud. Découvrez comment vérifier que la facturation est activée pour votre projet.
- Activer les API Compute Engine, GKE, and Cloud Build.
Préparer l'environnement
Suivez le tutoriel de configuration de Jenkins sur GKE. Assurez-vous de disposer d'une installation Jenkins opérationnelle s'exécutant dans GKE.
Dans Cloud Shell, clonez l'exemple de code :
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes cd continuous-deployment-on-kubernetes/sample-app
Attribuez le rôle
cluster-admin
au compte de service Jenkins :kubectl create clusterrolebinding jenkins-deploy \ --clusterrole=cluster-admin --serviceaccount=default:cd-jenkins
Dans ce tutoriel, le compte de service Jenkins nécessite les autorisations
cluster-admin
pour pouvoir créer des espaces de noms Kubernetes ainsi que les autres ressources requises par l'application. Pour une utilisation en production, vous devez cataloguer les autorisations individuelles nécessaires et les attribuer une par une au compte de service.
Comprendre l'application
Vous allez déployer l'exemple d'application gceme
dans votre pipeline de déploiement continu. L'application est écrite en langage Go et se situe dans le répertoire sample-app
du dépôt. Lorsque vous exécutez le binaire gceme
sur une instance Compute Engine, l'application affiche les métadonnées de l'instance dans une carte d'informations.
L'application s'apparente à un microservice proposant deux modes de fonctionnement :
En mode backend,
gceme
écoute le port 8080 et renvoie les métadonnées de l'instance Compute Engine au format JSON.En mode interface,
gceme
interroge le servicegceme
de backend et affiche dans l'interface utilisateur le fichier JSON ainsi obtenu.
Les modes interface et backend sont compatibles avec deux URL supplémentaires :
/version
affiche la version en cours d'exécution./healthz
indique l'état de l'application. En mode interface, l'état affiché estOK
si le backend est accessible.
Déployer l'exemple d'application sur Kubernetes
Déployez l'interface et le backend de gceme
sur Kubernetes à l'aide de fichiers manifestes décrivant l'environnement de déploiement. Les fichiers utilisent une image par défaut qui sera mise à jour plus loin dans ce tutoriel.
Déployez les applications dans deux environnements.
Production : site actif auquel vos utilisateurs accèdent.
Canary : site de moindre capacité recevant une partie du trafic utilisateur. Cet environnement vous permet d'évaluer l'intégrité de votre logiciel avec du trafic en temps réel, avant de le publier sur l'environnement en ligne.
Commencez par déployer l'application dans l’environnement de production afin d'alimenter le pipeline avec du code fonctionnel.
Créez l'espace de noms Kubernetes pour isoler logiquement le déploiement de production :
kubectl create ns production
Créez les déploiements et les services Canary et de production :
kubectl --namespace=production apply -f k8s/production kubectl --namespace=production apply -f k8s/canary kubectl --namespace=production apply -f k8s/services
Augmentez le nombre d'interfaces dans l'environnement de production :
kubectl --namespace=production scale deployment gceme-frontend-production --replicas=4
Récupérez l'adresse IP externe des services de production. L'affichage de l'adresse IP de l'équilibreur de charge peut prendre quelques minutes.
kubectl --namespace=production get service gceme-frontend
Une fois le processus terminé, une adresse IP apparaît dans la colonne
EXTERNAL-IP
.NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gceme-frontend LoadBalancer 10.35.254.91 35.196.48.78 80:31088/TCP 1m
Enregistrez l'adresse IP de l'équilibreur de charge du service d'interface dans une variable d'environnement :
export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
Afin de vérifier que les deux services fonctionnent, ouvrez l'adresse IP externe de l'interface dans votre navigateur.
Ouvrez un terminal distinct et interrogez l'URL
/version
du point de terminaison de production afin de pouvoir observer les mises à jour progressives dans la section suivante :while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1; done
Créer un dépôt pour héberger le code source de l'exemple d'application
Créez maintenant une copie de l'exemple d'application gceme
, puis transférez-la vers Cloud Source Repositories.
Créez le dépôt dans Cloud Source Repositories :
gcloud source repos create gceme
Initialisez le dépôt Git local :
git init git config credential.helper gcloud.sh export PROJECT_ID=$(gcloud config get-value project) git remote add origin https://source.developers.google.com/p/$PROJECT_ID/r/gceme
Définissez le nom d'utilisateur et l'adresse e-mail des commits Git de ce dépôt. Remplacez
[EMAIL_ADDRESS]
par votre adresse e-mail Git et[USERNAME]
par votre nom d'utilisateur Git.git config --global user.email "[EMAIL_ADDRESS]" git config --global user.name "[USERNAME]"
Ajoutez les fichiers, validez-les par un commit et transférez-les :
git add . git commit -m "Initial commit" git push origin master
Créer un pipeline
Utilisez Jenkins pour définir et exécuter un pipeline permettant de tester, créer et déployer votre copie de gceme
sur votre cluster Kubernetes.
Ajouter les identifiants du compte de service
Configurez vos identifiants de sorte que Jenkins puisse accéder au dépôt de code.
- Dans l'interface utilisateur Jenkins, cliquez sur Credentials (Identifiants) dans la zone de navigation de gauche.
Cliquez sur le lien Jenkins dans la table Credentials (Identifiants).
Cliquez sur Global Credentials (Identifiants globaux).
Cliquez sur Ajouter des identifiants dans la zone de navigation de gauche.
Sélectionnez Google Service Account from metadata (Compte de service Google à partir de métadonnées) dans le menu déroulant Kind (Genre).
Cliquez sur OK.
Il existe maintenant deux identifiants globaux. Notez le nom du deuxième identifiant pour pouvoir l'utiliser plus loin dans ce tutoriel.
Créer une tâche Jenkins
Utilisez maintenant la fonctionnalité de pipeline Jenkins pour configurer le pipeline de build. Les fichiers de pipeline Jenkins sont écrits dans une syntaxe semblable à Groovy.
Dans l'interface utilisateur de Jenkins, suivez les étapes ci-dessous pour configurer une tâche de pipeline.
- Cliquez sur le lien Jenkins en haut à gauche de l'interface.
- Cliquez sur le lien New Item (Nouvel élément) dans la zone de navigation de gauche.
- Nommez le projet sample-app, sélectionnez l'option Multibranch Pipeline (Pipeline multibranche), puis cliquez sur OK.
- Sur la page suivante, cliquez sur Add source (Ajouter une source) et sélectionnez git.
Collez l'adresse HTTPS clone URL (URL de clone HTTPS) du dépôt
sample-app
de Cloud Source Repositories dans le champ Project Repository (Dépôt du projet). Remplacez[PROJECT_ID]
par l'ID du projet.https://source.developers.google.com/p/[PROJECT_ID]/r/gceme
Dans la liste déroulante Credentials (Identifiants), sélectionnez le nom des identifiants que vous avez créés lors de l'ajout du compte de service.
Dans la section Scan Multibranch Pipeline (Analyser le pipeline multibranche), cochez la case Periodically if not otherwise run (Périodiquement, s'il ne s'exécute pas autrement). Définissez la valeur Interval (Intervalle) sur "1 minute".
Cliquez sur Save (Enregistrer).
Une fois que vous avez suivi ces étapes, une tâche nommée "Branch indexing" (Indexation des branches) s'exécute.
Il s'agit d'une métatâche qui identifie les branches de votre dépôt et vérifie qu'aucune modification n'a été introduite dans les branches existantes. Si vous actualisez Jenkins, la branche master
affiche cette tâche.
La première exécution de la tâche échouera tant que vous n'aurez pas apporté les quelques modifications de code demandées à l'étape suivante.
Modifier la définition du pipeline
Créez une branche pour l'environnement Canary, appelée canary
.
git checkout -b canary
Le conteneur Jenkinsfile qui définit ce pipeline est écrit dans la syntaxe Groovy de pipeline Jenkins. Tout un pipeline de build peut ainsi être défini dans un seul fichier Jenkinsfile qui accompagne votre code source. Les pipelines offrent des fonctionnalités extrêmement utiles telles que le chargement en parallèle, et ils requièrent l'approbation manuelle de l'utilisateur.
Modifiez le fichier Jenkinsfile afin qu'il contienne l'ID du projet à la ligne 1.
Déployer une version Canary
Maintenant que le pipeline est configuré correctement, il est temps de modifier l'application gceme
et de laisser votre pipeline la tester, l'empaqueter et la déployer.
L'environnement Canary est configuré comme une version Canary.
Ainsi, votre modification est transmise à un petit pourcentage de modules situés derrière l'équilibreur de charge de production. Vous effectuez cela dans Kubernetes en gérant plusieurs déploiements partageant les mêmes libellés. Pour cette application, les services gceme-frontend
équilibrent leur charge sur tous les pods portant les libellés app: gceme
et role: frontend
. Le fichier manifeste Canary k8s/frontend-canary.yaml
définit les instances dupliquées sur 1
et inclut les libellés requis pour le service gceme-frontend
.
Actuellement, un des cinq modules d'interface exécute le code Canary, tandis que les quatre autres exécutent le code de production. Cela aide à garantir que le code Canary n'a pas d'impact négatif sur les utilisateurs avant d'être déployé sur l'ensemble des pods.
- Ouvrez
html.go
et remplacez les deux occurrences deblue
parorange
. Ouvrez
main.go
et remplacez le numéro de version1.0.0
par2.0.0
:const version string = "2.0.0"
Ensuite, ajoutez ces fichiers à votre dépôt local et validez-les par un commit :
git add Jenkinsfile html.go main.go git commit -m "Version 2"
Enfin, appliquez vos modifications sur le serveur Git distant :
git push origin canary
Une fois la modification transférée dans le dépôt Git, accédez à l'interface utilisateur de Jenkins. Celle-ci indique que votre compilation a été lancée.
Lorsque la compilation s'exécute, cliquez sur la flèche vers le bas correspondant à cette compilation dans le menu de navigation situé à gauche, puis sélectionnez Console output (Résultat de la console) :
Attendez quelques minutes pour voir apparaître les premiers messages
kubectl --namespace=production apply...
dans le résultat du build. Quand ceux-ci commencent à apparaître, consultez le terminal qui interrogeait l'URL/version
de production et observez les modifications qui se produisent dans certaines requêtes. Vous avez maintenant déployé cette modification à un sous-ensemble d'utilisateurs.Une fois que la modification a été déployée dans l'environnement Canary, vous pouvez continuer à la déployer pour le reste de vos utilisateurs en fusionnant le code avec la branche
master
et en transférant le tout sur le serveur Git :git checkout master git merge canary git push origin master
Au bout d'une minute environ, la tâche
master
du dossiersample-app
est lancée.Cliquez sur le lien
master
pour afficher les étapes du pipeline, ainsi que les informations de réussite/échec et les durées associées.Interrogez l'URL de production pour vérifier que la nouvelle version 2.0.0 a été déployée et qu'elle traite les requêtes de tous les utilisateurs.
export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend) while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1; done
Vous pouvez consulter le fichier Jenkinsfile dans le projet pour voir le workflow.
Déployer une branche de développement
Parfois, vous devez gérer des modifications concrètes qui ne peuvent pas être appliquées directement à l'environnement Canary. Une branche de développement est un ensemble d'environnements dans lesquels vos développeurs testent les modifications qu'ils apportent au code avant de les soumettre pour intégration dans le site en ligne. Ces environnements sont des versions réduites de votre application, mais ils sont déployés avec les mêmes mécanismes que l'environnement en ligne.
Pour créer un environnement de développement à partir d'une branche de fonctionnalités, vous pouvez transférer la branche en question vers le serveur Git et laisser à Jenkins le soin de déployer votre environnement. Dans un scénario de développement, vous n'utiliseriez pas un équilibreur de charge public. Vous pouvez sécuriser votre application avec le proxy kubectl. Ce proxy s'authentifie auprès de l'API Kubernetes et traite les demandes envoyées de votre machine locale au service dans le cluster sans exposer votre service à Internet.
Créez une autre branche et transmettez-la au serveur Git :
git checkout -b new-feature git push origin new-feature
Une nouvelle tâche est créée et votre environnement de développement est alors en cours de création. Au bas du résultat de tâche de la console se trouvent des instructions vous indiquant comment accéder à votre environnement.
Démarrez le proxy en arrière-plan :
kubectl proxy &
Vérifiez que votre application est accessible à l'aide de localhost :
curl http://localhost:8001/api/v1/namespaces/new-feature/services/gceme-frontend:80/proxy/
Vous pouvez maintenant transmettre du code à cette branche pour mettre à jour votre environnement de développement. Lorsque vous avez terminé, fusionnez à nouveau votre branche dans
canary
pour déployer ce code dans l'environnement Canary.git checkout canary git merge new-feature git push origin canary
Lorsque vous êtes certain que votre code ne causera aucun problème dans l'environnement de production, fusionnez la branche
canary
au sein de la branchemaster
pour lancer le déploiement :git checkout master git merge canary git push origin master
Lorsque vous en avez terminé avec la branche de développement, supprimez-la du serveur et supprimez l'environnement de votre cluster Kubernetes :
git push origin :new-feature kubectl delete ns new-feature
Nettoyer
Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.
Supprimer le projet
Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé pour ce tutoriel.
Pour supprimer le projet :
- Dans Cloud Console, accédez à la page Gérer les ressources.
- Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
- Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.
Étape suivante
- Découvrez les bonnes pratiques relatives à Jenkins sur GKE.
- Consultez le tutoriel de configuration de Jenkins sur GKE.
- Apprenez à configurer Jenkins pour GKE.
- Testez d'autres fonctionnalités de Google Cloud. Découvrez nos tutoriels.