DRY Helm Charts

Tyas Seegers

Helm wordt vaak omschreven als de “package manager” voor Kubernetes. Met Helm charts kunnen ontwikkelaars hun applicaties en infrastructuur als herbruikbare templates definiëren. Een Helm chart bevat alle benodigde Kubernetes-resources om een applicatie te draaien, zoals Deployments, Services, ConfigMaps en meer. Al deze onderdelen zijn configureerbaar via eenvoudige values.yaml-files.

Dankzij Helm kun je:

  • Applicaties met één commando installeren of upgraden
  • Versiebeheer toepassen op je deployments
  • Instellingen eenvoudig overschrijven per omgeving
  • Complexe Kubernetes-configuraties abstraheren en herbruikbaar maken

Maar wat als je merkt dat je voor elke applicatie telkens dezelfde Helm templates kopieert? En dat één wijziging in een template leidt tot copy-paste-acties in talloze repositories? Don’t Repeat Yourself (DRY). Gebruik library charts.

Wat is een Helm library chart?

Een library chart in Helm is een speciaal type chart bedoeld voor het delen van templates en helper-functies, zonder zelf Kubernetes-resources te deployen. Je kunt het zien als een toolbox die door andere charts gebruikt wordt om configuraties te hergebruiken.

Voorbeeld folderstructuur van een Helm library chart
my-helm-library/
├── Chart.yaml
├── templates/
└── _configmap.tpl
└── _helpers.tpl

Folder structuur Helm library

De Chart.yaml ziet er als volgt uit:

apiVersion: v2
name: my-helm-library
description: A Helm library example
type: library
version: 0.1.0

Chart.yaml

Let op het veld "type: library". Daarmee geef je expliciet aan dat het om een library chart gaat.

Template voorbeeld: ConfigMap

Een template in een library chart definieer je met behulp van define-statements:

{{ define "my-helm-library.configmap" }}
{{- if .Values.config }}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include " my-helm-library.fullname" . }}-config
  labels:
    {{- include " my-helm-library.labels" $ | nindent 4 }}
data:
  {{- range $key, $value := .Values.config }}
  {{ $key }}: {{ $value | quote }}
  {{- end }}
---
{{- end }}
{{- end -}}

_configmap.tpl

In de praktijk bevat een library chart vaak meerdere templates, maar dit voorbeeld met alleen een ConfigMap is voldoende om te illustreren hoe het werkt. Let op: de bestandsnaam begint hier met een underscore (_configmap.tpl). Dit is belangrijk, omdat Helm bestanden die beginnen met een underscore niet automatisch rendert als Kubernetes-configuratie. De conventie is daarom om helper-templates altijd te laten beginnen met een underscore.

De library chart is nu klaar voor gebruik. Package en upload deze naar jouw repository of container registry naar keuze, zodat andere charts hier gebruik van kunnen maken.

Hergebruik in een application chart

Om de templates uit je library chart te gebruiken, voeg je deze toe als dependency in de Chart.yaml van je application-chart:

apiVersion: v2
name: my-application-chart
description: A Helm application chart
type: application
version: 2.0.0
appVersion: 2.0.0

dependencies:
  - name: my-helm-library
    version: 0.1.x
    repository: oci://my-container-registry.azurecr.io

Chart.yaml

Dankzij semantic versioning (0.1.x) kun je updates aanbrengen in de library chart zonder dat je code hoeft aan te passen in de application-chart. Een eenvoudige redeploy volstaat om de laatste compatible versie van de library te gebruiken.

Binnen de templates-folder van je application-chart maak je een yaml file (bijv. appmanifest.yaml) aan en roep je daar de gewenste resource-template aan:

{{- include " my-helm-library.configmap" . }}

appmanifest.yaml

De filenaam appmanifest.yaml is geen Helm conventie. Je bent vrij om include-statements in elk ander .yaml-file binnen de templates-folder te plaatsen. Let er wel op dat de filenaam niet met een underscore begint, in tegenstelling tot de template-files in de library chart.

Vervolgens bepaal je in de values.yaml-file welke configuratie je aan de ConfigMap wilt meegeven:

config:
  DummyConfigEntry: DummyConfigEntryValue
  AnotherDummyConfigEntry: AnotherDummyConfigEntryValue

values.yaml

Let op: je hoeft hier niet het subchart-naam als prefix te gebruiken (zoals gebruikelijk bij andere subcharts). De config staat direct op top-level in je values.yaml.

Meerdere library charts gebruiken

Het is mogelijk om templates uit meerdere library charts tegelijk te gebruiken. Ter illustratie een alternatieve appmanifest.yaml:

{{- include " my-helm-library.configmap" . }}
{{- include " another-helm-library.service" . }}

appmanifest.yaml

Zorg er uiteraard voor dat je another-helm-library ook toevoegt aan de dependencies in je Chart.yaml-file.

Wanneer je met meerdere library charts werkt, is het noodzakelijk om naamgevingsconflicten te voorkomen. Het is dan raadzaam om binnen de library charts de value-verwijzingen te voorzien van een prefix, zodat ze uniek blijven per chart.

Tot slot

Het toepassen van DRY-principes in je Helm charts zorgt voor minder herhaling, minder kans op fouten en eenvoudiger onderhoud over meerdere projecten heen. Door gebruik te maken van library charts kun je centrale templates en logica hergebruiken, terwijl je toch de flexibiliteit behoudt om per applicatie specifieke instellingen toe te passen.

Wil je hulp bij het opzetten van een Helm library structuur of bij het refactoren van bestaande charts? Neem gerust contact met ons op, wij denken graag met je mee.

Stel je vragen

Klaar voor transformatie?

We horen graag van je! Neem vandaag nog contact op.

info@cloudfulness.nl
Leigraafseweg 2, 6983 BP, Doesburg
0316 798 020