Déploiement continu sur Kubernetes Engine à l'aide de Jenkins

Ce tutoriel explique comment configurer un pipeline de distribution continue avec Jenkins et GKE, comme décrit dans le schéma suivant.

architecture de déploiement continu Jenkins

Objectifs

  • Comprendre un exemple d'application
  • Déployer une application sur Kubernetes
  • 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 fait appel à des composants payants de Google Cloud Platform (GCP), y compris :

  • Compute Engine
  • 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

  1. Connectez-vous à votre compte Google.

    Si vous n'en possédez pas déjà un, vous devez en créer un.

  2. Sélectionnez ou créez un projet Google Cloud Platform.

    Accéder à la page "Gérer les ressources"

  3. Assurez-vous que la facturation est activée pour votre projet Google Cloud Platform.

    Découvrir comment activer la facturation

  4. Activez Compute Engine, Kubernetes Engine, and Cloud Buildles API requises.

    Activer les API.

Préparer l'environnement

  1. Suivez le tutoriel de configuration de Jenkins sur GKE.

  2. Dans Cloud Shell, accédez au répertoire de l'exemple d'application.

    cd continuous-deployment-on-kubernetes/sample-app
    

Comprendre l'application

Vous allez déployer l'exemple d'application gceme dans votre pipeline de déploiement continu. Cette application est codée 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, elle affiche les métadonnées de cette dernière dans une fiche d'informations.

carte d'informations gceme

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 service backend gceme et affiche dans l'interface utilisateur le fichier JSON ainsi obtenu.

architecture gceme

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é est OK 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.

  1. Créez l'espace de noms Kubernetes pour isoler logiquement le déploiement de production.

    kubectl create ns production
    
  2. 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
    
  3. Augmentez le nombre d'interfaces dans l'environnement de production.

    kubectl --namespace=production scale deployment gceme-frontend-production --replicas=4
    
  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
    

  5. 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)
    
  6. Afin de vérifier que les deux services fonctionnent, ouvrez l'adresse IP externe de l'interface dans votre navigateur.

  7. 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 et placez-la dans Google Cloud Repositories.

  1. Créez le dépôt dans Cloud Source Repositories.

    gcloud source repos create gceme
    
  2. 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
    
  3. Définissez le nom d'utilisateur et l'adresse e-mail des commits Git de ce dépôt.

    git config --global user.email "[EMAIL_ADDRESS]"
    

    Remplacez [EMAIL_ADDRESS] par votre adresse e-mail Git.

    git config --global user.name "[USERNAME]"
    

    Remplacez [USERNAME] par votre nom d'utilisateur Git.

  4. Ajoutez, validez par un commit et transférez les fichiers.

    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.

  1. Dans l'interface utilisateur Jenkins, cliquez sur Credentials (Identifiants) dans la zone de navigation de gauche.
  2. Cliquez sur le lien Jenkins dans la table Credentials (Identifiants).

    Groupes d'identifiants Jenkins

  3. Cliquez sur Global Credentials (Identifiants globaux).

  4. Cliquez sur Add Credentials (Ajouter des identifiants) dans la zone de navigation de gauche.
  5. Sélectionnez Google Service Account from metadata (Compte de service Google à partir de métadonnées) dans le menu déroulant Kind (Genre).
  6. 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.

Identifiants Jenkins

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.

  1. Cliquez sur le lien Jenkins en haut à gauche de l'interface.

  2. Cliquez sur le lien New Item (Nouvel élément) dans la zone de navigation de gauche.

  3. Nommez le projet sample-app, sélectionnez l'option Multibranch Pipeline (Pipeline multibranche), puis cliquez sur OK.

  4. Sur la page suivante, cliquez sur Add source (Ajouter une source) et sélectionnez git.

  5. Collez l'adresse HTTPS clone URL (URL de clone HTTPS) du dépôt sample-app dans Cloud Source Repositories dans le champ Project Repository (Dépôt du projet), en remplaçant [PROJECT_ID] par l'ID de votre projet :

    https://source.developers.google.com/p/[PROJECT_ID]/r/gceme
    
  6. Dans le menu déroulant Credentials (Identifiants), sélectionnez le nom des identifiants que vous avez créés lors de l'ajout du compte de service.

  7. 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".

  8. Cliquez sur Save (Enregistrer).

    Créer des paramètres de tâche Jenkins

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é dans votre parc entier de modules.

  1. Ouvrez html.go et remplacez les deux apparitions de blue par orange.
  2. Ouvrez main.go et remplacez le numéro de version 1.0.0 par 2.0.0.

     const version string = "2.0.0"
    
  3. 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"
    
  4. Enfin, appliquez vos modifications sur le serveur Git distant.

     git push origin canary
    
  5. 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 build a été lancé.

    Premier écran de build Jenkins

  6. Lorsque la compilation s'exécute, cliquez sur la flèche vers le bas à côté du build dans le menu de navigation à gauche, puis sélectionnez Console output (Résultat de la console).

    Console de navigation Jenkins

  7. Attendez quelques minutes pour voir apparaître les premiers messages kubectl --namespace=production apply... dans la sortie du build. Quand ils commencent à apparaître, consultez le terminal qui interrogeait l'URL /version de production et observez les modifications commencer à apparaître dans certaines requêtes. Vous avez maintenant déployé cette modification à un sous-ensemble d'utilisateurs.

  8. 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
    
  9. Au bout d'environ une minute, la tâche master du dossier sample-app est lancée.

    Tâche maître Jenkins

  10. Cliquez sur le lien master pour voir les étapes de votre pipeline, ainsi que les informations de réussite/échec et les caractéristiques de minutage.

    Production de pipeline Jenkins

  11. 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.

  1. 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.

  1. Démarrez le proxy en arrière-plan.

    kubectl proxy &
    
  2. Vérifiez que votre application est accessible en utilisant localhost.

    curl http://localhost:8001/api/v1/proxy/namespaces/new-feature/services/gceme-frontend:80/
    
  3. 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
    
  4. 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 branche master pour lancer le déploiement.

    git checkout master
    git merge canary
    git push origin master
    
  5. 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

Afin d'éviter que des frais ne soient facturés sur votre compte Google Cloud Platform pour les ressources utilisées dans ce tutoriel, procédez comme suit :

Supprimer le projet

Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé dans le cadre de ce tutoriel.

Pour supprimer le projet, procédez comme suit :

  1. Dans la console GCP, accédez à la page "Projets".

    Accéder à la page Projets

  2. Dans la liste des projets, sélectionnez celui que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Étapes suivantes

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…