ConfigMaps et Secrets - ii02735/learn-k8 GitHub Wiki

Les ConfigMaps et Secrets

Le problème : ne pas figer la configuration

On n'écrit jamais de configuration (URL de base de données, mot de passe, niveau de log…) en dur dans une image : la même image doit pouvoir tourner en développement, en recette et en production, avec une configuration différente.

Kubernetes sépare donc la configuration du code, au moyen de deux objets :

  • ConfigMap : des données de configuration non sensibles ;
  • Secret : des données sensibles (mots de passe, jetons, certificats…).

Les deux se présentent comme un ensemble de paires clé/valeur, et se consomment de la même façon depuis un Pod : en variables d'environnement ou en fichiers montés.

ConfigMap et Secret consommés par un Pod

La ConfigMap

Une ConfigMap stocke de la configuration non sensible : variables d'environnement, fichiers de config, arguments de ligne de commande…

Elle peut être créée :

  • à partir de valeurs littérales (--from-literal) ;
  • à partir d'un ou plusieurs fichiers (--from-file) ;
  • à partir d'un répertoire entier (--from-file=<dossier>).

Le Secret

Un Secret est quasi identique à une ConfigMap, mais destiné aux données sensibles. Différences importantes :

  • les valeurs sont encodées en base64 ;
  • le Secret peut être typé : Opaque (par défaut), kubernetes.io/tls, kubernetes.io/dockerconfigjson, kubernetes.io/service-account-token…
  • il est stocké dans etcd, et n'est pas chiffré par défaut (voir les bonnes pratiques ci-dessous).

⚠️ Le base64 n'est pas du chiffrement : il s'agit d'un simple encodage, réversible sans clé. Un Secret n'est donc protégé que par les contrôles d'accès (RBAC) et, si activé, par le chiffrement au repos du cluster.

Consommer une ConfigMap ou un Secret

Il existe deux façons, valables pour les deux objets :

  • En variables d'environnement : via envFrom (toutes les clés) ou valueFrom.configMapKeyRef / valueFrom.secretKeyRef (une clé précise).
  • En fichiers : on monte la ConfigMap/Secret comme un volume ; chaque clé devient un fichier dans le conteneur.

Et une différence de comportement à retenir :

  • une variable d'environnement est figée au démarrage du conteneur : modifier la ConfigMap ne change pas l'environnement du conteneur déjà lancé ;
  • les fichiers d'un volume sont, eux, mis à jour (avec un léger délai) quand la ConfigMap/Secret change.

Note

Les Secrets montés en volume sont stockés dans un système de fichiers en mémoire (tmpfs), jamais écrits sur le disque du noeud.

Bonnes pratiques pour les Secrets

  • Ne jamais committer un Secret en clair dans Git : utiliser sealed-secrets, SOPS, External Secrets ou un coffre (Vault…).
  • Restreindre l'accès avec le RBAC (peu de comptes peuvent lire les Secrets).
  • Activer le chiffrement au repos dans etcd (configuration de l'apiserver).
  • Préférer le montage en fichiers plutôt que les variables d'environnement : celles-ci peuvent fuiter (processus enfants, dumps de crash, /proc…).
  • Faire tourner (rotation) les Secrets régulièrement.

Un manifeste ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  LOG_LEVEL: info
  app.properties: |
    server.port=8080
    feature.enabled=true

Un manifeste Secret

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: YWRtaW4=          # base64 de "admin"
  password: cGFzc3dvcmQ=      # base64 de "password"

Note

Le champ stringData permet d'écrire les valeurs en clair : l'API les convertit elle-même en base64.

Un Pod qui consomme les deux

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: nginx
      envFrom:
        - configMapRef:
            name: app-config
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: password
      volumeMounts:
        - name: config
          mountPath: /etc/app
          readOnly: true
  volumes:
    - name: config
      configMap:
        name: app-config

Les commandes principales

  • Créer une ConfigMap (littéral) : kubectl create configmap app-config --from-literal=LOG_LEVEL=info
  • Créer une ConfigMap (fichier) : kubectl create configmap app-config --from-file=app.properties
  • Lister les ConfigMaps : kubectl get configmaps (ou kubectl get cm)
  • Voir le contenu : kubectl describe configmap app-config
  • Créer un Secret (littéral) : kubectl create secret generic db-credentials --from-literal=password=password
  • Créer un Secret TLS : kubectl create secret tls mon-tls --cert=cert.pem --key=key.pem
  • Lister les Secrets : kubectl get secrets
  • Décoder une valeur : kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d
  • Encoder une valeur : echo -n 'password' | base64
⚠️ **GitHub.com Fallback** ⚠️