Chart Entwicklung Tipps und Tricks
Dieses Handbuch bespricht Tipps und Tricks, die Helm Chart Entwickler bei der Entwicklung von produktionsreifen Charts gelernt haben.
Kenne Deine Vorlagenfunktionen
Helm benutzt Go Templates für Vorlagen Ihrer Resourcedateien. Wobei Go schon einige eingebauten Funktionen mitbringt, haben wir noch viele andere hinzugefügt.
Als erstes haben wir alle Funktionen in der Sprig Bibliothek hinzugefügt.
Wir haben auch zwei spezielle Vorlagenfunktionen hinzugefügt: include
und required
. Die
include
Funktion erlaubt Ihnen das Hinzufügen anderer Vorlagen und das Zusammenfügen des
Ergebnisses in einer anderen Vorlagenfunktion.
Zum Beispiel diese Vorlage inkludiert eine Vorlage namens mytpl
,
dann wandelt es diese in Kleinschreibung um und quotet diese mit doppelten Anführungszeichen.
value: {{ include "mytpl" . | lower | quote }}
Die required
Function erlaubt Ihnen die Deklaration eines Wertes als notwendig für das
Vorlagenrendering. Wenn der Wert leer ist, wird das Vorlagenrendern fehlschlagen und dem
Benutzer eine Fehlermeldung ausgeben.
Das folgende Beispiel der required
Funktion deklariert einen Eintrag für
.Values.who
, der notwendig ist und gibt einen Fehler aus, wenn dieser fehlt:
value: {{ required "A valid .Values.who entry required!" .Values.who }}
Strings quoten, Integers nicht quoten
Wenn Sie mit Strings arbeiten, sind Sie mit Quoten immer auf der sicheren Seite:
name: {{ .Values.MyName | quote }}
Aber wenn Sie mit Integers arbeiten quoten Sie nicht die Werte. Das kann in vielen Fällen zu Fehlern in Kubernetes führen.
port: {{ .Values.Port }}
Dieser Hinweis gilt nicht für Umgebungsvariablen, die immer als String erwartet werden, auch wenn sie Integers repräsentieren:
env:
- name: HOST
value: "http://host"
- name: PORT
value: "1234"
Benutzen der 'include' Funktion
Go hat die Möglichkeit über eine eingebaute Funktion template
zwei Vorlagen zu
verbinden. Leider kann diese eingebaute Funktion nicht in Go Vorlagen Pipelines
verwendet werden.
Um das zu ermöglichen, eine Vorlage zu inkludieren und die Vorlagenausgabe weiter
zu bearbeiten, hat Helm eine spezielle include
Funktion:
{{ include "toYaml" $value | indent 2 }}
Dies inkludiert eine Vorlage namens toYaml
, gibt das $value
mit und
gibt dann die Ausgabe der Vorlage an die indent
Funktion weiter.
Da YAML Einrückungen und Leerzeichen viel Bedeutung zumisst, ist das ein grossartiger Weg um Codeschnippsel zu inkludieren, aber die Einrückungen im relevaten Kontext zu halten.
Benutzung der 'required' Funktion
Go stellt einen Weg zur Verfügung, um Vorlagenoptionen zu setzen und so das
Verhalten zu beeinflussen, wenn eine Map mit einem Schlüssel indiziert wird,
der in der Map nicht vorhanden ist. Das ist typischerweise gesetzt mit
template.Options("missingkey=option")
, wobei option
default
sein kann,
zero
oder error
. Wenn diese Option zu error gesetzt ist, wird die Ausführung
gestoppt, wennimmer der Wert leer ist. Es gibt Situationen, wenn Chart Entwickler
dieses Verhalten für bestimmte Werte in der values.yaml
Datei hervorrufen möchten.
Die required
Funktion gibt Entwicklern die Möglichkeit, einen Werteintrag zu
deklarieren, der für das Vorlagenrendern notwendig ist. Wenn der Wert in values.yaml
leer ist, wird die Vorlage nicht gerendert und eine Fehlermeldung wird vom Entwickler
bereitgestellt.
Zum Beispiel:
{{ required "A valid foo is required!" .Values.foo }}
Das oben wird eine Vorlage rendern, wenn .Values.foo
definiert ist, aber fehlschlagen,
wenn .Values.foo
nicht definiert ist.
Benutzen der 'tpl' Funktion
Die tpl
Funktion erlaubt Entwicklern Strings als Vorlagen in Vorlagen zu evaluieren.
Das ist nützlich, um einen Vorlagenstring als Wert zu einem Chart oder zum Rendern
einer externen Konfigurationsdatei zu verwenden. Syntax: {{ tpl TEMPLATE_STRING VALUES }}
Beispiele:
# values
template: "{{ .Values.name }}"
name: "Tom"
# template
{{ tpl .Values.template . }}
# output
Tom
Rendern einer externen Konfigurationsdatei:
# external configuration file conf/app.conf
firstName={{ .Values.firstName }}
lastName={{ .Values.lastName }}
# values
firstName: Peter
lastName: Parker
# template
{{ tpl (.Files.Get "conf/app.conf") . }}
# output
firstName=Peter
lastName=Parker
Erstellen eines Image Pull Secrets
Image Pull Secrets sind eine Kombination aus registry, username und
password. Sie brauchen sie vielleicht in einer Applikation, die Sie
bereitstellen möchten, aber zum Erstellen brauchen Sie öfters base64
.
Wir können eine Hilfsvorlage erstellen, um die Docker Konfigurationsdatei
mit einem Secret Payload zu erstellen. Hier kommt das Beispiel:
Zuerst nehmen wir an, dass die Zugangsdaten in der values.yaml
Datei definiert
sind, wie:
imageCredentials:
registry: quay.io
username: someone
password: sillyness
email: someone@host.com
Wir definieren dann unsere Hilfsvorlage wie folgt:
{{- define "imagePullSecret" }}
{{- with .Values.imageCredentials }}
{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }}
{{- end }}
{{- end }}
Zum Schluss verwenden wir die Hilfsvorlage in einer grösseren Vorlage, um das Secret Manifest zu erstellen:
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: {{ template "imagePullSecret" . }}
Automatisierte Bereitstellungen
Sehr oft werden ConfigMaps oder Secrets als Konfigurationsdateien in Container injiziert
oder dort sind andere externe Abhängigkeiten, was einen Pod Restart erforderlich macht.
Abhängig von der Applikation sollte ein Restart eine Aktualsierung durch helm upgrade
auslösen, aber die Deployment-Spezifikation selber ändert sich nicht und lässt die alte
Konfiguration als Ergebnis inkonsistent in der Bereitstellung.
Die sha256sum
Funktion kann benutzt werden, um in der Annotation Sektion des Deployments
dieses zu aktualisieren, wenn sich die Datei geändert hat.
kind: Deployment
spec:
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
[...]
In einem Ereignis, wenn Sie sowieso Ihr Deployment neu starten wollen, können Sie einen ähnlichen Schritt mit der Annotation gehen wie oben, aber diese mit einem zufälligen String ersetzen, sodass es immer eine Änderung gibt und diese einen Restart der Bereitstellung hervorruft:
kind: Deployment
spec:
template:
metadata:
annotations:
rollme: {{ randAlphaNum 5 | quote }}
[...]
Jede Benutzung dieser Vorlagenfunktion wird einen einzigartigen zufälligen String generieren. Das bedeutet, wenn dieser zufällige String mit mehreren Resourcen synchronisiert werden soll, müssen sich alle relevanten Resourcen in derselben Vorlagendatei befinden.
Beide Methoden helfen Ihnen, Ihre Aktualisierungsstrategie zu planen und Ausfälle zu verhindern.
HINWEIS: In der Vergangenheit empfohlen wir die Benutzung der Option
--recreate-pods
. Diese Option ist als veraltet markiert und in Helm 3
favorisieren wir die Methoden oben.
Helm anweisen, keine Resourcen zu installieren
Manchmal sollen Resourcen von Helm nicht deinstalliert werden, wenn Helm
läuft mit helm uninstall
. Chart Entwickler können eine Annotation zu einer
Resource hinzufügen, um das zu verhindern.
kind: Secret
metadata:
annotations:
"helm.sh/resource-policy": keep
[...]
(Als notwendig markieren)
Die Annotation "helm.sh/resource-policy": keep
instruiert Helm, das Löschen
dieser Resource bei Kommandos wie helm uninstall
, helm upgrade
oder
helm rollback
zu übergehen, was normalerweise zum Löschen führen würde.
Helm wird diese nicht länger verwalten. Das kann zu Problemen führen,
etwa bei helm install --replace
bei einer Version, die schon deinstalliert
ist, aber diese Resourcen behalten hat.
Benutzung von "Partials" und inkludierten Vorlagen
Manchmal möchten Sie Teile Ihres Charts wiederverwenden, in einem Block oder Vorlagenteile. Oft ist es sauberer, die in einer eigenen Datei vorzuhalten.
Im templates/
Verzeichnis werden Dateien, die mit einem Unterstrich
beginnen (_
), nicht als Ausgabedateien für Kubernetes Manifeste betrachtet.
Mit dieser Konvention, werden Hilfsvorlagen und Teile in eine
_helpers.tpl
Datei platziert.
Komplexe Charts mit vielen Abhängigkeiten
Viele Charts im CNCF Artifact Hub sind "building blocks" zum Erstellen erweiterter Applikationen. Aber Charts werden verwendet, zum Aufbau von Instanzen hochskalierbarer Anwendungen. In diesem Fall kann ein Schirm-Chart viele Unter-Charts haben, jede mit einer Funktion als Teil des Ganzen.
Die derzeitige Praxis zum Komponieren einer komplexten Applikation von
einzelnen Teilen ist ein Schirm-Chart auf höchster Stufe mit exponierten
globalen Konfigurationswerten und dann benutzen des charts/
Unterverzeichnis
zum Einschluss aller Komponenten.
YAML als Überschreibung von JSON
Entsprechend der Beschreibung der YAML Spezifikation ist YAML eine Überschreibung von JSON. Das bedeutet, dass jede valide JSON Struktur auch valide in YAML ist.
Dies hat Vorteile: Manchmal finden es Vorlagenentwickler einfacher eine Datenstruktur in JSON-ähnlicher Syntax anzugeben, anstatt sich mit dem leerzeichensensitiven YAML abzugeben.
Als bewährte Methode sollten Vorlagen einer YAML-ähnlichen Syntax folgen, unabhängig vom JSON. Die Syntax reduziert das Risiko eines Formatierungsproblems erheblich.
Vorsicht bei zufallsgenerierten Werten
Es gibt Funktionen in Helm, die zufällige Daten generieren, kryptographische Schlüssel usw.. Das ist gut so, aber achten Sie darauf, dass diese bem Aktualisieren und Rendern nochmal ausgeführt werden. Wenn eine Vorage unterschiedliche Daten wie beim letzten Lauf generiert, triggert das eine Aktualisierung der Resource.
Installieren oder Aktualisieren einer Version mit einem Kommando
Helm stellt einen Weg zur Verfügung, um Installation und Aktualisierung in einem Kommando
aufzurufen. Benutzen Sie helm upgrade
mit dem --install
Kommando. Das veranlasst Helm
erst nachzuschauen, ob eine Version schon installiert ist, bevor es sie installiert.
Wenn sie vorhanden ist, wird Helm die existierende Version aktualisieren.
$ helm upgrade --install <release name> --values <values file> <chart directory>