Contactez-nous

ConfigMaps : Gérer la configuration non sensible

Apprenez à utiliser les ConfigMaps Kubernetes pour découpler et gérer efficacement les données de configuration non sensibles de vos applications.

Externaliser la configuration : voici les ConfigMaps

Comme nous l'avons vu, coder en dur la configuration dans les images de conteneurs ou même directement dans les manifestes de Pods via des variables d'environnement ou des arguments n'est pas idéal, surtout lorsque la configuration change ou devient complexe. Pour résoudre ce problème de manière élégante, Kubernetes propose un objet API dédié au stockage des données de configuration non sensibles : le ConfigMap.

Un ConfigMap vous permet de découpler la configuration de la définition de vos Pods. Vous stockez vos paramètres, fichiers de configuration ou autres données non confidentielles dans un objet ConfigMap distinct, puis vous référencez ce ConfigMap depuis vos Pods pour injecter ces données là où elles sont nécessaires (variables d'environnement, fichiers montés en volume).

Cette approche rend vos images de conteneurs plus génériques et réutilisables, facilite la gestion des configurations pour différents environnements (développement, staging, production) en utilisant différents ConfigMaps, et permet de mettre à jour la configuration sans avoir à reconstruire les images.

Structure et contenu d'un ConfigMap

Un ConfigMap stocke les données sous forme de paires clé-valeur. Les valeurs peuvent être de simples chaînes de caractères ou le contenu de fichiers entiers.

La structure d'un manifeste YAML pour un ConfigMap est simple :

apiVersion: v1
kind: ConfigMap
metadata:
  name: mon-app-config # Nom du ConfigMap
  namespace: production # Les ConfigMaps sont namespacés
data: # Stocke les données sous forme de chaînes UTF-8
  # Clé-valeur simple
  database.url: "jdbc:mysql://mysql.production.svc.cluster.local:3306/mydb"
  log.level: "WARN"

  # Contenu d'un fichier de configuration via une clé multiligne
  nginx.conf: |
    server {
      listen       80;
      server_name  localhost;

      location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
      }
    }

  # Autre fichier
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
# binaryData: # Stocke les données binaires encodées en base64
#   clave.jks: "[BASE64_ENCODED_DATA]"

Points clés :

  • `metadata.name` : Le nom utilisé pour référencer le ConfigMap.
  • `data` : Un dictionnaire où les clés sont les noms des entrées de configuration et les valeurs sont les données correspondantes sous forme de chaînes de caractères (UTF-8). C'est la section la plus couramment utilisée.
  • `binaryData` : Permet de stocker des données binaires. Les valeurs doivent être encodées en base64. Si une clé existe à la fois dans `data` et `binaryData`, `binaryData` a la priorité.

Créer des ConfigMaps

Vous pouvez créer des ConfigMaps de plusieurs manières :

  1. A partir de fichiers YAML (méthode déclarative) : Ecrivez le manifeste YAML comme ci-dessus et appliquez-le avec `kubectl apply -f mon-configmap.yaml`.
  2. A partir de valeurs littérales avec `kubectl` :
    kubectl create configmap mon-config-literal \
      --from-literal=database.host=mysql \
      --from-literal=log.level=info \
      -n mon-namespace
  3. A partir d'un fichier individuel avec `kubectl` : Le nom du fichier devient la clé, et le contenu du fichier devient la valeur.
    kubectl create configmap config-depuis-fichier \
      --from-file=chemin/vers/mon/nginx.conf \
      -n mon-namespace
    Le ConfigMap contiendra une clé `nginx.conf` avec le contenu du fichier. Vous pouvez spécifier une clé différente avec `--from-file=ma-cle=chemin/vers/fichier`.
  4. A partir d'un répertoire avec `kubectl` : Chaque fichier dans le répertoire spécifié devient une entrée dans le ConfigMap, avec le nom de fichier comme clé et le contenu comme valeur.
    kubectl create configmap config-depuis-dossier \
      --from-file=chemin/vers/mon/dossier/config/ \
      -n mon-namespace

La méthode déclarative (fichier YAML) est généralement préférée pour la gestion via Git (GitOps), tandis que les commandes `kubectl create` sont pratiques pour une création rapide ou à partir de fichiers existants.

Utiliser les ConfigMaps dans les Pods

