Configuration
Variables d’environnement
Quand nous avons besoin de lancer une application en container sur Kubernetes, il est rare d’avoir toute la configuration écrite de manière statique dans l’image du container. On pourrait. Mais ça veut dire que dès qu’on veut lancer l’application en changeant un de ses paramètres, par exemple : si elle tourne sur un cluster de production ou hors production où on n’aura pas le même affichage d’une page web quels sont les identifiants qu’elle doit utiliser pour se connecter à une base de données Cela impliquerait de reconstruire l’image à chaque changement de paramètre. On se retrouverait alors avec autant d’images que d’environnements ou de combinaisons de configuration, ce qui devient rapidement difficile à maintenir.
Dans une approche cloud-native, on privilégie des images immuables contenant uniquement le code applicatif, tandis que la configuration est externalisée.
On externalise donc la configuration afin de conserver une image générique et réutilisable entre les environnements. L’image contient uniquement le code applicatif, tandis que les paramètres (environnement, identifiants, options d’exécution, etc.) sont injectés au moment du déploiement.
L’un des moyens les plus simples pour transmettre cette configuration à une application est d’utiliser des variables d’environnement. lien vers le répo github lié à cette section
Essayons de créer un pod avec une image busybox standard et de lui passer une variable d’environnement qui s’appelle “PLANET” et qui a comme valeur “blue”. Le YAML est le suivant :
apiVersion: v1
kind: Pod
metadata:
labels:
run: envvar
name: envvar
spec:
containers:
- image: busybox:latest
name: envvar
args:
- sleep
- "3600"
env:
- name: PLANET
value: "blue"On lance le pod dans notre cluster :
$ kubectl apply -f envvar.yamlEt pour exécuter une commande à l’intérieur du pod, on utilise la commande exec :
$ kubectl exec envvar -- env | grep PLANET
PLANET=blueSi on veut changer la variable d’environnement pour qu’elle ait comme valeur red, on pourrait changer la valeur dans le YAML de départ, et relancer le pod. Il n’y a pas besoin de changer l’image.
ConfigMap
Dans certaines petites applications, on a juste besoin de passer quelques variables d’environnement à l’application pour qu’elle fasse ce qu’on veut. Mais dans des applications plus complexes, on peut avoir beaucoup de variables d’environnement et plusieurs fichiers de configuration à passer.
Les ConfigMaps sont des objets Kubernetes qui permettent d’externaliser la configuration d’une application afin de ne pas l’inclure directement dans l’image du container.
Une ConfigMap peut être injectée dans un Pod de deux manières principales :
- en tant que variables d’environnement
- en tant que fichiers montés via un volume
Dans le premier cas, les clés de la ConfigMap deviennent des variables accessibles par l’application.
Dans le second cas, chaque clé est créée sous forme de fichier dans l’arborescence du Pod.
Lors de la CKA, il est important de bien comprendre ces deux mécanismes, car ils sont fréquemment utilisés pour configurer des applications de manière déclarative.
Prenons un exemple simple : nous souhaitons transmettre deux variables d’environnement à une application via une ConfigMap.
Il est possible de créer une ConfigMap directement en ligne de commande avec kubectl, ce qui est particulièrement pratique lors de la CKA :
$ kubectl create configmap space --from-literal=planet=blue --from-literal=moon=white
configmap/space createdIl est également possible de la définir dans un fichier YAML, puis d’appliquer la configuration de manière déclarative :
apiVersion: v1
kind: ConfigMap
metadata:
name: space
data:
planet: blue
moon: white
Ensuite, on va créer un pod à qui on va passer des variables d’environnement à partir de cette ConfigMap :
apiVersion: v1
kind: Pod
metadata:
labels:
run: configenvvar
name: configenvvar
spec:
containers:
- image: busybox:latest
name: configenvvar
args:
- sleep
- "3600"
env:
- name: PLANET
valueFrom:
configMapKeyRef:
name: space
key: planet
- name: MOON
valueFrom:
configMapKeyRef:
name: space
key: moonOn lance ce pod et on regarde s’il a bien reçu ses variables d’environnement :
$ kubectl apply -f configenvvar.yaml
$ kubectl exec configenvvar -- env | grep -E "PLANET|MOON"
PLANET=blue
MOON=whiteSecret
Une partie de la configuration des applications peuvent être sensibles, comme des mots de passe pour accéder à une base de données, ou une clé d’API pour accéder à un service externe.
Ce type de configuration ne doit pas être stocké dans une ConfigMap, mais dans un objet Secret, qui bénéficie de mécanismes de contrôle d’accès (RBAC) spécifiques afin de limiter la lecture et la modification aux utilisateurs autorisés.
Les Secrets peuvent être injectés dans un Pod soit en tant que variables d’environnement, soit en tant que fichiers montés via un volume, de la même manière que les ConfigMaps.
Par défaut, les données sont simplement encodées en base64 dans etcd. Toutefois, Kubernetes permet d’activer le chiffrement au repos (encryption at rest) afin que les Secrets soient chiffrés lorsqu’ils sont stockés dans etcd.
Nous allons créer un Secret qui contient un username et un password :
$ echo -n 'admin' > username
$ echo -n 'admin-pass' > password
$ kubectl create secret generic admin-creds --from-file=username --from-file=passwordIl y a plusieurs types de secret dont la liste est ici : secret types
Dans notre cas, nous avons utilisé le type de Secret standard, par défaut, sans contraintes qui s’appelle Opaque.
Si nous essayons de le lire avec nos droits d’administrateur, nous allons voir ça :
apiVersion: v1
kind: Secret
metadata:
name: admin-creds
type: Opaque
data:
username: YWRtaW4=
password: YWRtaW4tcGFzcw==Les valeurs des secrets sont encodées en base64 (admin en base64 donne YWRtaW4=). L’encodage ne constitue pas un moyen de protection des secrets. Pour empêcher les utilisateurs de voir les secrets, il ne faut pas qu’ils aient les droits nécessaires, qui ne devraient être attribués qu’aux administrateurs et aux utilisateurs privilégiés.
Maintenant que le Secret est créé, on peut créer un pod qui va charger ses valeurs en tant que variables d’environnement :
apiVersion: v1
kind: Pod
metadata:
labels:
run: secretenv
name: secretenv
spec:
containers:
- image: busybox:latest
name: secretenv
args:
- sleep
- "3600"
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: admin-creds
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: admin-creds
key: passwordOn lance le pod et on s’assure qu’il détient bien les secrets :
$ kubectl apply -f secretenv.yaml
$ kubectl exec secretenv -- env | grep -E "USERNAME|PASSWORD"
USERNAME=admin
PASSWORD=admin-passConclusion
Les variables d’environnement constituent un moyen simple et efficace de transmettre une partie de la configuration d’une application déployée sur Kubernetes.
Cette configuration peut être définie directement dans la description YAML d’un Pod (ou d’un Deployment), ou externalisée à l’aide d’une ConfigMap ou d’un Secret lorsqu’il s’agit de données sensibles.
Cependant, de nombreuses applications nécessitent des fichiers de configuration complets plutôt que de simples variables d’environnement.
Dans ce cas, les ConfigMaps et les Secrets peuvent être montés en tant que fichiers dans l’arborescence du Pod grâce aux volumes, permettant ainsi à l’application de lire sa configuration comme elle le ferait sur un système classique.
La compréhension de ces mécanismes est essentielle pour déployer des applications configurables, sécurisées et conformes aux bonnes pratiques cloud-native sur Kubernetes.


