## 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 \
 --docker-email=user@example.com \
 -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 yaml dans un terminal partagé ou enregistré. Les valeurs base64 peuvent être décodées instantanément. Préférez kubectl describe secret pour les noms de clés ou jq pour 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-config sur 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 role et kubectl create rolebinding pour accorder l'accès à des secrets ou namespaces spécifiques. Exemple pour autoriser un compte de service à lire uniquement le secret db-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 .gitignore pour *-secret.yaml , ou utilisez des modèles avec sealed secrets ou des opérateurs de secrets externes pour les workflows GitOps.

- Définissez immutable: true sur 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> et kubectl 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 -- sh -c 'test -n "$VAR" && echo set'

- [ ] Pour les montages en volume, vérifiez les permissions et le contenu des fichiers : kubectl exec -- ls -l /path

- [ ] Définissez immutable: true si 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.