Aller au contenu principal
KubernetesDevOpsFormation

ConfigMaps et Secrets

30 min de lecture Apprendre Kubernetes — Chapitre 6

Externalise ta configuration avec les ConfigMaps et protège tes données sensibles avec les Secrets et Sealed Secrets.

Tu as une image Docker qui tourne nickel en dev. Tu la pousses en staging et… rien ne marche. L’URL de la base de données est en dur dans le code, le mot de passe aussi. Tu rebuilds l’image pour chaque environnement. Classique, et totalement évitable.

Kubernetes propose deux ressources pour séparer la configuration du code : les ConfigMaps pour la config non sensible, et les Secrets pour les données confidentielles. Ce chapitre t’apprend à les maîtriser — et surtout à éviter les erreurs que tout le monde fait en production.

Pourquoi c’est important

Le principe 12-Factor App est clair : la configuration doit vivre en dehors du code. En dur dans l’image Docker, ta config devient un boulet — tu rebuilds pour chaque changement, tu dupliques des images quasi identiques, et tu risques de leaker des credentials dans ton registry.

Avec les ConfigMaps et Secrets, tu obtiens :

  • Une seule image pour tous tes environnements (dev, staging, prod)
  • Des modifications à chaud sans rebuild ni redéploiement
  • Une séparation claire entre ce qui est sensible et ce qui ne l’est pas
  • Un workflow GitOps propre où la config est versionnée à côté des manifestes

🧠 À retenir : Une image Docker ne devrait jamais contenir de configuration spécifique à un environnement. Si tu changes d’env, tu changes la ConfigMap, pas l’image.

Comprendre le concept

ConfigMap : ta config externalisée

Un ConfigMap stocke des paires clé-valeur. Tu peux y mettre des variables simples (LOG_LEVEL=info) ou des fichiers entiers (un nginx.conf, un application.yml). Kubernetes les injecte dans tes Pods de deux façons : en variables d’environnement ou en fichiers montés via un volume.

Secret : le ConfigMap des données sensibles

Un Secret fonctionne exactement comme un ConfigMap, mais il est conçu pour les mots de passe, tokens API, certificats TLS et clés SSH. Les valeurs sont encodées en base64 dans le manifeste YAML.

⚠️ Attention : base64 n’est pas du chiffrement. N’importe qui avec kubectl get secret -o yaml peut décoder tes données. En production, active le chiffrement at rest d’etcd et restreins les accès RBAC.

Sealed Secrets : le chaînon manquant pour GitOps

Tu veux stocker tes manifestes dans Git mais les Secrets contiennent des données en clair ? Sealed Secrets résout ce problème. Un outil CLI (kubeseal) chiffre tes Secrets avec une clé publique. Seul le contrôleur installé dans le cluster peut les déchiffrer. Le fichier chiffré est safe pour Git.

Commandes essentielles

Voici comment créer et consommer des ConfigMaps et Secrets au quotidien. On commence par créer une ConfigMap avec des valeurs littérales et un Secret pour les credentials d’une base de données :

# ConfigMap depuis des valeurs littérales
kubectl create configmap app-config \
  --from-literal=APP_ENV=production \
  --from-literal=LOG_LEVEL=info

# ConfigMap depuis un fichier de config
kubectl create configmap nginx-conf \
  --from-file=default.conf=./nginx.conf

# Secret générique
kubectl create secret generic db-creds \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASSWORD='S3cur3P@ss!'

# Secret TLS depuis un certificat
kubectl create secret tls app-tls \
  --cert=tls.crt --key=tls.key

💡 Tip DevOps : Utilise --dry-run=client -o yaml pour générer le YAML sans appliquer. Parfait pour versionner dans Git ou piper vers kubeseal.

Pour injecter ces ressources dans un Pod, tu as deux approches. L’injection en variables d’environnement est la plus simple — chaque clé devient une variable accessible dans ton conteneur :

apiVersion: v1
kind: Pod
metadata:
  name: api-server
spec:
  containers:
    - name: api
      image: my-api:2.0
      env:
        - name: APP_ENV
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: APP_ENV
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-creds
              key: DB_PASSWORD
      envFrom:
        - configMapRef:
            name: app-config

Pour injecter un fichier de configuration complet (comme un nginx.conf), tu montes la ConfigMap comme un volume. Chaque clé devient un fichier dans le répertoire cible :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-custom
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          volumeMounts:
            - name: config-vol
              mountPath: /etc/nginx/conf.d
              readOnly: true
      volumes:
        - name: config-vol
          configMap:
            name: nginx-conf

🧠 À retenir : Les ConfigMaps montées en volume se mettent à jour automatiquement (~60s). Les variables d’environnement, non — il faut redémarrer le Pod.

Cas concret entreprise

🔥 Cas réel : Une équipe déploie une API e-commerce sur trois environnements (dev, staging, prod). Chaque env a sa propre base de données, son niveau de log et son URL de cache Redis.

Voici le manifeste déclaratif qui combine ConfigMap pour la config applicative et Secret pour les credentials. Un seul Deployment, trois comportements différents selon le namespace :

# config-prod.yaml — à appliquer dans le namespace "prod"
apiVersion: v1
kind: ConfigMap
metadata:
  name: api-config
  namespace: prod
data:
  APP_ENV: "production"
  LOG_LEVEL: "warn"
  REDIS_URL: "redis-prod.internal:6379"
---
apiVersion: v1
kind: Secret
metadata:
  name: api-secrets
  namespace: prod
