Gérer « efficacement » les fichiers de configuration dans les charts HELM

Dès qu’on veut déployer des environnements Kubernetes, Helm devient une des solutions à considérer.
Le déploiement des objets standards tels que deployment, autoscaler et autres se fait aisément car ces derniers ne changent pas d’un environnement à l’autre. Généralement on déploie la même infrastructure sur tous les environnements du développement à la production.

Bien évidemment on pourra limiter la taille des replicas sur l’environnement de développement par exemple mais au fond, le contenu des charts sera identique. Une des difficultés que l’on pourra rencontrer c’est dans la gestion des fichiers de configuration.

Je vais essayer d’exposer dans cet article comment j’ai réussi à gérer +/- efficacement (en tout cas pour moi) les fichiers de configuration dans les charts HELM.

Les config maps et secrets

Logiquement dans ce type d’architecture, les configmaps et secrets permettent le chargement des variables d’environnement et autres mots de passe. Cependant si vous utilisez certains frameworks qui nécessitent des fichiers de configuration, vous devrez charger les fichiers dans des volumes. Pour ces derniers, les volumes n’ont pas besoin d’être persistents.

Par exemple dans la configuration de votre deployment, vous pourrez configurer le montage d’un volume de la manière suivante:

  volumeMounts:
            - mountPath: /config
              name: configuration-volume
              readOnly: true
            - mountPath: /secrets
              name: secret-volume
              readOnly: true
      [...]
      volumes:
        - configMap:
            defaultMode: 420
            name: configuration
          name: configuration-volume
        - name: secret-volume
          secret:
            defaultMode: 420
            secretName: secrets

Pour intégrer un fichier binaire, on pourra le faire de la manière suivante dans le template HELM:

apiVersion: v1
# Definition of secrets
kind: Secret
[...]
type: Opaque
# Inclusion of binary configuration files
data:
  my_keystore.jks: {{ .Files.Get "secrets/my_keystore.jks" | b64enc }}

Vous pouvez définir les fichiers directement dans vos configmaps. Cependant, si vos fichiers sont volumineux, vous aurez du mal à les maintenir. Personnellement, j’opte pour mettre les fichiers de configuration à coté et les charger dans le configmap.

On pourra procéder de la manière suivante:

apiVersion: v1
kind: ConfigMap
[...]

data:
  my.conf:   {{- (.Files.Glob "conf/*").AsConfig | nindent 2 }} 

Livrables agnostiques

Une bonne pratique de développement logiciel est d’externaliser la configuration de vos environnements (ex. l’URL JDBC de la base de données) des livrables. Les charts HELM n’échappent à la règle.

On peut stocker la configuration de chaque environnement dans le chart, mais dans ce cas, on perdra beaucoup de souplesse lors des mises à jour des propriétés et cela nous imposera une nouvelle version.

On a plusieurs niveaux d’externalisation. Le premier est dans le chart. Vous pouvez externaliser les différentes valeurs dans le fichier values.yml. Ci dessous un exemple avec un autoscaler:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  labels:
  [...]
spec:
  maxReplicas: {{ .Values.myapp.maxReplicaCount }}
  minReplicas: {{ .Values.myapp.minReplicaCount }}
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
   [...]
  targetCPUUtilizationPercentage: {{ .Values.myapp.replicationThreesold }}

Les valeurs sont décrites comme suit:

myapp:
  minReplicaCount: "2"
  maxReplicaCount: "6"
  replicationThreesold: 80

Pour externaliser les valeurs d’environnement, vous pourrez donc externaliser un autre fichier values.yml qui sera appliqué au déploiement. Les valeurs de ce dernier surchargeront les valeurs définies dans le chart.
Il est important de noter également que les données présentes dans les fichiers de configuration (ex. fichier application.properties) peuvent être « variabilisées » et surchargées par le même mécanisme. Vous aurez à utiliser la commande tpl.

apiVersion: v1
kind: ConfigMap
metadata:
  name: configuration
  labels:
    [...]
data:
  application.properties: 
    |- 
    {{ tpl (.Files.Get "conf/application.properties") . | nindent 4}} 

Conclusion

Vous l’aurez compris, les charts HELM n’échappent pas aux règles déjà connues de gestion des environnements et des livrables. Même si il y a quelques subtilités à connaître pour intégrer des fichiers de configuration par exemple, les grands principes restent les mêmes.