Introduction
Kubernetes Secrets permet de stocker et de gérer des données sensibles — mots de passe, jetons d'API, certificats TLS et identifiants de registre — séparément du code applicatif. Cet article propose un guide pratique axé sur les commandes pour les opérations de base liées aux Secrets Kubernetes dans le travail quotidien. Plutôt que de simplement énumérer des options, chaque section présente une commande réaliste, la sortie attendue, les signes d'échec courants et l'action de récupération.
Nous aborderons la vérification de l'environnement, la création de secrets à partir de valeurs littérales et de fichiers, l'inspection des secrets sans les exposer, la consommation des secrets dans des pods sous forme de variables d'environnement et de fichiers montés, la mise à jour et la rotation des secrets, le dépannage des échecs de montage, et l'application de bonnes pratiques opérationnelles.
Prérequis : un cluster Kubernetes en cours d'exécution, kubectl configuré avec un kubeconfig valide, et une familiarité de base avec les pods et les déploiements. Les exemples utilisent la syntaxe de Kubernetes 1.24, mais les commandes fonctionnent à partir de la version 1.19. Si vous utilisez un cluster géré, adaptez les chemins locaux et vérifiez vos autorisations RBAC (Role-Based Access Control, contrôle d'accès basé sur les rôles).
Vérifiez votre environnement et vos autorisations RBAC avant de manipuler des secrets
Avant de créer ou de modifier un secret, confirmez le cluster et le namespace cibles. Un incident courant consiste à appliquer un secret dans le mauvais namespace ou sur le mauvais cluster.
Exécutez :
kubectl config current-context
kubectl cluster-info
kubectl version --short
Sortie attendue pour le contexte actuel :
gke_my-project_us-central1_cluster-1
Kubernetes control plane is running at https://34.123.45.67
Client Version: v1.24.0
Server Version: v1.24.0
Vérifiez vos autorisations pour les secrets dans le namespace cible :
kubectl auth can-i create secrets --namespace default
kubectl auth can-i get secrets --namespace default
Sortie attendue :
yes
yes
Si vous obtenez no, demandez à un administrateur le rôle RBAC minimal requis ; n'utilisez pas cluster-admin pour les opérations quotidiennes sur les secrets.
Créer un secret à partir de valeurs littérales
La façon la plus rapide de créer un secret est d'utiliser kubectl create secret generic avec l'option --from-literal. Ne placez jamais la valeur du secret dans la commande après --from-literal si l'historique du shell est activé ; utilisez --from-literal=password=$DB_PASSWORD après vous être assuré que la variable d'environnement n'est pas journalisée, ou privilégiez la création à partir de fichiers dans les scripts.
Exemple :
kubectl create secret generic db-credentials \
--from-literal=username=app_user \
--from-literal=password='S3cret!Value#2024' \
--namespace default
Sortie attendue :
secret/db-credentials created
Vérifiez que le secret existe et affiche une taille de données plutôt que le contenu en clair :
kubectl get secret db-credentials -n default
Sortie :
NAME TYPE DATA AGE
db-credentials Opaque 2 15s
kubectl describe secret db-credentials -n default affiche uniquement les noms de clés et la taille en octets, pas les valeurs :
Name: db-credentials
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 19 bytes
username: 8 bytes
Cela est sûr pour un terminal, mais kubectl get secret -o yaml imprimera la valeur encodée en base64 ; évitez donc cela dans les sessions partagées.
Créer un secret à partir d'un fichier ou d'un fichier d'environnement
Pour des valeurs plus longues comme des certificats TLS ou des fichiers de configuration, créez des secrets à partir de fichiers. Le nom du fichier devient la clé du secret par défaut.
# Créer un fichier contenant le mot de passe
echo -n 'P@ssw0rdFile' > ./db-password.txt
kubectl create secret generic file-secret \
--from-file=./db-password.txt \
-n default
Sortie :
secret/file-secret created
Le secret contient désormais la clé db-password.txt. Pour utiliser une clé différente, spécifiez --from-file=password=./db-password.txt.
Pour un groupe de variables de type environnement, utilisez --from-env-file :
cat <<EOF > ./app.env
API_KEY=abcd1234
TOKEN=token-9876
EOF
kubectl create secret generic env-secret \
--from-env-file=./app.env \
-n default
Le secret env-secret contient maintenant les clés API_KEY et TOKEN.
Créer un secret à partir d'un manifeste YAML
La création déclarative est préférable pour le contrôle de version et la répétabilité. Voici un manifeste de secret générique :
apiVersion: v1
kind: Secret
metadata:
name: app-secret
namespace: default
type: Opaque
data:
username: YXBwX3VzZXI=
password: UzNjcmV0IVZhbHVlIzIwMjQ=
Les valeurs dans data doivent être encodées en base64. Pour générer la valeur encodée sans historique du shell :
echo -n 'app_user' | base64
echo -n 'S3cret!Value#2024' | base64
Sortie :
YXBwX3VzZXI=
UzNjcmV0IVZhbHVlIzIwMjQ=
Si vous préférez le texte en clair dans le manifeste, utilisez stringData au lieu de data. Kubernetes l'encode automatiquement à la création :
apiVersion: v1
kind: Secret
metadata:
name: app-secret
namespace: default
type: Opaque
stringData:
username: app_user
password: S3cret!Value#2024
Appliquez le manifeste :
kubectl apply -f app-secret.yaml
Sortie :
secret/app-secret created
Le type de secret Opaque est utilisé pour des données arbitraires définies par l'utilisateur. D'autres types courants incluent kubernetes.io/dockerconfigjson pour les identifiants de registre et kubernetes.io/tls pour les certificats TLS. Créez-les avec des commandes dédiées :
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=myuser \
--docker-password=mypassword \
[email protected] \
-n default
kubectl create secret tls my-tls-secret \
--cert=path/to/tls.crt \
--key=path/to/tls.key \
-n default
Sorties attendues respectivement :
secret/regcred created
secret/my-tls-secret created
Inspecter les secrets en toute sécurité
Pour lister tous les secrets d'un namespace :
kubectl get secrets -n default
Sortie :
NAME TYPE DATA AGE
app-secret Opaque 2 5m
db-credentials Opaque 2 10m
file-secret Opaque 1 4m
regcred kubernetes.io/dockerconfigjson 1 2m
my-tls-secret kubernetes.io/tls 2 1m
Pour voir les clés contenues dans un secret sans exposer les valeurs, utilisez :
kubectl get secret db-credentials -n default -o jsonpath='{.data}' | jq 'keys'
Si vous n'avez pas jq, utilisez :
kubectl get secret db-credentials -n default -o jsonpath='{range $k, $v := .data}{$k}{"\n"}{end}'
Sortie attendue :
password
username
Pour récupérer une seule valeur et la décoder localement :
kubectl get secret db-credentials -n default -o go-template='{{ .data.password | base64decode }}'
Si votre version de kubectl prend en charge la fonction base64decode (1.18+). Sinon :
kubectl get secret db-credentials -n default -o jsonpath='{.data.password}' | base64 -d
Sortie :
S3cret!Value#2024
Veillez à ne pas rediriger cette sortie vers un fichier susceptible d'être versionné.
Utiliser les secrets dans un pod comme variables d'environnement
Créez un déploiement qui injecte une valeur de secret comme variable d'environnement. C'est la méthode la plus simple pour les applications qui lisent leur configuration depuis l'environnement.
Exemple de manifeste de déploiement :
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: app
image: nginx:1.25
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
Appliquez :
kubectl apply -f webapp-deployment.yaml
kubectl rollout status deployment/webapp -n default
Sortie attendue du rollout :
deployment "webapp" successfully rolled out
Pour vérifier que la variable d'environnement est définie dans le conteneur sans imprimer le secret dans les journaux, vous pouvez consulter la spécification du pod ou utiliser une commande temporaire qui vérifie uniquement la présence du nom de variable :
kubectl exec deployment/webapp -- printenv DB_USER
Sortie :
app_user
Pour éviter d'imprimer le mot de passe, utilisez :
kubectl exec deployment/webapp -- sh -c 'test -n "$DB_PASSWORD" && echo "DB_PASSWORD is set"'
Sortie attendue :
DB_PASSWORD is set
Si la clé du secret est absente, le pod échouera avec CreateContainerConfigError. Nous couvrons le dépannage dans une section ultérieure.
Monter un secret comme volume de fichiers
Pour les applications qui attendent des fichiers de configuration, montez le secret comme volume. Chaque clé devient un fichier dans le chemin de montage.
Exemple de fragment de pod :
apiVersion: v1
kind: Pod
metadata:
name: secret-volume-pod
namespace: default
spec:
containers:
- name: app
image: busybox:1.36
command: ["sleep", "3600"]
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-credentials
Appliquez et exécutez une commande pour lister les fichiers montés :
kubectl apply -f secret-volume-pod.yaml
kubectl exec secret-volume-pod -- ls -l /etc/secrets
Sortie attendue :
total 0
lrwxrwxrwx 1 root root 13 Mar 10 10:00 password -> ..data/password
lrwxrwxrwx 1 root root 16 Mar 10 10:00 username -> ..data/username
Les liens symboliques pointent vers la version actuelle des données du secret, ce qui permet à Kubernetes de mettre à jour le montage lorsque le secret change (pour les volumes, pas pour les variables d'environnement). Vous pouvez lire un fichier :
kubectl exec secret-volume-pod -- cat /etc/secrets/username
Sortie :
app_user
Pour monter uniquement une clé spécifique ou définir des permissions de fichier, utilisez items et defaultMode dans la définition du volume :
volumes:
- name: secret-volume
secret:
secretName: db-credentials
items:
- key: username
path: db-username
defaultMode: 0400
Le fichier /etc/secrets/db-username contiendra alors le nom d'utilisateur et aura les permissions 0400 (lecture uniquement par le propriétaire). Cela est utile dans des contextes de sécurité stricts.
Mettre à jour et faire la rotation d'un secret
Les secrets sont immuables dans certaines versions de Kubernetes si vous définissez immutable: true, mais par défaut ils sont modifiables. Pour mettre à jour un secret sans modifier manuellement les valeurs base64, régénérez un nouveau manifeste et appliquez-le.
Méthode 1 : Utilisez kubectl create secret avec --dry-run=client pour produire le YAML, puis appliquez :
kubectl create secret generic db-credentials \
--from-literal=username=app_user \
--from-literal=password='NewP@ssword#2024' \
--dry-run=client -o yaml | kubectl apply -f -
Sortie :
secret/db-credentials configured
Méthode 2 : Modifiez avec kubectl edit secret db-credentials -n default et changez manuellement la valeur base64. Cette méthode est sujette aux erreurs ; à utiliser uniquement pour des correctifs rapides avec vérification immédiate.
Après la mise à jour d'un secret, les déploiements qui le consomment comme variable d'environnement ne redémarrent pas automatiquement. Déclenchez un redémarrage progressif :
kubectl rollout restart deployment/webapp -n default
kubectl rollout status deployment/webapp -n default
Pour un secret monté en volume, le kubelet met généralement à jour les fichiers montés dans un délai d'une minute sans redémarrage. Cependant, l'application doit surveiller les changements de fichiers ou être redémarrée. Par sécurité, effectuez un redémarrage progressif après toute rotation de secret qui affecte des charges de travail en cours d'exécution.
Résoudre les échecs courants liés aux secrets
1. Le pod échoue avec CreateContainerConfigError
Si un pod référence une clé de secret qui n'existe pas, le conteneur ne peut pas démarrer. Décrivez le pod :
kubectl describe pod webapp-7c6f6f6c9-abcde -n default
Recherchez les événements :
Warning Failed 16s (x2 over 20s) kubelet Error: secret "db-credentials" not found
Warning Failed 16s kubelet Error: couldn't find key username in Secret default/db-credentials
Correctif : créez le secret ou corrigez le nom de la clé, puis supprimez le pod en échec (s'il n'est pas géré par un contrôleur) ou appliquez un manifeste corrigé.
2. Permission refusée lors de la lecture d'un secret monté
Si votre conteneur s'exécute en tant qu'utilisateur non root et que le volume de secret a des permissions par défaut 0644 ou 0600, mais que le propriétaire du fichier est root, l'application peut échouer avec permission denied en essayant de lire.
Exemple d'erreur dans les journaux de l'application :
open /etc/secrets/password: permission denied
Correctif : définissez defaultMode: 0444 dans la définition du volume de secret, ou définissez fsGroup dans le contexte de sécurité du pod pour que les fichiers soient lisibles par le groupe spécifié :
spec:
securityContext:
fsGroup: 2000
containers:
- name: app
...
Réappliquez ensuite et redémarrez le pod.
3. Problèmes de décodage base64
Lors de la création manuelle de secrets à partir de data, assurez-vous que la valeur est en base64 valide. Des commandes comme echo ajoutent un caractère de nouvelle ligne ; utilisez echo -n ou printf. Exemple d'encodage erroné :
echo 'password' | base64 # inclut une nouvelle ligne, produit cGFzc3dvcmQK
Le Cg== final ou la nouvelle ligne peut amener l'application à recevoir un caractère de nouvelle ligne supplémentaire. Utilisez :
printf 'password' | base64 # cGFzc3dvcmQ=
Si vous avez déjà créé le secret, inspectez la longueur décodée :
kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 -d | wc -c
Le nombre d'octets attendu doit correspondre à l'original ; s'il est supérieur d'un octet, c'est probablement une nouvelle ligne finale.
4. Secret référencé dans le mauvais namespace
Les secrets sont des objets à portée de namespace. Si un pod dans le namespace production référence db-credentials, le secret doit exister dans production, pas dans default. Confirmez :
kubectl get secret db-credentials -n production
S'il n'existe pas, créez-le dans le bon namespace ou ajustez le manifeste du pod pour utiliser le nom complet (ce qui n'est pas possible pour les références de secret ; elles doivent être dans le même namespace que le pod). L'accès inter-namespaces nécessite de copier le secret ou d'utiliser un contrôleur comme Kubernetes External Secrets.
Bonnes pratiques de sécurité et d'exploitation pour les opérations quotidiennes
- N'utilisez jamais
kubectl get secret -o yamldans un terminal partagé ou enregistré. Les valeurs base64 peuvent être décodées instantanément. Préférezkubectl describe secretpour les noms de clés oujqpour les clés.
- Activez le chiffrement au repos dans l'etcd de votre cluster. Sur les clusters gérés, c'est souvent un paramètre. Sur les clusters autogérés, configurez un plugin KMS ou utilisez au minimum
--encryption-provider-configsur l'API server. Cela protège les secrets si les sauvegardes etcd fuient.
- Appliquez le principe du moindre privilège avec RBAC. N'accordez l'accès en lecture aux secrets qu'aux comptes de service qui en ont besoin. Utilisez
kubectl create roleetkubectl create rolebindingpour accorder l'accès à des secrets ou namespaces spécifiques. Exemple pour autoriser un compte de service à lire uniquement le secretdb-credentials:
kubectl create role secret-reader --verb=get --verb=list --resource=secrets --resource-name=db-credentials -n default
kubectl create rolebinding secret-reader-binding --role=secret-reader --serviceaccount=default:my-app-sa -n default
- Évitez de versionner les secrets dans git. Utilisez
.gitignorepour*-secret.yaml, ou utilisez des modèles avec sealed secrets ou des opérateurs de secrets externes pour les workflows GitOps.
- Définissez
immutable: truesur les secrets qui ne sont pas censés changer. Cela empêche les mises à jour accidentelles et améliore les performances. Exemple :
apiVersion: v1
kind: Secret
metadata:
name: static-secret
immutable: true
data:
key: dmFsdWU=
- Faites régulièrement la rotation des secrets et testez que les applications récupèrent les nouvelles valeurs après un redémarrage. Utilisez un déploiement canari ou un pod qui lit le secret et vérifie la longueur.
Liste de contrôle opérationnelle pour la gestion quotidienne des secrets
Utilisez cette liste ordonnée lorsque vous travaillez avec les Secrets Kubernetes :
- [ ] Confirmez le contexte et le namespace actuels :
kubectl config current-context && kubectl config get-contexts - [ ] Vérifiez les autorisations RBAC :
kubectl auth can-i create secrets -n <namespace> - [ ] Capturez l'état actuel :
kubectl get secrets -n <namespace> -o name - [ ] Créez ou mettez à jour le secret à partir d'un fichier ou d'un manifeste, jamais depuis l'historique du shell s'il est sensible
- [ ] Vérifiez la création :
kubectl get secret <name> -n <namespace>etkubectl describe secret <name> -n <namespace> - [ ] Décodez un exemple de valeur pour confirmer qu'elle correspond au texte en clair attendu (dans un shell sécurisé)
- [ ] Appliquez le manifeste de pod ou de déploiement qui consomme le secret
- [ ] Vérifiez l'état du déploiement :
kubectl rollout status deployment/<name> -n <namespace> - [ ] Testez l'accès à l'intérieur du pod sans imprimer les secrets :
kubectl exec <pod> -- sh -c 'test -n "$VAR" && echo set' - [ ] Pour les montages en volume, vérifiez les permissions et le contenu des fichiers :
kubectl exec <pod> -- ls -l /path - [ ] Définissez
immutable: truesi le secret ne doit pas changer - [ ] Documentez le propriétaire du secret, l'intervalle de rotation et la procédure de récupération
Conclusion
Les commandes de base de Kubernetes Secrets deviennent utiles lorsqu'elles sont combinées à des habitudes sûres : vérifier le cluster cible, créer les secrets à partir de fichiers ou de manifestes, les inspecter sans exposer les valeurs, les consommer explicitement dans les pods et tester le résultat. Cet article a couvert les opérations fondamentales, de la création au dépannage, avec des commandes concrètes et des sorties attendues.
Comme prochaine étape, choisissez un secret à faible risque dans un namespace de développement et suivez le flux complet : créez-le à partir d'un manifeste, montez-le comme fichier, vérifiez les permissions, puis simulez une clé manquante pour observer le mode d'échec. Entraînez-vous à effectuer une rotation avec un redémarrage progressif et observez le comportement de l'application. Cet exercice pratique transformera ces commandes en une routine quotidienne fiable.