ConfigMaps et Secrets - ii02735/learn-k8 GitHub Wiki
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.
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>).
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).
Il existe deux façons, valables pour les deux objets :
-
En variables d'environnement : via
envFrom(toutes les clés) ouvalueFrom.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.
- 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.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: production
LOG_LEVEL: info
app.properties: |
server.port=8080
feature.enabled=trueapiVersion: 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.
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- 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(oukubectl 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