type: Opaque
stringData:
  DB_URL: "postgresql://prod-db.internal:5432/shop"
  DB_PASSWORD: "Pr0d-Sup3r-S3cr3t!"
  API_KEY: "sk-live-abc123xyz"

L’équipe chiffre le Secret avec Sealed Secrets avant de le commiter dans Git :

# Générer le Secret en dry-run, puis chiffrer
kubectl create secret generic api-secrets \
  --namespace=prod \
  --from-literal=DB_URL='postgresql://prod-db.internal:5432/shop' \
  --from-literal=DB_PASSWORD='Pr0d-Sup3r-S3cr3t!' \
  --dry-run=client -o yaml | kubeseal --format yaml \
  > sealed-api-secrets-prod.yaml

Le fichier sealed-api-secrets-prod.yaml est pushé dans le repo Git. ArgoCD l’applique automatiquement. Le contrôleur Sealed Secrets le déchiffre dans le cluster. Les vrais credentials ne quittent jamais le cluster.

💡 Tip DevOps : Versionne le nom de tes ConfigMaps immuables (api-config-v3, api-config-v4). Un rolling update se déclenche automatiquement quand tu changes la référence dans le Deployment.

Pièges fréquents

1. Croire que base64 = sécurité. Un echo YWRtaW4= | base64 -d et ton mot de passe est en clair. Toujours combiner Secrets + chiffrement at rest + RBAC strict.

2. Utiliser des variables d’environnement pour les secrets critiques. Les env vars apparaissent dans les logs de debug, les core dumps et /proc/<pid>/environ. Monte tes secrets en fichiers avec des permissions restrictives (defaultMode: 0400).

3. Oublier que les env vars ne se rafraîchissent pas. Tu modifies une ConfigMap, mais ton app garde les anciennes valeurs. Seuls les volumes montés se mettent à jour automatiquement.

4. Commiter des Secrets en clair dans Git. Même si tu les supprimes après, l’historique Git les garde. Utilise Sealed Secrets ou un vault externe (HashiCorp Vault, AWS Secrets Manager).

5. Pas de RBAC sur les Secrets. Par défaut, tout ServiceAccount peut lire tous les Secrets du namespace. Verrouille les accès avec des Roles ciblés.

⚠️ Attention : Un kubectl get secret db-creds -o jsonpath='{.data.DB_PASSWORD}' | base64 -d affiche le mot de passe en clair. Contrôle qui a accès à cette commande via RBAC et audit logs.

Exercice pratique

Objectif : Déployer Nginx avec une page de status personnalisée, alimentée par une ConfigMap, et des credentials factices dans un Secret monté en fichier.

  1. Crée une ConfigMap status-config contenant une clé default.conf avec un bloc serveur Nginx qui renvoie {"status": "ok", "env": "staging"} sur /health
  2. Crée un Secret app-creds avec API_KEY=test-key-12345
  3. Déploie Nginx en montant la ConfigMap dans /etc/nginx/conf.d et le Secret dans /etc/secrets
  4. Vérifie avec kubectl exec que /etc/secrets/API_KEY contient la valeur décodée
  5. Modifie la ConfigMap (change staging en production) et vérifie que le fichier se met à jour sans redémarrer le Pod
💡 Solution

Crée les ressources et le Deployment dans un seul fichier :

apiVersion: v1
kind: ConfigMap
metadata:
  name: status-config
data:
  default.conf: |
    server {
        listen 80;
        location /health {
            default_type application/json;
            return 200 '{"status": "ok", "env": "staging"}';
        }
    }
---
apiVersion: v1
kind: Secret
metadata:
  name: app-creds
type: Opaque
stringData:
  API_KEY: "test-key-12345"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-status
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-status
  template:
    metadata:
      labels:
        app: nginx-status
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
          volumeMounts:
            - name: nginx-conf
              mountPath: /etc/nginx/conf.d
            - name: secrets
              mountPath: /etc/secrets
              readOnly: true
      volumes:
        - name: nginx-conf
          configMap:
            name: status-config
        - name: secrets
          secret:
            secretName: app-creds
            defaultMode: 0400

Vérifie le résultat :

kubectl apply -f nginx-status.yaml
kubectl exec deploy/nginx-status -- cat /etc/secrets/API_KEY
# test-key-12345
kubectl port-forward deploy/nginx-status 8080:80
curl localhost:8080/health
# {"status": "ok", "env": "staging"}

À retenir

  • ConfigMap = configuration non sensible (env vars, fichiers de config, feature flags)
  • Secret = données sensibles (mots de passe, tokens, certificats) — base64 ≠ chiffrement
  • Sealed Secrets = chiffrement côté client pour un workflow GitOps propre
  • Volumes montés > variables d’environnement pour les secrets (sécurité + mise à jour auto)
  • Une image, plusieurs configs : le découplage code/config est la base d’un déploiement Kubernetes sain

🧠 À retenir : Pense aux ConfigMaps comme des fichiers .env versionnés et aux Secrets comme un coffre-fort avec une serrure en carton — rajoute un vrai verrou (Sealed Secrets, Vault) avant d’aller en production.

➡️ La suite

Prochain chapitre : la sécurité Kubernetes — RBAC, Network Policies, Pod Security Standards. Parce qu’un cluster sans sécurité, c’est une porte ouverte sur Internet.

🖥️ Pratique sur ton propre serveur

Pour suivre Apprendre Kubernetes en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés