Introduction
Dans cette partie du TP nous allons nous intéresser à un exemple de mise en œuvre d’une méthodologie de mise à jour d’une application de type “canari” (canary deployment), en utilisant Kubernetes via la plateforme GKE (Google Kubernetes Engine) déjà utilisée dans les exercices précédents.
Cette technique permet de mettre à jour les différentes instances de composants d’un service avec réplication (replicas) en offrant les propriétés suivantes :
-
éviter d’interrompre la disponibilité du service (pas d’arrêt total du service) ;
-
rediriger progressivement le trafic (requêtes applicatives) vers la ou les instances de la nouvelle version afin de limiter l’impact d’éventuels problèmes non anticipés introduits par la nouvelle version (et pouvoir facilement revenir intégralement à la version antérieure si nécessaire).
Nous allons illustrer cette méthodologie de manière simple et relativement manuelle mais notez qu’il est également possible d’utiliser des approches avec davantage d’automatisation (par exemple, pour l’augmentation progressive de la part du traffic attribuée à la nouvelle version ou pour l’annulation de la mise en jour en cas de détection de problème).
Cet exercice sera basé sur un tutoriel existant, assez ancien mais toujours pertinent pour illustrer les notions de base. Le tutoriel illustre succesivement deux façons (parmi d’autres) de faire un déploiement de canari(s). La première est basée sur l’utilisation d’un objet de type load balancer ; la seconde est basée sur l’utilisation d’un objet de type ingress.
!! ATTENTION !! Certaines étapes du tutoriel ci-dessous nécessitent des petites modifications car quelques commandes et formats/contenus de fichiers de configuration de Kubernetes ont évolué lors des dernières années.
Voici la la listes des différences/modifications à prendre en compte :
-
Le service GCR (Google Container Registry) (pour le stockage et la récupération d’images de conteneurs) est désormais déprécié et remplacé par un nouveau service nommé Artifact Registry, que vous avez déjà utilisé dans une partie précédente des TP (livraison continue). Il vous faudra donc adapter légèrement les parties basées sur GCR pour utiliser Artifact Registry à la place. (Reportez-vous au TP précédent pour les détails.)
-
Le contenu des fichiers utilisés pour tous les Deployments a évolué:
- Cela concerne les deux parties du TP :
- Pour la première partie (dossier
k8s/lb
) : fichiersapp-production.yml
etapp-canary.yml
- Pour la seconde partie (dossier
k8s/ingress
) : fichiersapp-production.yml
etapp-canary.yml
- Pour la première partie (dossier
- La version d’API à indiquer doit être
apiVersion: apps/v1
(au lieu deapiVersion: extensions/v1beta1
). - Il faut rajouter un selector correspondant au label (de la partie
template
) qui spécifie le nom de l’application. Concrêtement, cela se traduit par l’ajout de quelques lignes juste après le champreplicas
. Par exemple, vous trouverez ci-dessous la version modifiée (intégrale) du fichierapp-production.yml
utilisé dans la première partie du TP (dossierk8s/lb
). Attention : la chaîne de caractèresPROJECT_ID
devra être remplacée par l’identifiant de votre projet GCP, à l’aide de la commandesed
(comme indiqué à certaines étapes du tutoriel). (Pour plus d’informations sur le contenu de ces fichiers de configuration, vous pouvez éventuellement consulter la documentation concernant les Deployments.)
kind: Deployment apiVersion: apps/v1 metadata: name: kubeapp-production spec: replicas: 3 selector: matchLabels: app: kubeapp template: metadata: name: kubeapp labels: app: kubeapp env: production spec: containers: - name: kubeapp image: gcr.io/PROJECT_ID/app:1.0 imagePullPolicy: Always readinessProbe: httpGet: path: /health port: 8080 command: ["/app"] ports: - name: kubeapp containerPort: 8080
- Cela concerne les deux parties du TP :
-
le contenu des fichiers utilisés pour la gestion de l’Ingress (dans la 2ème partie du tutoriel, dossier
ingress
) a évolué. Plus précisément :-
Le contenu du fichier
app-ingress-production.yml
doit être modifié comme suit :kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: app-ingress spec: defaultBackend: service: name: kubeapp-production-service port: number: 80
-
Le contenu du fichier
app-ingress-canary.yml
doit être modifié comme suit :kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: app-ingress spec: defaultBackend: service: name: kubeapp-production-service port: number: 80 rules: - host: canary.foo.bar http: paths: - path: / pathType: Prefix backend: service: name: kubeapp-canary-service port: number: 80 - host: foo.bar http: paths: - path: / pathType: Prefix backend: service: name: kubeapp-production-service port: number: 80
-
Il est donc important de garder à l’esprit les avertissements ci-dessus au fil du tutoriel.
Travail à effectuer
Vous pouvez maintenant commencer le tutoriel en allant sur la page suivante : Kubernetes Canary deployments 🐤 for mere mortals
Important : Il est bien sûr demandé de comprendre et d’expliquer chaque étape (principe, commandes utilisées, contenu des fichiers de configuration, …).
Quelques précisions pouvr éviter d’éventuels malentendus :
-
Vous pouvez bien sûr igorer certaines étapes pratiques au tout début du TP, que vous avez déjà faites : création d’un projet GCP et configuration du compte de facturation, création d’un nouveau cluster GKE …
-
Notez que ce TP, comme les précédents, ne nécessite qu’un seul cluster GKE (sur lequel cohabiteront les différentes version de l’application: version courante et version canari). Vous pouvez conserver le cluster GKE que vous avez déjà (ou éventuellement le supprimer et en créer un nouveau).
-
Dans les fichiers de configuration associés aux Deployments (en l’occurrence
app-production.yml
etapp-canary.yml
), la ligneapiVersion: apps/v1
correspond à la version des API Kubernetes (pour ce type d’objet) sur laquelle le contenu des fichiers (champs, valeurs) est basé. Cela n’a rien à voir avec les numéros de version de l’application (version 1.0 pour la version initiale et version 2.0 pour les canaris). Il faut donc toujours conserverapiVersion: apps/v1
même pour les canaris. Le même genre de remarque s’applique également aux fichiers de configuration utilisés pour les objets de type “réseau” (loadBalancer et Ingress) : pour les fichiers correspondants, on doit toujours avoirapiVersion: networking.k8s.io/v1
, même pour les configurations avec canaris. -
Le tutoriel n’utilise qu’un seul namespace nommé “production”, (par opposition à d’autres phases/besoins comme “staging”, “test”, etc.) pour l’ensemble des manipulations. Notez bien que tous les pods sont ici déployés dans le même namespace : les pods de la version initiale/stable (associée à
app-production.yml
) mais aussi les pods de la version canari (associée àapp-canary.yml
). Autrement dit, les canaris sont également déployés en production (c’est même leur but).
Pour aller plus loin avec les canary deployments (facultatif)
Pour approfondir le sujet, vous pouvez considérer l’une des pistes suivantes, ou les deux :
- Canary deployment using Ingress NGINX Controller. L’un des intérêts de cette mise en œuvre est de pouvoir facilement configurer (et ajuster dynamiquement) la proportion de requêtes aiguillés vers le(s) canari(s). Pour plus de détails, voir aussi les documentations suivantes :
- Canary deployments dans un contexte de CI/CD avec Gitlab