Une fois un ConfigMap créé, vous pouvez injecter ses données dans les conteneurs de vos Pods de deux manières principales :

  1. Comme Variables d'Environnement :
    - Injecter une clé spécifique : Utilisez `env.valueFrom.configMapKeyRef`.
    spec:
      containers:
      - name: mon-conteneur
        image: mon-image
        env:
        - name: LOG_LEVEL_APP # Nom de la variable dans le conteneur
          valueFrom:
            configMapKeyRef:
              name: mon-app-config # Nom du ConfigMap
              key: log.level       # Clé à récupérer dans le ConfigMap
    La variable `LOG_LEVEL_APP` dans le conteneur aura la valeur associée à la clé `log.level` dans `mon-app-config`.
    - Injecter toutes les clés comme variables : Utilisez `envFrom.configMapRef`. Chaque clé du ConfigMap devient le nom d'une variable d'environnement dans le conteneur.
    spec:
      containers:
      - name: mon-conteneur
        image: mon-image
        envFrom:
        - configMapRef:
            name: mon-app-config # Nom du ConfigMap
    Si `mon-app-config` a les clés `database.url` et `log.level`, le conteneur aura les variables `database.url` et `log.level`. (Attention aux noms de clés non valides pour les variables d'env, K8s les ignorera).
  2. Comme Fichiers dans un Volume : Montez le ConfigMap comme un type de volume spécial.
    - Monter toutes les clés comme fichiers : Chaque clé du ConfigMap devient un fichier dans le répertoire de montage (`mountPath`), où le nom du fichier est la clé et le contenu du fichier est la valeur.
    spec:
      containers:
      - name: mon-conteneur
        image: mon-image
        volumeMounts:
        - name: config-volume # Nom du montage
          mountPath: /etc/config # Répertoire de montage dans le conteneur
      volumes:
      - name: config-volume # Nom du volume, doit correspondre au volumeMount
        configMap:
          name: mon-app-config # Nom du ConfigMap à monter
    Le répertoire `/etc/config` contiendra les fichiers `database.url`, `log.level`, `nginx.conf`, etc.
    - Monter des clés spécifiques comme fichiers (projection) : Vous pouvez choisir quelles clés monter et leur donner des noms de fichier spécifiques.
    spec:
      containers:
      - name: mon-conteneur
        image: mon-image
        volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/conf.d # Monter un fichier spécifique ici
          subPath: nginx_config # Nom du fichier dans le conteneur (si différent de la clé)
          # readOnly: true (souvent une bonne idée)
      volumes:
      - name: config-volume
        configMap:
          name: mon-app-config
          items:
          - key: nginx.conf       # Clé du ConfigMap
            path: nginx_config    # Nom du fichier dans le volume (qui sera monté via subPath)
    Ici, seul le contenu de la clé `nginx.conf` du ConfigMap est monté comme fichier `nginx_config` dans `/etc/nginx/conf.d` à l'intérieur du conteneur.

Le montage en volume est souvent préféré pour les fichiers de configuration complets, tandis que les variables d'environnement conviennent mieux aux paramètres simples.

Mises à jour et remarques importantes

Quelques points importants concernant les ConfigMaps :

  • Non-sensibilité : Rappelez-vous que les ConfigMaps sont destinés à des données non sensibles. N'y stockez jamais de mots de passe, tokens ou clés API. Utilisez les Secrets pour cela.
  • Mises à jour : Si vous mettez à jour un ConfigMap, les Pods qui l'utilisent ne verront pas automatiquement les changements :
    • Les variables d'environnement sont injectées au démarrage du conteneur et ne sont pas mises à jour dynamiquement. Vous devez redémarrer les Pods (par exemple, via `kubectl rollout restart deployment/...`) pour qu'ils prennent en compte les nouvelles valeurs.
    • Les volumes ConfigMap sont montés et les fichiers sont créés. Par défaut, les fichiers montés via un volume ConfigMap sont mis à jour périodiquement par le Kubelet (environ toutes les minutes), mais l'application à l'intérieur du conteneur doit être capable de détecter et de recharger ces fichiers modifiés pour que la mise à jour soit effective sans redémarrage du Pod. Si vous utilisez `subPath` dans le `volumeMount`, la mise à jour dynamique ne fonctionne généralement pas.
  • Taille limitée : Les ConfigMaps (comme les Secrets) sont stockés dans etcd et ne sont pas conçus pour contenir de très grandes quantités de données (la limite par objet est généralement de 1 Mo).
  • Immutabilité (optionnelle) : Vous pouvez rendre un ConfigMap immuable en définissant `immutable: true` dans son manifeste. Cela empêche toute modification ultérieure et peut être utile pour garantir la stabilité de la configuration pour certains Pods.

Gérer les ConfigMaps avec `kubectl`

  • Lister les ConfigMaps : `kubectl get configmaps` (ou `kubectl get cm`) [-n namespace]
  • Afficher le contenu : `kubectl describe configmap [NOM_CONFIGMAP]` [-n namespace] (affiche les clés et un aperçu des valeurs)
  • Afficher le contenu complet (YAML) : `kubectl get configmap [NOM_CONFIGMAP] -o yaml` [-n namespace]
  • Supprimer un ConfigMap : `kubectl delete configmap [NOM_CONFIGMAP]` [-n namespace]

Conclusion : une gestion propre de la configuration

Les ConfigMaps sont un outil essentiel dans l'arsenal Kubernetes pour gérer la configuration des applications de manière découplée et organisée. En externalisant les paramètres non sensibles dans des objets ConfigMap dédiés et en les injectant dans les Pods via des variables d'environnement ou des volumes, vous rendez vos applications plus portables, plus faciles à gérer et à adapter à différents environnements.

Cependant, leur utilisation est strictement réservée aux données non confidentielles. Pour les informations sensibles, nous devons nous tourner vers leur contrepartie sécurisée : les Secrets.