Introduction
Les Secrets Kubernetes stockent des informations sensibles telles que des mots de passe, des jetons et des clés TLS. Si un Secret est mal configuré, divulgué ou indisponible, les applications échouent ou les informations d'identification peuvent être compromises. Surveiller les Secrets ne consiste pas à exposer leur contenu. Il s'agit de détecter quand ils sont créés, mis à jour, supprimés ou ne parviennent pas à être montés correctement, et quand les modèles d'accès semblent suspects.
Ce guide couvre la surveillance pratique des Secrets pour les développeurs, les ingénieurs DevOps, les SRE et les équipes plateforme. Il relie les alertes, les métriques, les tableaux de bord et la réponse aux incidents à des commandes réelles, des sorties attendues et des décisions de récupération. L'accent est mis sur la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, éviter de journaliser les valeurs des secrets, vérifier les résultats et documenter les chemins de récupération.
Vous trouverez des exemples concrets pour les journaux d'audit Kubernetes, le Metrics Server, Prometheus, Alertmanager, Grafana et un playbook de réponse aux incidents étape par étape. Chaque exemple suppose un cluster fonctionnel avec kubectl configuré et, le cas échéant, Prometheus ou Grafana installé.
Inventaire de la version et de l'environnement
Avant de surveiller les Secrets, connaissez votre environnement. Commencez par des observations en lecture seule pour établir l'état actuel. Cela évite des erreurs comme appliquer un correctif au mauvais cluster ou supposer qu'une fonctionnalité est disponible alors qu'elle ne l'est pas.
Vérifier la version de Kubernetes
kubectl version --short
Exemple de sortie attendue :
Client Version: v1.28.2
Server Version: v1.28.4
Certaines fonctionnalités de surveillance des Secrets, telles que les politiques de journal d'audit ou les Secrets Immutable, dépendent de la version du serveur API. Par exemple, les Secrets Immutable sont devenus stables dans Kubernetes 1.21. Si votre cluster est plus ancien, ne vous fiez pas à ce champ.
Lister les Secrets existants
kubectl get secrets --all-namespaces
Exemple de sortie :
NAMESPACE NAME TYPE DATA AGE
default my-app-secret Opaque 2 3d
kube-system default-token-abcde kubernetes.io/service-account-token 3 180d
Notez l'espace de noms, le nom, le type, le nombre de clés de données et l'âge. Un Secret récemment créé dans un espace de noms sensible peut mériter une inspection plus approfondie.
Inspecter sans révéler les valeurs
N'exécutez jamais kubectl get secret -o yaml à la légère, car cela imprime des valeurs encodées en base64 qui peuvent être décodées. À la place, listez uniquement les clés :
kubectl get secret my-app-secret -n default -o jsonpath='{.data}' | jq 'keys'
Exemple de sortie :
[
"password",
"username"
]
Cela confirme que le Secret existe et possède les clés attendues sans exposer les données.
Vérifier l'état du montage
Si une application utilise un Secret, vérifiez qu'il est monté correctement. Trouvez le pod :
kubectl get pods -n default -l app=my-app
Puis inspectez les montages de volume :
kubectl describe pod <pod-name> -n default | grep -A 5 Mounts
Exemple de sortie :
Mounts:
/etc/app-secrets from secret-volume (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-xxxxx (ro)
Si le point de montage est absent, le Secret peut ne pas être référencé dans la spécification du pod.
Chemin de configuration sûr
Les changements de configuration de la surveillance des Secrets doivent être incrémentaux. Commencez par des métriques en lecture seule et des journaux d'audit avant d'activer des alertes bloquantes.
Activer la journalisation d'audit
Les journaux d'audit Kubernetes enregistrent toutes les requêtes API, y compris celles concernant les Secrets. Configurez le serveur API avec un fichier de politique d'audit qui journalise l'accès aux Secrets au niveau Metadata ou supérieur. Un fichier de politique minimal :
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets"]
Appliquez la politique au serveur API (cela nécessite les drapeaux kube-apiserver --audit-policy-file et --audit-log-path). Testez ensuite en listant les Secrets :
kubectl get secrets
Vérifiez le journal d'audit pour les entrées :
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"...","stage":"ResponseComplete","requestURI":"/api/v1/secrets","verb":"list","user":{"username":"admin"},"sourceIPs":["10.0.0.1"],"responseStatus":{"code":200}}
Cela vous donne une piste sans journaliser les données des secrets.
Utiliser un compte de service dédié
Créez un compte de service dédié pour les outils de surveillance avec le moindre privilège. Par exemple :
apiVersion: v1
kind: ServiceAccount
metadata:
name: secret-monitor
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-monitor-role
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: secret-monitor-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: secret-monitor-role
subjects:
- kind: ServiceAccount
name: secret-monitor
namespace: monitoring
Appliquez-le :
kubectl apply -f secret-monitor-rbac.yaml
Testez l'accès depuis le compte de service :
kubectl auth can-i list secrets --as=system:serviceaccount:monitoring:secret-monitor
Attendu : yes
Tester dans un espace de noms hors production
Avant de modifier la production, créez un Secret de test dans un espace de noms de bac à sable et vérifiez que votre pile de surveillance le détecte.
Vérification et diagnostic
Avec l'observation de base en place, collectez des métriques et mettez en place des diagnostics qui révèlent la santé de l'utilisation des Secrets.
Métriques du serveur API
Le serveur API Kubernetes expose des métriques sur les requêtes, y compris les opérations sur les Secrets. Si vous avez Prometheus qui collecte le serveur API, les métriques utiles incluent :
apiserver_request_total{resource="secrets"}apiserver_request_duration_seconds_bucket{resource="secrets"}
Par exemple, une requête PromQL pour voir le taux de requêtes de liste de Secrets sur 5 minutes :
rate(apiserver_request_total{resource="secrets", verb="list"}[5m])
Cela peut indiquer une activité inhabituelle si le taux augmente.
Vérifier les pods avec des Secrets montés
Utilisez kubectl pour trouver les pods qui montent un Secret particulier. Cela aide à diagnostiquer pourquoi une mise à jour de Secret n'est pas répercutée (les pods ont souvent besoin d'un redémarrage pour prendre en compte les modifications des Secrets montés) :
kubectl get pods --all-namespaces -o json | jq -r '.items[] | select(.spec.volumes[]?.secret.secretName == "my-app-secret") | .metadata.namespace + "/" + .metadata.name'
Exemple de sortie :
default/my-app-7d4f8b9c6-abcde
default/my-app-7d4f8b9c6-fghij
Inspecter les événements
Les événements capturent souvent les problèmes liés aux Secrets, tels que les échecs de montage :
kubectl get events --all-namespaces --field-selector reason=FailedMount
Exemple de sortie :
NAMESPACE LAST SEEN TYPE REASON OBJECT MESSAGE
default 2m Warning FailedMount pod/my-app-... MountVolume.SetUp failed for volume "secret-volume" : secret "my-app-secret" not found
Cela vous indique immédiatement que le Secret est manquant.
Utiliser des règles d'alerte Prometheus
Définissez des règles d'alerte pour les opérations sur les Secrets. Par exemple, alertez si un Secret est supprimé de manière inattendue :
groups:
- name: kubernetes-secrets
rules:
- alert: SecretDeleted
expr: increase(apiserver_request_total{resource="secrets", verb="delete"}[10m]) > 0
for: 1m
labels:
severity: critical
annotations:
summary: "Secret supprimé au cours des 10 dernières minutes"
description: "Une requête de suppression de Secret a été observée. Enquêtez immédiatement."
Testez l'alerte en supprimant un Secret de test et en vérifiant Alertmanager.
Modes de défaillance et récupération
Les Secrets échouent de manière prévisible. Connaître les modes de défaillance vous aide à détecter et à récupérer rapidement.
Mode de défaillance 1 : Secret introuvable
Symptôme : Les pods ne démarrent pas avec des événements FailedMount référençant un Secret manquant.
Diagnostic : Vérifiez l'espace de noms et le nom du Secret :
kubectl get secrets -n <namespace> | grep <secret-name>
S'il n'est pas trouvé, le Secret peut avoir été supprimé ou créé dans un autre espace de noms.
Récupération : Recréez le Secret à partir d'une source fiable. Si vous utilisez un contrôle de version ou un gestionnaire de secrets, appliquez le manifeste :
kubectl apply -f secret.yaml
Puis redémarrez les pods affectés :
kubectl rollout restart deployment <deployment-name>
Mode de défaillance 2 : Données de Secret incorrectes
Symptôme : L'application se connecte à une base de données mais obtient des erreurs d'authentification. Le Secret existe mais contient des valeurs incorrectes.
Diagnostic : Comparez les clés de données et, sans imprimer les valeurs, vérifiez l'encodage base64 ou le hachage. Si possible, vérifiez les journaux d'application pour des indices sans exposer les secrets.
Récupération : Mettez à jour le Secret avec des valeurs correctes en utilisant une méthode sécurisée. Par exemple, créez à partir de littéraux :
kubectl create secret generic my-app-secret --from-literal=username=correct-user --from-literal=password='correct-password' --dry-run=client -o yaml | kubectl apply -f -
Puis redémarrez les pods.
Mode de défaillance 3 : Rotation de Secret non répercutée
Symptôme : Après avoir fait tourner un secret dans un système externe, l'application utilise toujours les anciennes informations d'identification. Cela arrive souvent parce que les pods mettent en cache les Secrets.
Diagnostic : Vérifiez l'heure de démarrage du pod et l'âge du Secret :
kubectl get pod <pod-name> -o jsonpath='{.metadata.creationTimestamp}'
kubectl get secret <secret-name> -o jsonpath='{.metadata.creationTimestamp}'
Si le pod est plus ancien que la mise à jour du Secret, il utilise l'ancien volume monté.
Récupération : Redémarrez les pods pour remonter le Secret mis à jour :
kubectl rollout restart deployment <deployment-name>
Si vous utilisez un Secret avec immutable: true, vous devez supprimer et recréer le pod ou utiliser un nouveau nom de Secret.
Mode de défaillance 4 : Accès non autorisé ou fuite
Symptôme : Les journaux d'audit montrent des requêtes get ou list inattendues pour les Secrets provenant d'un utilisateur ou d'une IP inconnue.
Diagnostic : Examinez les journaux d'audit :
{"verb":"get","resource":"secrets","user":{"username":"system:serviceaccount:default:compromised-sa"},"sourceIPs":["203.0.113.50"]}
Récupération : Révoquez immédiatement le compte de service ou les informations d'identification de l'utilisateur, faites tourner les Secrets affectés et enquêtez sur l'IP source. Appliquez une politique réseau pour restreindre l'accès au serveur API si nécessaire.
Tableau de bord et surveillance continue
Un tableau de bord donne une vue d'ensemble de la santé et de l'activité des Secrets. Utilisez Grafana avec la source de données Prometheus.
Exemples de panneaux Grafana
Panneau 1 : Secrets créés/supprimés (dernières 24 heures)
sum(increase(apiserver_request_total{resource="secrets", verb="create"}[24h])) by (namespace)
Panneau 2 : Taux de lecture des Secrets par utilisateur
sum by (user) (rate(apiserver_request_total{resource="secrets", verb="get"}[5m]))
Panneau 3 : Pods avec échecs de montage de Secrets
Cela nécessite un exportateur personnalisé ou l'utilisation de kube-state-metrics. Kube-state-metrics expose kube_pod_container_status_waiting_reason pour CrashLoopBackOff, mais pour les échecs de montage de Secrets, vous devrez peut-être analyser les événements ou utiliser une métrique personnalisée. Sinon, utilisez le tableau de bord basé sur les journaux Elasticsearch ou Loki suivant si vous collectez des événements.
Exemple d'alerte : Échec de montage de Secret
Si vous collectez les événements Kubernetes dans Prometheus via un exportateur comme eventrouter, vous pouvez créer une alerte :
- alert: SecretMountFailed
expr: increase(kube_event_count{reason="FailedMount", involved_object_kind="Pod"}[10m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Des pods échouent à monter un Secret"
Utiliser kube-state-metrics
Kube-state-metrics fournit une métrique kube_secret_created et kube_secret_info. Vous pouvez alerter sur des Secrets nouveaux inattendus :
increase(kube_secret_created[1h]) > 3
Cela pourrait être un signe de mauvaise configuration ou d'attaque.
Liste de contrôle des opérations
Utilisez cette liste de contrôle dans le cadre de votre revue hebdomadaire des opérations. Attribuez chaque élément à un propriétaire et définissez une fréquence de révision. Par exemple, « Priya Shah, responsable de l'ingénierie » est propriétaire de la revue de surveillance des Secrets, et la revue a lieu tous les lundis matin.
Vérifications quotidiennes (automatisées)
- [ ] Alertmanager n'a aucune alerte critique active pour les opérations sur les Secrets.
- [ ] Le tableau de bord Grafana ne montre aucun pic inattendu dans les lectures de Secrets.
- [ ] L'échantillon du journal d'audit ne montre aucune tentative d'accès non autorisé aux Secrets.
- [ ] Tous les pods avec des Secrets montés sont en état Running et ne redémarrent pas en boucle.
Vérifications hebdomadaires (revue manuelle)
- [ ] Examiner la liste des Secrets créés ou supprimés au cours de la semaine écoulée. Propriétaire : Priya Shah, responsable de l'ingénierie. À revoir chaque semaine.
- [ ] Confirmer que les Secrets ayant fait l'objet d'une rotation ont été mis à jour et que les pods ont redémarré. Propriétaire : Marcus Chen, ingénieur DevOps.
- [ ] Vérifier les Secrets obsolètes non utilisés par aucun pod. Utilisez :
kubectl get secrets --all-namespaces -o json | jq -r '.items[] | select(.metadata.ownerReferences == null) | .metadata.namespace + "/" + .metadata.name'
Vérifiez ensuite s'ils sont nécessaires.
- [ ] Examiner les permissions RBAC pour l'accès aux Secrets et supprimer les comptes de service inutilisés. Propriétaire : Aisha Patel, ingénieure sécurité.
Audit mensuel (équipe de sécurité)
- [ ] Auditer toutes les règles du journal d'audit pour leur exhaustivité et les ajuster si nécessaire.
- [ ] Effectuer un exercice simulé de fuite de Secret pour tester la réponse aux incidents.
- [ ] Faire tourner tous les Secrets statiques de plus de 90 jours.
- [ ] Évaluer l'intégration d'une gestion externe des secrets (par exemple, Vault, AWS Secrets Manager) si elle n'est pas déjà utilisée.
Pièges courants et comment les éviter
Piège 1 : Journaliser les valeurs des Secrets
Pourquoi cela arrive : Les développeurs utilisent kubectl get secret -o yaml pour le débogage et la sortie est capturée dans les journaux ou la sortie CI.
Comment l'éviter : N'utilisez jamais -o yaml sur les Secrets. Utilisez kubectl get secret <name> -o jsonpath='{.data}' pour lister uniquement les clés. Masquez les secrets dans les journaux et configurez les systèmes CI pour masquer les valeurs sensibles.
Piège 2 : Supposer que les mises à jour des Secrets se propagent instantanément
Pourquoi cela arrive : Les équipes font tourner un Secret et s'attendent à ce que tous les pods utilisent la nouvelle valeur immédiatement. Cependant, les Secrets montés ne sont mis à jour que périodiquement par le kubelet (si vous utilisez des variables d'environnement, ils ne sont jamais mis à jour).
Comment l'éviter : Considérez les mises à jour de Secrets comme nécessitant un redémarrage du pod. Utilisez un déploiement ou un outil comme Reloader pour automatiser les redémarrages.
Piège 3 : Ne pas surveiller les accès non autorisés
Pourquoi cela arrive : La surveillance se concentre sur la santé des pods mais pas sur les journaux d'audit du serveur API, donc quelqu'un peut exfiltrer des Secrets sans être remarqué.
Comment l'éviter : Activez la journalisation d'audit avec le niveau Metadata pour les Secrets, et configurez des alertes pour les modèles d'accès inhabituels (par exemple, un utilisateur accédant à de nombreux Secrets en peu de temps).
Piège 4 : RBAC trop large
Pourquoi cela arrive : Pour simplifier, les équipes accordent get et list sur tous les Secrets à de nombreux comptes de service.
Comment l'éviter : Utilisez le moindre privilège. N'accordez l'accès en lecture aux Secrets qu'aux composants qui en ont absolument besoin. Utilisez des comptes de service distincts par application et évitez les permissions de lecture à l'échelle du cluster.
Piège 5 : Fatigue des alertes
Pourquoi cela arrive : Les alertes sont trop bruyantes, comme alerter à chaque création de Secret, ce qui pousse les équipes à les ignorer.
Comment l'éviter : Ajustez les seuils d'alerte en fonction du comportement normal. Utilisez des clauses for pour exiger que la condition persiste, et distinguez entre gravité d'avertissement et critique.
Conclusion
La surveillance des Secrets Kubernetes est essentielle pour la sécurité et la fiabilité. Elle nécessite une combinaison de journalisation d'audit, de métriques, d'alertes et de tableaux de bord, le tout enveloppé dans un processus opérationnel sûr. Commencez par des observations en lecture seule, mettez en œuvre des alertes progressivement et protégez toujours les valeurs des secrets contre toute exposition.
En suivant les étapes pratiques de ce guide, vous pouvez détecter les défaillances, les accès non autorisés et la dérive de configuration avant qu'ils ne causent des incidents. Attribuez clairement la propriété des tâches de surveillance et révisez-les régulièrement pour maintenir l'efficacité du système. Utilisez la liste de contrôle des opérations pour vous assurer que rien n'est manqué, et affinez continuellement vos alertes au fur et à mesure que votre cluster grandit.
Derniers mots
La surveillance des Secrets Kubernetes n'a pas besoin d'être complexe. Commencez par les bases : connaissez votre environnement, activez les journaux d'audit, configurez Prometheus et Grafana, et créez quelques alertes significatives. À mesure que votre confiance grandit, étendez-vous à la rotation automatisée et à la gestion externe des secrets. La clé est de faire de la surveillance une habitude, pas une réflexion après coup.