E-NO
Kubernetes 7 min de lecture

Dépannage des Secrets Kubernetes avec des exemples pratiques

calendar_today Publié : 2026-08-11
update Dernière mise à jour : 2026-08-11
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Dépannage des Secrets Kubernetes avec des exemples pratiques ».

Les Secrets Kubernetes stockent des données sensibles telles que les clés d'API, les mots de passe de base de données, les certificats TLS et les jetons de compte de service. Lorsque les applications échouent au démarrage, plantent avec des erreurs de permission ou se comportent de manière incohérente d'un environnement à l'autre, la cause racine est souvent un Secret mal configuré ou manquant. Ce guide présente un flux de travail de dépannage systématique : inventorier l'environnement, valider la configuration du Secret, vérifier la consommation à l'exécution, diagnostiquer les modes de défaillance courants et appliquer des étapes de récupération sûres. Chaque section comprend des commandes concrètes, des motifs de sortie attendus et des points de décision pour passer du symptôme à la résolution sans deviner.

Inventaire de l'environnement et base de référence des versions

Avant de modifier quoi que ce soit, capturez l'état actuel du cluster, de la charge de travail et du Secret lui-même. Commencez par la version de Kubernetes et le backend des Secrets, car la configuration du chiffrement au repos, la disponibilité du pilote CSI et les versions de l'opérateur External Secrets influencent tous le comportement.

kubectl version --short
# Client Version: v1.28.4
# Kustomize Version: v5.0.4
# Server Version: v1.27.9

Vérifiez si le cluster utilise le fournisseur de chiffrement par défaut de kube-apiserver ou un plugin KMS externe :

kubectl get cm -n kube-system kube-apiserver -o yaml 2>/dev/null | grep -A5 "encryption-provider-config" || echo "Aucune configuration de chiffrement trouvée (défaut : identity)"

Listez tous les Secrets dans l'espace de noms cible et notez leurs types, âges et étiquettes :

kubectl get secrets -n production -o custom-columns=NAME:.metadata.name,TYPE:.type,AGE:.metadata.creationTimestamp,LABELS:.metadata.labels

Sortie typique :

NAME                  TYPE                       AGE                   LABELS
tls-ingress-cert      kubernetes.io/tls          45d                   app=ingress,env=prod
db-credentials        Opaque                     12d                   app=api,component=postgres
docker-registry-key   kubernetes.io/dockerconfigjson 30d              app=worker,registry=ghcr
api-tokens            Opaque                     3d                    app=api,rotate=weekly

Identifiez la charge de travail qui consomme le Secret. Pour un Deployment nommé api-server :

kubectl get deployment api-server -n production -o yaml | grep -A10 "secretRef\|envFrom\|volumeMounts"

Enregistrez les noms exacts des clés que le conteneur attend. Une incompatibilité entre la clé du Secret (DB_PASSWORD) et la référence env (DATABASE_PASSWORD) est une cause fréquente de CrashLoopBackOff sans erreur évidente dans le Secret lui-même.

Chemin de configuration sûr : création et mise à jour des Secrets

Traitez les manifestes de Secrets comme du code : versionnés, revus et appliqués via un pipeline. N'éditez jamais des Secrets en direct avec kubectl edit en production sans plan de retour arrière.

