Apprenez à construire un pipeline CI/CD fiable pour les déploiements Kubernetes avec des vérifications de déploiement sécurisées, une validation automatisée et un retour arrière rapide. Ce guide couvre les prérequis, la mise en œuvre étape par étape, les commandes de vérification, les modes de défaillance et une liste de contrôle opérationnelle, avec des exemples pratiques que vous pouvez adapter à votre cluster.
Introduction
Les déploiements Kubernetes gèrent le cycle de vie de vos pods d'application, offrant des mises à jour déclaratives, une mise à l'échelle et un retour arrière. Mais appliquer manuellement des fichiers YAML en espérant que tout se passe bien est risqué. L'automatisation CI/CD apporte la répétabilité, la sécurité et la rapidité à votre processus de publication. Ce guide vous accompagne dans la construction d'un pipeline CI/CD pratique pour les déploiements Kubernetes, de la configuration de l'environnement aux vérifications automatisées du déploiement et aux procédures de retour arrière. Vous apprendrez à vérifier le comportement de votre pipeline, à diagnostiquer les défaillances et à établir une liste de contrôle opérationnelle qui maintient la fiabilité de vos versions.
À la fin de ce guide, vous disposerez de :
- Un flux de travail de déploiement automatisé et versionné utilisant GitHub Actions (ou votre outil CI/CD préféré)
- Un déploiement Kubernetes configuré avec des mises à jour progressives, des sondes de santé et des limites de ressources
- Des étapes de vérification servant de barrières de qualité avant la promotion en production
- Un plan documenté de récupération en cas d'échec et de retour arrière
- Une liste de contrôle opérationnelle pour maintenir la cohérence entre les versions
Inventaire des versions et de l'environnement
Avant d'automatiser, confirmez les versions de votre chaîne d'outils et la topologie du cluster. Les incohérences de versions sont une source courante de défaillances de pipeline. Cette section répertorie les composants requis et une disposition minimale du cluster.
Prérequis :
- Cluster Kubernetes v1.19 ou ultérieur (recommandé pour un comportement kubectl stable et une compatibilité API)
- CLI kubectl v1.19+ installé et configuré pour atteindre votre cluster
- Accès à un registre de conteneurs (par exemple, Docker Hub, Google Container Registry, Amazon ECR)
- Une plateforme CI/CD (GitHub Actions, GitLab CI, Jenkins ou similaire)
- Code source de l'application avec un Dockerfile
- Un espace de noms dédié aux tests (nous en créerons un dans la section suivante)
Exécutez cette vérification de version pour confirmer la compatibilité :
kubectl version --short
# Sortie attendue :
# Client Version: v1.24.0
# Server Version: v1.24.0
Si les versions client et serveur diffèrent de plus d'une version mineure, mettez à niveau kubectl ou le cluster pour éviter les problèmes d'API obsolètes.
Topologie du cluster (hypothétique mais illustrative) :
- Espace de noms :
production - Déploiement :
myapp - Service :
myapp-svc(NodePort ou LoadBalancer) - Quotas de ressources par espace de noms : CPU 2 cœurs, Mémoire 4Gi
Conservez cet inventaire dans un document partagé (par exemple, un README.md dans votre référentiel d'infrastructure) afin que chaque membre de l'équipe travaille avec les mêmes hypothèses.
Chemin de configuration sécurisé
Commencez par un déploiement pilote étroit et mesurable. Évitez les changements étendus qui affectent les services critiques. Utilisez un espace de noms séparé pour les tests et promouvez progressivement vers la production.
Étape 1 : Créer un espace de noms dédié
Créez un espace de noms qui reflète la production, y compris les quotas de ressources et les politiques réseau si vous les utilisez.
kubectl create namespace myapp-test
# Attendu : namespace/myapp-test created
Appliquez un quota de ressources pour éviter une consommation de ressources incontrôlée :
# quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: myapp-test-quota
namespace: myapp-test
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "4"
limits.memory: 8Gi
kubectl apply -f quota.yaml -n myapp-test
# Attendu : resourcequota/myapp-test-quota created
Étape 2 : Définir un manifeste de déploiement avec une stratégie de mise à jour progressive explicite
Une stratégie de mise à jour progressive garantit zéro temps d'arrêt en remplaçant progressivement les anciens pods par de nouveaux. Configurez maxUnavailable et maxSurge pour contrôler le rythme. Incluez des sondes de préparation et de vivacité afin que Kubernetes ne route le trafic que vers des pods sains.
Exemple deployment.yaml :
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp-test
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myregistry/myapp:1.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
Appliquez-le :
kubectl apply -f deployment.yaml
# Attendu : deployment.apps/myapp created
Vérifiez que les pods démarrent :
kubectl get pods -n myapp-test
# Attendu : 3 pods avec statut Running et 1/1 Ready
Étape 3 : Automatiser avec un pipeline CI/CD simple
Voici un workflow GitHub Actions minimal qui construit et déploie à chaque poussée sur main. Il utilise kubectl avec un jeton de compte de service stocké comme secret. Ajustez le registre et les noms d'image pour votre environnement.
Tout d'abord, créez un compte de service Kubernetes avec des autorisations limitées à l'espace de noms myapp-test :
# service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: github-actions
namespace: myapp-test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: github-actions-role
namespace: myapp-test
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "update", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: github-actions-binding
namespace: myapp-test
subjects:
- kind: ServiceAccount
name: github-actions
namespace: myapp-test
roleRef:
kind: Role
name: github-actions-role
apiGroup: rbac.authorization.k8s.io
Appliquez cela et récupérez un jeton :
kubectl apply -f service-account.yaml -n myapp-test
# Attendu : serviceaccount/github-actions created, role..., rolebinding...
# Obtenir le jeton (en supposant Kubernetes 1.24+ avec l'API TokenRequest) :
kubectl create token github-actions -n myapp-test --duration=24h
# Copiez la sortie du jeton.
Stockez le jeton et l'URL du serveur du cluster comme secrets dans votre référentiel GitHub : KUBE_TOKEN et KUBE_SERVER.
Créez maintenant le fichier de workflow .github/workflows/deploy.yml :
name: Deploy to Kubernetes
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build and push image
env:
REGISTRY: myregistry
IMAGE: myapp
TAG: ${{ github.sha }}
run: |
docker build -t $REGISTRY/$IMAGE:$TAG .
echo ${{ secrets.REGISTRY_PASSWORD }} | docker login $REGISTRY -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin
docker push $REGISTRY/$IMAGE:$TAG
- name: Set up kubectl
uses: azure/setup-kubectl@v1
- name: Deploy to cluster
env:
KUBE_SERVER: ${{ secrets.KUBE_SERVER }}
KUBE_TOKEN: ${{ secrets.KUBE_TOKEN }}
run: |
kubectl config set-cluster mycluster --server=$KUBE_SERVER --insecure-skip-tls-verify=true
kubectl config set-credentials github-actions --token=$KUBE_TOKEN
kubectl config set-context mycontext --cluster=mycluster --user=github-actions --namespace=myapp-test
kubectl config use-context mycontext
kubectl set image deployment/myapp myapp=myregistry/myapp:${{ github.sha }} -n myapp-test
kubectl rollout status deployment/myapp -n myapp-test --timeout=120s
Ce pipeline construit l'image, la pousse vers le registre, met à jour l'image du déploiement et attend la fin du déploiement. La commande rollout status fait échouer le pipeline si le déploiement ne devient pas sain dans les 120 secondes.
Vérification et diagnostic
Après avoir appliqué les modifications, vérifiez que le déploiement a réussi et que l'application sert correctement le trafic. Intégrez ces vérifications dans votre pipeline en tant que barrières automatisées.
État du déploiement de base
kubectl rollout status deployment/myapp -n myapp-test
# Attendu : deployment "myapp" successfully rolled out
Inspecter la santé des pods
kubectl get pods -n myapp-test
# Attendu : 3 pods avec statut Running et READY 1/1
Afficher l'historique des déploiements
kubectl rollout history deployment/myapp -n myapp-test
# Sortie attendue :
# REVISION CHANGE-CAUSE
# 1 <none>
# 2 <none>
Pour enregistrer une cause de changement, ajoutez une annotation avant d'appliquer :
kubectl annotate deployment/myapp kubernetes.io/change-cause="Deploy commit $(git rev-parse --short HEAD)" -n myapp-test --overwrite
Décrire les événements pour le diagnostic
kubectl describe deployment myapp -n myapp-test
# Cherchez la section Events : ScalingReplicaSet, SuccessfulCreate, etc.
Consulter les journaux en cas d'échec d'un pod
kubectl logs deployment/myapp -n myapp-test --tail=20
| Commande | Résultat attendu |
|---|---|
kubectl rollout status deployment/myapp -n myapp-test | "successfully rolled out" |
kubectl get pods -n myapp-test | Tous les pods Running et Ready |
kubectl get replicasets -n myapp-test | Le nouveau ReplicaSet a les répliques souhaitées, l'ancien est réduit |
kubectl describe deployment myapp -n myapp-test | Aucun événement d'erreur |
Utilisez ces vérifications comme barrières dans votre pipeline avant de promouvoir en production. Par exemple, après rollout status, ajoutez une étape qui exécute un test de fumée :
kubectl run smoke-test --image=curlimages/curl --rm -it --restart=Never -n myapp-test -- -s http://myapp-svc:8080/healthz
# Attendu : réponse HTTP 200
Modes de défaillance et récupération
Même avec l'automatisation, des échecs surviennent. Les modes de défaillance courants incluent les erreurs d'extraction d'image, les échecs de sonde de préparation et les ressources insuffisantes. Savoir comment récupérer rapidement est essentiel.
Défaillance 1 : ImagePullBackOff
- Cause : Étiquette d'image incorrecte ou informations d'identification du registre erronées.
- Détection :
kubectl get podsafficheImagePullBackOff. - Récupération : Corrigez l'étiquette de l'image ou les informations d'identification, puis appliquez un manifeste corrigé ou mettez à jour le déploiement.
Exemple de diagnostic :
kubectl get pods -n myapp-test
# NAME READY STATUS RESTARTS AGE
# myapp-765d459796-8s9k7 0/1 ImagePullBackOff 0 2m
kubectl describe pod myapp-765d459796-8s9k7 -n myapp-test
# Cherchez les événements : Failed to pull image ...
Défaillance 2 : CrashLoopBackOff
- Cause : L'application plante au démarrage, souvent en raison d'une mauvaise configuration.
- Détection :
kubectl get podsafficheCrashLoopBackOff. - Récupération : Vérifiez les journaux avec
kubectl logs, corrigez le code/la configuration, et poussez une nouvelle image.
kubectl logs pod/myapp-765d459796-8s9k7 -n myapp-test --previous
# Examinez la trace de pile ou le message d'erreur.
Défaillance 3 : Déploiement bloqué en raison d'un échec de sonde de préparation
- Cause : Les nouveaux pods ne deviennent jamais prêts, donc le déploiement stagne.
- Détection :
kubectl rollout statusexpire ou affiche une progression. - Récupération : Étudiez l'endpoint de la sonde de préparation ou le comportement de l'application. Effectuez un retour arrière si nécessaire.
Défaillance 4 : Ressources insuffisantes
- Cause : Quota de ressources dépassé ou capacité du cluster limitée.
- Détection : Les nouveaux pods restent en état
Pending. - Récupération : Réduisez d'autres charges de travail ou augmentez les quotas de ressources.
Procédure de retour arrière
Ayez toujours un plan de retour arrière et testez-le dans un espace de noms hors production avant d'en avoir besoin en production.
# Retour à la révision précédente
kubectl rollout undo deployment/myapp -n myapp-test
# Attendu : deployment.apps/myapp rolled back
# Ou retour à une révision spécifique
kubectl rollout undo deployment/myapp --to-revision=2 -n myapp-test
# Attendu : deployment.apps/myapp rolled back
Après le retour arrière, vérifiez :
kubectl rollout status deployment/myapp -n myapp-test
# Attendu : successfully rolled out
| Mode de défaillance | Symptôme | Action de récupération |
|---|---|---|
| ImagePullBackOff | Le statut du pod affiche ImagePullBackOff | Corriger l'étiquette de l'image ou le secret du registre, appliquer le déploiement mis à jour |
| CrashLoopBackOff | Le pod redémarre à plusieurs reprises | Vérifier les journaux, corriger l'erreur d'application, pousser une nouvelle image |
| Échec de la sonde de préparation | Déploiement bloqué, nouveaux pods non prêts | Vérifier l'endpoint de la sonde, ajuster la sonde ou corriger l'application, retour arrière si nécessaire |
| Ressources insuffisantes | Pods en attente | Réduire la charge ou augmenter les quotas de ressources |
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle avant et après chaque déploiement pour garantir la cohérence et la sécurité. Conservez-la dans votre référentiel ou wiki et mettez-la à jour au fur et à mesure que votre processus évolue.
Liste de contrôle avant déploiement
- [ ] Vérifier que les versions du cluster et de kubectl correspondent aux attentes (
kubectl version --short) - [ ] Examiner les modifications du manifeste de déploiement dans le contrôle de version (diff avec la dernière version)
- [ ] S'assurer que l'image est construite et poussée avec une étiquette unique (par exemple, SHA git, pas
latest) - [ ] Confirmer que les demandes et limites de ressources sont définies pour tous les conteneurs
- [ ] Vérifier que les sondes de préparation et de vivacité sont configurées et pointent vers les bons endpoints
- [ ] Vérifier que le pipeline CI/CD dispose des bonnes informations d'identification du cluster (jeton de compte de service, URL du serveur)
- [ ] Exécuter une application à blanc pour valider la syntaxe YAML :
kubectl apply -f deployment.yaml --dry-run=client -n myapp-test
Liste de contrôle après déploiement
- [ ] Exécuter
kubectl rollout statuset confirmer le succès - [ ] Vérifier la préparation des pods et les journaux pour les erreurs (
kubectl get pods,kubectl logs) - [ ] Surveiller les métriques de l'application (taux d'erreur, latence) pendant au moins 5 minutes après le déploiement
- [ ] Enregistrer la révision du déploiement et tout changement notable (mettre à jour les notes de version ou le journal des modifications)
- [ ] En cas de problème, exécuter la procédure de retour arrière et documenter la cause racine dans un rapport d'incident
Revue périodique
- [ ] Examiner la sécurité du pipeline : faire tourner les secrets, appliquer le principe du moindre privilège sur les comptes de service
- [ ] Mettre à jour les images de base et les dépendances pour corriger les vulnérabilités
- [ ] Tester le retour arrière dans un environnement de staging tous les trimestres
- [ ] Évaluer la vitesse et la fiabilité du pipeline ; optimiser le cache de construction et le parallélisme si nécessaire
Conclusion
L'automatisation du déploiement CI/CD sur Kubernetes améliore la fiabilité et réduit les erreurs manuelles. En commençant par un pilote étroit, en implémentant un pipeline simple et en vérifiant chaque déploiement, vous créez une base pour des versions plus sûres. Lorsque des échecs surviennent, avoir une voie de retour arrière claire minimise les temps d'arrêt.
Adoptez la liste de contrôle opérationnelle pour garder votre processus cohérent, et étendez progressivement l'automatisation à d'autres services à mesure que la confiance grandit. N'oubliez pas d'itérer : commencez petit, mesurez le succès et affinez votre pipeline en fonction du comportement observé. Avec ces pratiques, vous pouvez livrer plus rapidement en toute confiance, sachant que vos déploiements Kubernetes sont sûrs, reproductibles et récupérables.
Prochaines étapes : implémentez ces modèles dans votre propre cluster, intégrez des notifications (par exemple, des alertes Slack) en cas d'échec du pipeline, et explorez des outils de livraison progressive comme Argo Rollouts ou Flagger pour des stratégies de déploiement plus avancées.