Introduction
Exécuter une application stateful répliquée sur Kubernetes en production exige plus que de déployer un StatefulSet et d'espérer que tout se passe bien. Les charges de travail stateful — bases de données, courtiers de messages, caches distribués et systèmes similaires — imposent des exigences strictes en matière d'identité, de stockage, d'ordre et de gestion gracieuse du cycle de vie. Lorsque les choses tournent mal, les opérateurs ont besoin d'un processus clair et reproductible pour diagnostiquer et récupérer sans causer de perturbations supplémentaires.
Cet article fournit une liste de contrôle opérationnelle de production adaptée aux applications stateful répliquées sur Kubernetes. Il s'adresse aux développeurs, aux consultants DevOps et aux équipes techniques de startups responsables du bon fonctionnement de ces systèmes. La liste de contrôle relie les opérations Kubernetes, les bonnes pratiques et la maintenance à des commandes concrètes, des sorties attendues, des signaux de défaillance et des décisions de récupération.
Le principe fondamental est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés plutôt que des secrets, vérifier le résultat et documenter comment récupérer si l'état attendu n'est pas atteint. Chaque section ci-dessous aborde un domaine opérationnel spécifique : inventaire des versions et de l'environnement, configuration sûre, vérification et diagnostics, modes de défaillance et récupération, et une liste de contrôle opérationnelle consolidée.
Inventaire des versions et de l'environnement
Avant de toucher à une application stateful en cours d'exécution, vous devez savoir exactement à quoi vous avez affaire. Un inventaire des versions et de l'environnement établit la référence : la version installée, la topologie de déploiement, les prérequis et les composants exacts inspectés. Cela évite les suppositions erronées et réduit le risque d'appliquer un correctif destiné à une version ou une configuration différente.
Pour une application stateful répliquée exécutée en tant que StatefulSet Kubernetes, l'inventaire doit capturer :
- Version du cluster Kubernetes et compatibilité avec le serveur d'API
- Version du manifeste du StatefulSet et nombre actuel de réplicas
- Images de conteneurs et leurs étiquettes
- État des PersistentVolumeClaim (PVC), classe de stockage et capacité
- Politiques réseau, budgets de perturbation des pods et toute ressource personnalisée affectant la charge de travail
Commencez par des observations en lecture seule. Capturez d'abord l'état actuel et les horodatages, protégez les identifiants et le matériel privé, puis modifiez un seul élément délimité uniquement lorsque son rayon d'impact et son chemin de récupération sont compris.
Commandes Kubernetes pratiques pour l'inventaire :
# Version du cluster
kubectl version --short
# Vue d'ensemble du StatefulSet
kubectl get statefulset <nom-statefulset> -o wide
# Pods avec IP et nœuds
kubectl get pods -l app=<étiquette-app> -o wide
# Réclamations de volume persistant
kubectl get pvc -l app=<étiquette-app>
# Événements pour l'espace de noms (récents)
kubectl get events --sort-by=.metadata.creationTimestamp | tail -20
Exemple de sortie pour un StatefulSet à trois réplicas sain nommé postgres :
NAME READY AGE CONTAINERS IMAGES
postgres 3/3 42d postgres postgres:14.5
NAME READY STATUS RESTARTS AGE IP NODE
postgres-0 1/1 Running 0 42d 10.244.1.10 worker-1
postgres-1 1/1 Running 0 42d 10.244.2.20 worker-2
postgres-2 1/1 Running 0 42d 10.244.3.30 worker-3
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-postgres-0 Bound pvc-8a2b3c4d-... 20Gi RWO standard 42d
data-postgres-1 Bound pvc-9b3c4d5e-... 20Gi RWO standard 42d
data-postgres-2 Bound pvc-0c4d5e6f-... 20Gi RWO standard 42d
Si l'une de ces commandes échoue ou affiche des versions inattendues, enquêtez avant de continuer. Par exemple, un pod en statut CrashLoopBackOff nécessite une inspection des journaux :
# Journaux actuels
kubectl logs postgres-0
# Journaux du conteneur précédent (s'il a redémarré)
kubectl logs postgres-0 --previous
Gardez le test local petit. Appliquez un manifeste, inspectez les ressources générées et vérifiez le trafic avec kubectl port-forward ou un type de service local avant de passer à un équilibreur de charge cloud ou à un contrôleur d'entrée. Par exemple, après un test de mise à niveau de version :
# Redirection de port vers le local pour tester la connectivité
kubectl port-forward svc/postgres 5432:5432
# Dans un autre terminal
psql -h localhost -U postgres -c 'SELECT version();'
Si la sortie correspond à la nouvelle version attendue, le chemin de mise à niveau est probablement sain. Sinon, annulez avant de l'appliquer à la production.
Chemin de configuration sûr
Les changements de configuration sont une source fréquente d'incidents dans les applications stateful. Un chemin de configuration sûr signifie que vous savez ce que vous changez, pourquoi, quel est le résultat attendu et comment revenir en arrière si nécessaire. Pour les StatefulSets, certains champs sont immuables après la création (par exemple, spec.volumeClaimTemplates et spec.serviceName). Tenter de les modifier échouera ; parfois, vous devez supprimer et recréer le StatefulSet tout en préservant les données, ce qui nécessite une planification minutieuse.
Le chemin de configuration sûr consiste en :
- Observation en lecture seule : Vérifiez la configuration actuelle avec
kubectl get statefulset <nom> -o yamlet comparez-la à une base de référence saine stockée dans le contrôle de version. - Changement justifié minimal : Modifiez un champ à la fois, de préférence d'abord dans un environnement de préproduction. Utilisez
kubectl diffpour prévisualiser les changements. - Évaluation du rayon d'impact : Déterminez quels pods seront affectés. Pour un StatefulSet, les modifications du modèle de pod déclencheront une mise à jour progressive uniquement si la stratégie de mise à jour est
RollingUpdate. AvecOnDelete, aucun pod n'est mis à jour tant qu'il n'est pas supprimé manuellement. - Vérification : Après l'application, vérifiez l'état des pods, les journaux et la santé de l'application.
Commandes pour une configuration sûre :
# Prévisualiser les changements avant de les appliquer
kubectl diff -f statefulset-mis-a-jour.yaml
# Appliquer le changement
kubectl apply -f statefulset-mis-a-jour.yaml
# Suivre l'état du déploiement
kubectl rollout status statefulset/<nom>
# Si vous utilisez la stratégie OnDelete, déclenchez la mise à jour pod par pod
kubectl delete pod <nom>-0
Exemple de mise à jour contrôlée des ressources. Supposons que vous deviez augmenter les demandes de CPU pour un conteneur de base de données. La différence montre :
--- a/statefulset.yaml
+++ b/statefulset.yaml
@@ -42,7 +42,7 @@ spec:
resources:
requests:
- cpu: "500m"
+ cpu: "750m"
memory: "1Gi"
Appliquez puis observez les pods redémarrer dans l'ordre. Pour un StatefulSet RollingUpdate, les pods sont mis à jour dans l'ordre ordinal inverse (indice le plus élevé en premier). Vous pouvez vérifier avec :
kubectl get pods -w
Les noms de pods postgres-2, puis postgres-1, puis postgres-0 passeront de Running à Terminating puis à ContainerCreating puis à Running à nouveau. Si un pod reste bloqué en Pending ou CrashLoopBackOff, annulez immédiatement le changement.
Points de sécurité critiques pour la configuration stateful :
- Ne modifiez jamais
volumeClaimTemplatessur un StatefulSet en direct ; c'est immuable. Créez plutôt un nouveau StatefulSet et migrez les données, ou étendez le volume en utilisant la fonctionnalité d'extension de votre fournisseur de stockage si elle est prise en charge. - Définissez toujours
updateStrategyexplicitement. La valeur par défaut estRollingUpdateavecpartition: 0, mais pour les bases de données, vous pouvez vouloirOnDeletepour contrôler quand chaque réplica redémarre. - Protégez les secrets : ne mettez pas de mots de passe ou de clés dans des manifestes en texte brut. Utilisez les Secrets Kubernetes, des opérateurs de secrets externes ou les magasins de secrets du fournisseur cloud. Référencez-les comme variables d'environnement ou volumes montés.
Exemple d'utilisation sécurisée d'un secret :
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
type: Opaque
stringData:
POSTGRES_PASSWORD: "s3cr3t-example"
---
apiVersion: apps/v1
kind: StatefulSet
spec:
template:
spec:
containers:
- name: postgres
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
Ne journalisez jamais et n'affichez jamais la valeur du secret. Utilisez kubectl get secret postgres-secret -o yaml uniquement dans un environnement contrôlé, et caviardez la sortie dans la documentation.
Vérification et diagnostics
La vérification signifie confirmer que le système se comporte comme prévu après un changement ou pendant les opérations normales. Le diagnostic consiste à identifier la cause profonde lorsque ce n'est pas le cas. Pour les applications stateful, la santé ne se limite pas au statut du pod ; vous devez vérifier la disponibilité au niveau de l'application, la cohérence des données et l'état de la réplication.
Une approche de vérification en couches :
Couche 1 : Statut des objets Kubernetes
kubectl get statefulset <nom>
kubectl get pods -l app=<étiquette>
kubectl get pvc -l app=<étiquette>
Tous les pods doivent être Running avec READY 1/1 et zéro redémarrage (ou un nombre de redémarrages faible et stable). Le StatefulSet doit afficher READY égal au nombre de réplicas souhaité.
Couche 2 : Journaux des conteneurs
kubectl logs <nom-pod> --tail=50
kubectl logs <nom-pod> --previous
Recherchez des motifs d'erreur : connexion refusée, disque plein, retard de réplication, etc. Exemple de journal problématique de PostgreSQL :
FATAL: could not write to file "pg_wal/xlogtemp.123": No space left on device
Cela indique que le PVC est plein. Action immédiate : augmentez le disque ou nettoyez les anciens fichiers WAL.
Couche 3 : Vérifications de santé de l'application
Utilisez kubectl exec pour exécuter des commandes spécifiques à l'application :
# Pour PostgreSQL
kubectl exec -it postgres-0 -- psql -U postgres -c "SELECT 1;"
# Pour un point de terminaison HTTP générique
kubectl exec -it <pod> -- curl -f http://localhost:8080/health
Couche 4 : Vérification du réseau et du service
kubectl get endpoints <nom-service>
Les points de terminaison doivent lister les IP des pods. S'ils sont vides, le sélecteur de service ne correspond pas aux étiquettes des pods. Testez la connectivité depuis un autre pod :
kubectl run -it --rm debug --image=busybox -- sh
# À l'intérieur du pod de débogage
wget -qO- http://<nom-service>:<port>/health
Exemple de scénario de diagnostic : un StatefulSet PostgreSQL à trois réplicas affiche postgres-2 en CrashLoopBackOff. Étapes :
kubectl describe pod postgres-2affiche les événements :
Warning BackOff 2m (x12 over 3m) kubelet Back-off restarting failed container
kubectl logs postgres-2 --previousaffiche :
FATAL: could not connect to the primary server: connection refused
- Vérifiez le pod primaire
postgres-0:
kubectl logs postgres-0
Si postgres-0 affiche recovery ou n'accepte pas les connexions, le problème peut être un cerveau divisé ou un basculement échoué. Enquêtez sur la configuration de la réplication.
Pour chaque diagnostic, enregistrez la commande, la sortie et l'horodatage. Cela crée une piste d'audit pour les revues post-incident.
Modes de défaillance et récupération
Les applications stateful peuvent échouer de nombreuses façons. Comprendre les modes de défaillance courants et disposer d'étapes de récupération prédéfinies réduit les temps d'arrêt et la panique. Nous décrivons ici plusieurs modes de défaillance pertinents pour les charges de travail stateful répliquées sur Kubernetes, avec les signaux de diagnostic et les actions de récupération.
1. Pod en CrashLoopBackOff
Signal : kubectl get pods affiche CrashLoopBackOff ou Error ; kubectl describe pod montre plusieurs redémarrages.
Causes courantes :
- Mauvaise configuration (mauvaise variable d'environnement, secret manquant)
- Bug de l'application
- Limites de ressources trop basses (OOMKilled)
- Données corrompues sur le volume persistant
Diagnostic :
kubectl describe pod <nom-pod> | grep -A 10 "Last State"
kubectl logs <nom-pod> --previous
Récupération :
- Corrigez la configuration ou le code et appliquez le changement.
- Si OOMKilled, augmentez la limite de mémoire ou réduisez l'utilisation de la mémoire de l'application.
- Si corruption des données, restaurez à partir de la sauvegarde ou de l'instantané.
2. Volume persistant plein ou indisponible
Signal : Les journaux des pods affichent "No space left on device" ; kubectl get pvc montre la capacité atteinte ; le pod peut être bloqué en ContainerCreating si le volume ne peut pas être monté.
Diagnostic :
kubectl get pvc
kubectl describe pvc <nom-pvc>
kubectl exec <pod> -- df -h
Récupération :
- Étendez le PVC si la classe de stockage le prend en charge :
kubectl patch pvc <nom-pvc> -p '{"spec":{"resources":{"requests":{"storage":"40Gi"}}}}'. - Supprimez les données inutiles dans l'application (par exemple, anciens journaux, fichiers temporaires).
- Si le volume est indisponible en raison d'une défaillance du nœud, le pod peut être bloqué ; forcez la suppression du pod et laissez-le se replanifier sur un nœud sain (mais soyez prudent avec l'identité du StatefulSet).
3. Cerveau divisé de l'ensemble de réplicas
Signal : Plusieurs pods prétendent être primaires ; les clients obtiennent des données incohérentes ; les journaux affichent des conflits de réplication.
Diagnostic :
- Vérifiez le statut d'élection du primaire spécifique à l'application (par exemple,
patronictl listpour PostgreSQL géré par Patroni). kubectl get pods -o widepour voir si les pods sont répartis incorrectement sur les nœuds.
Récupération :
- Utilisez le mécanisme de basculement de l'application pour forcer un primaire.
- Pour les StatefulSets, assurez-vous que la politique de gestion des pods et les politiques réseau ne permettent pas un accès non intentionnel.
- Ne supprimez jamais le pod qui détient le volume de données primaire sans une sauvegarde.
4. Mise à jour du StatefulSet bloquée
Signal : kubectl rollout status statefulset/<nom> se bloque ; certains pods sont mis à jour mais d'autres restent anciens.
Diagnostic :
kubectl get pods
kubectl describe pod <pod-bloqué>
Vérifiez les événements pour les erreurs de tirage d'image, les échecs de planification ou les échecs de sonde de disponibilité.
Récupération :
- Si erreur de tirage d'image, corrigez le nom de l'image ou les identifiants.
- Si la sonde de disponibilité échoue, inspectez les journaux de l'application ; la nouvelle version peut ne pas être compatible avec les données existantes.
- Annulation :
kubectl rollout undo statefulset/<nom>
5. Défaillance d'un nœud
Signal : Les pods sur un nœud passent en Unknown ou Terminating ; le nœud est marqué NotReady.
Diagnostic :
kubectl get nodes
kubectl describe node <nom-nœud>
Récupération :
- Attendez que Kubernetes replanifie les pods sur des nœuds sains. Les pods du StatefulSet avec des volumes persistants seront recréés sur des nœuds capables de monter le volume.
- Si un pod est bloqué en terminaison, forcez sa suppression :
kubectl delete pod <nom-pod> --grace-period=0 --force. - Assurez-vous que la classe de stockage prend en charge le multi-attachement ou que le volume est libéré du nœud défaillant.
Pour toutes les actions de récupération, documentez l'incident et les étapes entreprises. Après la récupération, vérifiez l'intégrité des données et l'état de la réplication.
Liste de contrôle opérationnelle
Cette section consolide les vérifications opérationnelles clés en une seule liste de contrôle qui peut être utilisée lors de la maintenance régulière, des déploiements ou de la réponse aux incidents. La liste de contrôle est organisée par phase opérationnelle.
Liste de contrôle pré-déploiement
- [ ] Vérifier la compatibilité de la version Kubernetes avec les versions prises en charge par l'application.
- [ ] Examiner le manifeste du StatefulSet pour les contraintes d'immuabilité (par exemple,
volumeClaimTemplates). - [ ] S'assurer que les réclamations de volume persistant sont créées et liées.
- [ ] Définir les demandes et limites de ressources ; éviter des limites trop strictes pour les applications stateful.
- [ ] Définir un budget de perturbation des pods (PDB) pour protéger le quorum :
kubectl get pdb - [ ] Configurer les sondes de vivacité et de disponibilité de manière appropriée (ne pas surcharger avec des vérifications lourdes).
- [ ] Tester les procédures de sauvegarde et de restauration dans un environnement non productif.
Liste de contrôle de déploiement / mise à jour
- [ ] Utiliser
kubectl diffpour prévisualiser les changements. - [ ] Appliquer les changements avec
kubectl apply -f. - [ ] Surveiller le déploiement avec
kubectl rollout status statefulset/<nom>. - [ ] Observer les transitions des pods :
kubectl get pods -w - [ ] Si vous utilisez
OnDelete, mettez à jour les pods manuellement dans l'ordre ordinal inverse. - [ ] Après chaque mise à jour de pod, vérifier la santé de l'application (par exemple,
SELECT 1pour une base de données, point de terminaison de santé API pour les applications personnalisées). - [ ] Vérifier l'état de la réplication ; s'assurer que les réplicas sont synchronisés avant de continuer.
- [ ] Si un pod échoue, faire une pause et annuler :
kubectl rollout undo statefulset/<nom>.
Vérifications de santé quotidiennes / hebdomadaires
- [ ]
kubectl get statefulset <nom>- s'assurer que les réplicas prêts sont égaux au nombre souhaité. - [ ]
kubectl get pods -l app=<étiquette>- tous enRunning, faible nombre de redémarrages. - [ ]
kubectl get pvc- utilisation de la capacité en dessous du seuil (par exemple, 80%). - [ ] Vérifier les journaux de l'application pour les erreurs :
kubectl logs <pod> --tail=100 - [ ] Surveiller les métriques : CPU, mémoire, E/S disque, retard de réplication.
- [ ] Examiner les événements pour les avertissements :
kubectl get events --field-selector type=Warning - [ ] Vérifier que les tâches de sauvegarde se sont terminées avec succès.
Liste de contrôle de réponse aux incidents
- [ ] Identifier la portée : quels pods, nœuds, services sont affectés ? Utiliser
kubectl get pods -o wideetkubectl get events. - [ ] Préserver les preuves : collecter les journaux, la sortie de description et l'état actuel avant de faire des changements.
- [ ] Déterminer si le problème est au niveau de l'application ou de l'infrastructure.
- [ ] Vérifier les volumes persistants et le sous-système de stockage.
- [ ] Si nécessaire, isoler les nœuds :
kubectl cordon <nœud> - [ ] Appliquer le correctif avec un changement minimal.
- [ ] Vérifier soigneusement la récupération avant de déclarer la résolution.
- [ ] Documenter l'incident : chronologie, cause profonde, actions entreprises, mesures préventives.
Exemple concret détaillé : mise à niveau d'un cluster CockroachDB à trois nœuds
Supposons que vous ayez un StatefulSet CockroachDB avec trois réplicas. Vous souhaitez passer de la v22.1 à la v22.2.
- Pré-vérifications :
- Vérifier la santé du cluster :
kubectl exec cockroachdb-0 -- cockroach node statusmontre tous les nœuds en vie. - Vérifier l'espace disque :
kubectl exec cockroachdb-0 -- df -h /cockroach/cockroach-datamontre 35% utilisés. - Examiner les notes de mise à niveau : CockroachDB nécessite des versions mineures séquentielles.
- Mettre à jour l'image : Changez l'étiquette de l'image du conteneur de
cockroachdb/cockroach:v22.1.10àcockroachdb/cockroach:v22.2.0dans le manifeste du StatefulSet. Utilisezkubectl edit statefulset cockroachdbou un patch :
kubectl set image statefulset/cockroachdb cockroachdb=cockroachdb/cockroach:v22.2.0
- Surveiller le déploiement : Le StatefulSet utilise
RollingUpdateavecpartition: 0. Les pods seront mis à jour decockroachdb-2àcockroachdb-0. Observez :
kubectl rollout status statefulset/cockroachdb
- Vérifier chaque pod : Après le redémarrage de chaque pod, vérifiez qu'il rejoint le cluster :
kubectl exec cockroachdb-0 -- cockroach node status
Les trois nœuds doivent montrer is_live: true.
- Post-mise à niveau : Exécutez les commandes de migration recommandées s'il y en a (voir la documentation CockroachDB). Ensuite, vérifiez la version du cluster :
kubectl exec cockroachdb-0 -- cockroach sql --execute="SHOW CLUSTER SETTING version;"
La sortie doit montrer 22.2.
Si un pod ne démarre pas, annulez l'image et consultez les journaux :
kubectl set image statefulset/cockroachdb cockroachdb=cockroachdb/cockroach:v22.1.10
kubectl logs cockroachdb-2 --previous
Cette liste de contrôle et cet exemple démontrent l'approche pratique, étape par étape, nécessaire pour des opérations sûres d'applications stateful répliquées sur Kubernetes.
Conclusion
Une liste de contrôle opérationnelle de production pour les applications stateful répliquées sur Kubernetes n'a de valeur que si chaque recommandation est limitée à une version, observable et réversible là où la technologie le permet. Copier une commande sans vérifier les prérequis et la sortie attendue n'est pas une procédure opérationnelle ; c'est un pari.
Les points clés à retenir de cet article :
- Inventaire d'abord : Connaissez toujours vos versions, votre topologie et l'état des ressources avant de faire des changements.
- Configuration sûre : Utilisez
kubectl diff, comprenez l'immuabilité et protégez les secrets. - Vérification en couches : Vérifiez le statut Kubernetes, les journaux, la santé de l'application et la connectivité réseau.
- Préparez-vous aux défaillances : Connaissez les modes de défaillance courants et ayez des procédures de récupération prêtes.
- Suivez une liste de contrôle : Utilisez la liste de contrôle consolidée pour les déploiements, les vérifications de routine et la réponse aux incidents.
Comme prochaine étape, choisissez une vérification à faible risque pour votre application stateful, enregistrez l'état actuel, exécutez la vérification documentée, comparez le résultat avec le signal attendu et passez en revue les dépendances telles que StatefulSet, PersistentVolume et PersistentVolumeClaim. Par exemple, exécutez kubectl get statefulset <nom> -o yaml et confirmez que updateStrategy et podManagementPolicy correspondent à votre intention opérationnelle.
Un flux de travail technique fiable rend les défaillances visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision. En suivant les pratiques de cet article, vous pouvez exécuter vos applications stateful répliquées sur Kubernetes avec une plus grande confiance et résilience.