Création déclarative avec kubectl create secret (essai à sec d'abord)

Générez un manifeste sans l'appliquer, inspectez la sortie en base64, puis validez le YAML :

kubectl create secret generic db-credentials \
  --namespace=production \
  --from-literal=DB_HOST=postgres-primary.production.svc.cluster.local \
  --from-literal=DB_PORT=5432 \
  --from-literal=DB_USER=app_user \
  --from-literal=DB_PASSWORD='S3cur3P@ssw0rd!' \
  --dry-run=client -o yaml > db-credentials.yaml

Le fichier généré contient des valeurs encodées en base64. Vérifiez l'aller-retour de l'encodage :

grep "DB_PASSWORD:" db-credentials.yaml | awk '{print $2}' | base64 -d
# Sortie : S3cur3P@ssw0rd!

Appliquez avec l'application côté serveur pour préserver la propriété des champs :

kubectl apply -f db-credentials.yaml --server-side --force-conflicts

Rotation des valeurs sans temps d'arrêt

Lors de la rotation d'un mot de passe, créez une nouvelle version du Secret et mettez à jour le Deployment pour le référencer, puis déployez :

kubectl create secret generic db-credentials-v2 \
  --namespace=production \
  --from-literal=DB_PASSWORD='N3wP@ssw0rd!' \
  --from-literal=DB_HOST=postgres-primary.production.svc.cluster.local \
  --from-literal=DB_PORT=5432 \
  --from-literal=DB_USER=app_user \
  --dry-run=client -o yaml | kubectl apply -f -

kubectl set env deployment/api-server -n production DB_PASSWORD_=$(kubectl get secret db-credentials-v2 -n production -o jsonpath='{.data.DB_PASSWORD}' | base64 -d)
# Ou mieux : utilisez envFrom avec secretRef.name=db-credentials-v2 et déployez
kubectl patch deployment api-server -n production -p '{"spec":{"template":{"spec":{"containers":[{"name":"api","envFrom":[{"secretRef":{"name":"db-credentials-v2"}}]}]}}}}'
kubectl rollout status deployment/api-server -n production --timeout=3m

Vérifiez que le nouveau Secret est monté :

kubectl exec -n production deploy/api-server -- cat /etc/secrets/db-credentials/DB_PASSWORD 2>/dev/null || echo "Volume non monté ; vérifiez volumeMounts"

Modèle avec l'opérateur External Secrets

Si vous utilisez l'opérateur External Secrets (ESO) avec AWS Secrets Manager, Vault ou Azure Key Vault, la surface de dépannage se déplace vers les ressources ExternalSecret et SecretStore :

kubectl get externalsecret -n production
kubectl describe externalsecret db-credentials -n production
# Recherchez Condition: Ready=True, horodatage de la dernière synchronisation et tout événement "SecretSynced"

Une défaillance ESO courante : le SecretStore référence un ARN de rôle qui n'a pas la permission secretsmanager:GetSecretValue. Le journal des événements affichera Failed to fetch secret: AccessDenied.

Vérification et diagnostics à l'exécution

Une fois que le Secret existe, confirmez que la charge de travail reçoit réellement les bonnes valeurs à l'exécution.

Inspection au niveau du Pod

Vérifiez les variables d'environnement à l'intérieur d'un conteneur en cours d'exécution :

POD=$(kubectl get pods -n production -l app=api -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n production $POD -- env | grep -E 'DB_|PASSWORD|TOKEN'

Sortie attendue :

DB_HOST=postgres-primary.production.svc.cluster.local
DB_PORT=5432
DB_USER=app_user
DB_PASSWORD=S3cur3P@ssw0rd!

Si la variable est manquante ou vide, inspectez la spécification du pod pour le chemin de montage du volume :

kubectl get pod $POD -n production -o yaml | grep -A5 "volumeMounts\|secret:"

Pour les montages basés sur des fichiers (courants avec les certificats TLS), lisez le fichier directement :

kubectl exec -n production $POD -- cat /etc/tls/tls.crt | head -2
# Devrait afficher : -----BEGIN CERTIFICATE-----

Journaux du Kubelet et du serveur API

Si le pod est bloqué dans ContainerCreating, le kubelet peut être incapable de monter le Secret. Sur un nœud (ou via kubectl debug node/...) :

journalctl -u kubelet -f | grep -i "secret\|mount"
# Recherchez : "Failed to mount secret" ou "secret not found"

Au niveau du serveur API, surveillez les événements Secret qui indiquent des retards de propagation :

kubectl get events -n production --field-selector involvedObject.kind=Secret --sort-by='.lastTimestamp'

Effets de bord des politiques réseau et RBAC

Un Secret peut exister et être monté, mais l'application échoue à l'utiliser en raison de la connectivité en aval (par exemple, impossible d'atteindre l'hôte de la base de données) ou d'un RBAC insuffisant pour lire le Secret. Vérifiez que le ServiceAccount a les droits get et list sur secrets dans l'espace de noms :

kubectl auth can-i get secrets -n production --as=system:serviceaccount:production:api-server
# yes

Modes de défaillance et procédures de récupération

1. Secret introuvable / Échec de montage

Symptôme : Pod bloqué dans ContainerCreating ; les événements affichent MountVolume.SetUp failed for volume "secret-volume" : secret "db-credentials" not found.

Diagnostic :

kubectl get secret db-credentials -n production
# Error from server (NotFound): secrets "db-credentials" not found

Récupération :

  • Recréez le Secret à partir de la sauvegarde ou de la source de vérité (Vault, SealedSecret, dépôt GitOps).
  • Si vous utilisez SealedSecrets, déchiffrez le Secret scellé :
  kubeseal --fetch-cert --controller-name=sealed-secrets -n kube-system > pub.pem
  kubeseal --cert pub.pem --format yaml < db-credentials.yaml > db-credentials-sealed.yaml
  kubectl apply -f db-credentials-sealed.yaml
  • Confirmez que le pod récupère :
  kubectl delete pod -n production -l app=api  # Force la recréation avec le nouveau Secret
  kubectl rollout status deployment/api-server -n production

2. Incompatibilité de clé entre le Secret et l'attente du conteneur

Symptôme : L'application journalise KeyError: 'DATABASE_PASSWORD' ou démarre avec une variable d'environnement vide.

Diagnostic :

kubectl get secret db-credentials -n production -o jsonpath='{.data}' | jq -r 'keys[]'
# DB_HOST
# DB_PORT
# DB_USER
# DB_PASS   <-- Note : la clé est DB_PASS, pas DB_PASSWORD

Récupération :

  • Option A : Mettez à jour le Secret pour inclure la clé attendue (préféré pour la compatibilité descendante) :
  kubectl patch secret db-credentials -n production -p '{"stringData":{"DB_PASSWORD":"S3cur3P@ssw0rd!"}}'
  • Option B : Mettez à jour la référence env du Deployment pour qu'elle corresponde à la clé existante et redéployez.

3. Identifiants mis en cache obsolètes après rotation

Symptôme : L'application continue d'utiliser l'ancien mot de passe après la mise à jour du Secret ; les journaux de la base de données montrent des échecs d'authentification pour l'ancien utilisateur.

Cause racine : Le pod monte le Secret comme un volume mais l'application lit le fichier seulement au démarrage. Kubernetes met à jour le fichier sur place (écriture atomique via échange de lien symbolique), mais l'application conserve un descripteur de fichier ouvert ou met la valeur en cache.

Récupération :

  • Redémarrez le pod pour forcer la relecture :
  kubectl rollout restart deployment/api-server -n production
  • Pour une rotation sans temps d'arrêt, implémentez un gestionnaire de rechargement SIGHUP dans l'application ou utilisez un sidecar (par exemple, stakater/reloader) qui surveille les changements de Secret et déclenche des redémarrages progressifs.

4. Expiration ou incompatibilité de certificat TLS

Symptôme : Le contrôleur d'ingress journalise x509: certificate signed by unknown authority ou les clients signalent CERT_DATE_INVALID.

Diagnostic :

kubectl get secret tls-ingress-cert -n production -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -dates -subject -issuer
# notBefore=Nov 10 00:00:00 2023 GMT
# notAfter=Nov 10 00:00:00 2024 GMT
# subject=CN = api.example.com
# issuer=CN = Let's Encrypt Authority X3

Récupération :

  • Si vous utilisez cert-manager, déclenchez le renouvellement :
  kubectl annotate certificate tls-ingress-cert -n production cert-manager.io/force-renewal="$(date +%s)" --overwrite
  • Pour les certificats manuels, générez un nouveau Secret avec la paire cert/clé renouvelée et mettez à jour spec.tls[0].secretName de l'Ingress.

5. Mauvaise configuration du chiffrement au repos

Symptôme : Après la mise à niveau du plan de contrôle, les Secrets deviennent illisibles ; kubectl get secret retourne des données brouillées ou Error from server (InternalError): Internal error occurred: failed to decrypt.

Diagnostic : Le encryption-provider-config sur le serveur API pointe vers une clé KMS qui a été supprimée ou tournée sans mettre à jour la configuration.

Récupération :

  • Restaurez la clé KMS ou mettez à jour la configuration de chiffrement pour utiliser une clé valide, puis redémarrez kube-apiserver (redémarrage progressif sur les clusters gérés).
  • Si les données sont perdues, restaurez les Secrets à partir de la sauvegarde etcd ou de la source GitOps.

Liste de contrôle opérationnelle

Utilisez cette liste lors de la réponse aux incidents ou des audits de routine :

  • [ ] Inventaire : kubectl get secrets -n <ns> -o wide capturé ; types, âges et étiquettes des Secrets documentés.
  • [ ] Correspondance des références : Chaque spécification Deployment/StatefulSet/Pod liste envFrom.secretRef ou volumeMounts avec les noms et clés exacts des Secrets.
  • [ ] Validation par essai à sec : Tous les changements de Secrets générés avec --dry-run=client -o yaml et validés dans Git avant l'application.
  • [ ] Exercice de rotation : Test trimestriel de rotation de mot de passe utilisant le motif Secret v2 + déploiement ; mesurez le MTTR.
  • [ ] Santé des External Secrets : kubectl get externalsecret -A montre tous Ready=True ; dernière synchronisation < 1 heure.
  • [ ] Surveillance des certificats : kubectl get certificates -A (cert-manager) ou script personnalisé vérifie notAfter < 30 jours ; alerte déclenchée.
  • [ ] Audit RBAC : kubectl auth can-i get secrets -n <ns> --as=system:serviceaccount:<ns>:<sa> retourne yes uniquement pour les charges de travail requises.
  • [ ] Vérification des sauvegardes : Sauvegarde SealedSecrets ou Velero des Secrets de l'espace de noms testée dans un cluster de staging au cours des 30 derniers jours.
  • [ ] Documentation : Le runbook renvoie à cet article, inclut les commandes spécifiques au cluster (par exemple, procédure de débogage de nœud pour cluster géré).

Conclusion

Le dépannage des Secrets Kubernetes n'est pas une seule commande mais une boucle disciplinée : observer l'état en direct, le comparer à l'intention déclarée, isoler le plus petit changement qui comble l'écart et vérifier le résultat avant de déclarer le succès. Les incidents les plus coûteux proviennent de l'omission de l'étape d'inventaire — supposer que le Secret existe, a les bonnes clés et est correctement monté — pour découvrir ensuite une incompatibilité de clé silencieuse ou un cache obsolète après une rotation. En traitant les Secrets comme des artefacts versionnés, en les validant au repos et à l'exécution, et en répétant la rotation et la récupération, vous transformez une source fréquente de pannes en un processus prévisible et auditable. Commencez votre prochain audit en exécutant les commandes d'inventaire de ce guide sur un espace de noms critique ; les écarts que vous trouverez seront ceux qui comptent.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO