
Wir haben in einem
früheren Artikel über Helm gesprochen und „allgemein“ damit gearbeitet. Gehen wir nun die Praxis von der anderen Seite an - aus der Sicht des Erstellers der Diagramme (d. H. Pakete für Helm). Und obwohl dieser Artikel aus der Welt der Ausbeutung stammte, stellte sich heraus, dass er Materialien über Programmiersprachen ähnlicher war - so ist das Schicksal der Autoren der Charts. Ein Diagramm ist also eine Sammlung von Dateien ...
Diagrammdateien können in zwei Gruppen unterteilt werden:
- Dateien, die zum Generieren von Kubernetes-Ressourcenmanifesten erforderlich sind. Dazu gehören Vorlagen aus dem
templates
und Dateien mit Werten (Standardwerte werden in values.yaml
gespeichert). In dieser Gruppe befinden sich auch die Datei require.yaml und das charts
- all dies wird zum Organisieren verschachtelter Diagramme verwendet. - Begleitdateien mit Informationen, die hilfreich sein können, um Diagramme zu finden, sie kennenzulernen und zu verwenden. Die meisten Dateien in dieser Gruppe sind optional.
Weitere Informationen zu den Dateien beider Gruppen:
Chart.yaml
- Datei mit Informationen zum Diagramm;LICENSE
- eine optionale Textdatei mit einer Kartenlizenz;README.md
- eine optionale Datei mit Dokumentation;requirements.yaml
- eine optionale Datei mit einer Liste von Abhängigkeitsdiagrammen;values.yaml
- Datei mit Standardwerten für Vorlagen;charts/
- ein optionales Verzeichnis mit verschachtelten Diagrammen;templates/
- Verzeichnis mit Kubernetes Ressourcenmanifestvorlagen;templates/NOTES.txt
- Eine optionale Textdatei mit einem Hinweis, der dem Benutzer während der Installation und Aktualisierung angezeigt wird.
Um den Inhalt dieser Dateien besser zu verstehen, können Sie sich auf das
offizielle Handbuch für
Diagrammentwickler beziehen oder im
offiziellen Repository nach relevanten Beispielen suchen.
Beim Erstellen eines Diagramms im Großen und Ganzen kommt es darauf an, einen ordnungsgemäß gestalteten Satz von Dateien zu organisieren. Die Hauptschwierigkeit bei diesem „Design“ ist die Verwendung eines ziemlich fortschrittlichen Vorlagensystems, um das gewünschte Ergebnis zu erzielen. Zum Rendern von Kubernetes-Ressourcenmanifesten wird eine
Standard- Go-Vorlagen-Engine verwendet , die um Helm-Funktionen erweitert wird .
Erinnerung : Helm-Entwickler kündigten an, dass in der nächsten Hauptversion des Projekts - Helm 3 - Lua-Skripte unterstützt werden, die gleichzeitig mit Go-Vorlagen verwendet werden können. Ich werde auf diesen Punkt nicht näher eingehen - dies (und andere Änderungen in Helm 3) können hier gelesen werden .So sieht Helm 2 beispielsweise aus wie die Kubernetes-Manifestvorlage der
Bereitstellung für ein WordPress-Blog aus einem
früheren Artikel :
deploy.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: {{ template "fullname" . }} labels: app: {{ template "fullname" . }} chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" spec: replicas: {{ .Values.replicaCount }} template: metadata: labels: app: {{ template "fullname" . }} chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" release: "{{ .Release.Name }}" spec: {{- if .Values.image.pullSecrets }} imagePullSecrets: {{- range .Values.image.pullSecrets }} - name: {{ . }} {{- end}} {{- end }} containers: - name: {{ template "fullname" . }} image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy | quote }} env: - name: ALLOW_EMPTY_PASSWORD {{- if .Values.allowEmptyPassword }} value: "yes" {{- else }} value: "no" {{- end }} - name: MARIADB_HOST {{- if .Values.mariadb.enabled }} value: {{ template "mariadb.fullname" . }} {{- else }} value: {{ .Values.externalDatabase.host | quote }} {{- end }} - name: MARIADB_PORT_NUMBER {{- if .Values.mariadb.enabled }} value: "3306" {{- else }} value: {{ .Values.externalDatabase.port | quote }} {{- end }} - name: WORDPRESS_DATABASE_NAME {{- if .Values.mariadb.enabled }} value: {{ .Values.mariadb.db.name | quote }} {{- else }} value: {{ .Values.externalDatabase.database | quote }} {{- end }} - name: WORDPRESS_DATABASE_USER {{- if .Values.mariadb.enabled }} value: {{ .Values.mariadb.db.user | quote }} {{- else }} value: {{ .Values.externalDatabase.user | quote }} {{- end }} - name: WORDPRESS_DATABASE_PASSWORD valueFrom: secretKeyRef: {{- if .Values.mariadb.enabled }} name: {{ template "mariadb.fullname" . }} key: mariadb-password {{- else }} name: {{ printf "%s-%s" .Release.Name "externaldb" }} key: db-password {{- end }} - name: WORDPRESS_USERNAME value: {{ .Values.wordpressUsername | quote }} - name: WORDPRESS_PASSWORD valueFrom: secretKeyRef: name: {{ template "fullname" . }} key: wordpress-password - name: WORDPRESS_EMAIL value: {{ .Values.wordpressEmail | quote }} - name: WORDPRESS_FIRST_NAME value: {{ .Values.wordpressFirstName | quote }} - name: WORDPRESS_LAST_NAME value: {{ .Values.wordpressLastName | quote }} - name: WORDPRESS_BLOG_NAME value: {{ .Values.wordpressBlogName | quote }} - name: WORDPRESS_TABLE_PREFIX value: {{ .Values.wordpressTablePrefix | quote }} - name: SMTP_HOST value: {{ .Values.smtpHost | quote }} - name: SMTP_PORT value: {{ .Values.smtpPort | quote }} - name: SMTP_USER value: {{ .Values.smtpUser | quote }} - name: SMTP_PASSWORD valueFrom: secretKeyRef: name: {{ template "fullname" . }} key: smtp-password - name: SMTP_USERNAME value: {{ .Values.smtpUsername | quote }} - name: SMTP_PROTOCOL value: {{ .Values.smtpProtocol | quote }} ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: httpGet: path: /wp-login.php {{- if not .Values.healthcheckHttps }} port: http {{- else }} port: https scheme: HTTPS {{- end }} {{ toYaml .Values.livenessProbe | indent 10 }} readinessProbe: httpGet: path: /wp-login.php {{- if not .Values.healthcheckHttps }} port: http {{- else }} port: https scheme: HTTPS {{- end }} {{ toYaml .Values.readinessProbe | indent 10 }} volumeMounts: - mountPath: /bitnami/apache name: wordpress-data subPath: apache - mountPath: /bitnami/wordpress name: wordpress-data subPath: wordpress - mountPath: /bitnami/php name: wordpress-data subPath: php resources: {{ toYaml .Values.resources | indent 10 }} volumes: - name: wordpress-data {{- if .Values.persistence.enabled }} persistentVolumeClaim: claimName: {{ .Values.persistence.existingClaim | default (include "fullname" .) }} {{- else }} emptyDir: {} {{ end }} {{- if .Values.nodeSelector }} nodeSelector: {{ toYaml .Values.nodeSelector | indent 8 }} {{- end -}} {{- with .Values.affinity }} affinity: {{ toYaml . | indent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{ toYaml . | indent 8 }} {{- end }}
Nun zu den Grundprinzipien und Merkmalen der Standardisierung in Helm. Die meisten der folgenden Beispiele stammen aus den Diagrammen des
offiziellen Repositorys .
Vorlagen
Vorlagen: {{ }}
Alles, was mit Vorlagen zu tun hat, ist in doppelte geschweifte Klammern gewickelt. Text außerhalb der geschweiften Klammern bleibt beim Rendern unverändert.
Kontextwert:.
Beim Rendern einer Datei oder eines Teils
(weitere Informationen zum Wiederverwenden von Vorlagen finden Sie in den nächsten Abschnitten des Artikels) wird der Wert ausgelöst, auf den intern über die Kontextvariable zugegriffen werden kann. Bei Übergabe als Argument an eine Struktur wird der Punkt verwendet, um auf die Felder und Methoden dieser Struktur zuzugreifen.
Der Wert der Variablen ändert sich während des Rendervorgangs
abhängig vom Kontext, in dem sie verwendet wird. Die meisten Blockanweisungen überschreiben die Kontextvariable im Hauptblock.
Die Hauptoperatoren und ihre Funktionen werden nachstehend nach Kenntnis der grundlegenden Helmstruktur erläutert.Die Grundstruktur von Helm
Beim Rendern von Manifesten wird eine Struktur mit den folgenden Feldern in die Vorlagen geworfen:
- Feld
.Values
- für den Zugriff auf die Parameter, die während der Installation und Aktualisierung der Version festgelegt werden. Dazu gehören die Werte der Optionen --set
, --set-string
und --set-file
sowie die Parameter von Dateien mit Werten, die Datei values.yaml
und die Dateien, die den Werten der Optionen --values
:
containers: - name: main image: "{{ .Values.image }}:{{ .Values.imageTag }}" imagePullPolicy: {{ .Values.imagePullPolicy }}
.Release
- um Release-Daten zu Rollout, Installation oder Aktualisierung, Release-Name, Namespace und den Werten mehrerer weiterer Felder zu verwenden, die beim Generieren von Manifesten hilfreich sein können:
metadata: labels: heritage: "{{ .Release.Service }}" release: "{{ .Release.Name }}" subjects: - namespace: {{ .Release.Namespace }}
.Chart
- um auf Diagramminformationen zuzugreifen. Die Felder entsprechen dem Inhalt der Datei Chart.yaml
:
labels: chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
- Struktur
.Files
- zum Arbeiten mit Dateien, die im Diagrammverzeichnis gespeichert sind; Die Struktur und die verfügbaren Methoden finden Sie hier . Beispiele:
data: openssl.conf: | {{ .Files.Get "config/openssl.conf" | indent 4 }}
data: {{ (.Files.Glob "files/docker-entrypoint-initdb.d/*").AsConfig | indent 2 }}
.Capabilities
- um auf Informationen zu dem Cluster zuzugreifen, in dem der .Capabilities
wird:
{{- if .Capabilities.APIVersions.Has "apps/v1beta2" }} apiVersion: apps/v1beta2 {{- else }} apiVersion: extensions/v1beta1 {{- end }}
{{- if semverCompare "^1.9-0" .Capabilities.KubeVersion.GitVersion }} apiVersion: apps/v1 {{- else }}
Betreiber
Wir beginnen natürlich mit den
else
if
,
else if
und
else
:
{{- if .Values.agent.image.tag }} image: "{{ .Values.agent.image.repository }}:{{ .Values.agent.image.tag }}" {{- else }} image: "{{ .Values.agent.image.repository }}:v{{ .Chart.AppVersion }}" {{- end }}
Der
range
ist für die Arbeit mit Arrays und Karten ausgelegt. Wenn ein Array als Argument übergeben wird und Elemente enthält, wird für jedes Element ein Block nacheinander ausgeführt (in diesem Fall wird der Wert innerhalb des Blocks über die Kontextvariable verfügbar):
{{- range .Values.ports }} - name: {{ .name }} port: {{ .containerPort }} targetPort: {{ .containerPort}} {{- else }} ... {{- end}}
{{ range .Values.tolerations -}} - {{ toYaml . | indent 8 | trim }} {{ end }}
Um mit Maps zu arbeiten, wird eine Syntax mit Variablen bereitgestellt:
{{- range $key, $value := .Values.credentials.secretContents }} {{ $key }}: {{ $value | b64enc | quote }} {{- end }}
Ein ähnliches Verhalten tritt
with
Operator: auf: Wenn das übergebene Argument vorhanden ist, wird der Block ausgeführt und die Kontextvariable im Block entspricht dem Wert des Arguments. Zum Beispiel:
{{- with .config }} config: {{- with .region }} region: {{ . }} {{- end }} {{- with .s3ForcePathStyle }} s3ForcePathStyle: {{ . }} {{- end }} {{- with .s3Url }} s3Url: {{ . }} {{- end }} {{- with .kmsKeyId }} kmsKeyId: {{ . }} {{- end }} {{- end }}
Um die Vorlagen wiederzuverwenden, kann ein Bundle aus
define [name]
und
template [name] [variable]
verwendet werden, wobei der übergebene Wert über die Kontextvariable im
define
Block verfügbar gemacht wird:
apiVersion: v1 kind: ServiceAccount metadata: name: {{ template "kiam.serviceAccountName.agent" . }} ... {{- define "kiam.serviceAccountName.agent" -}} {{- if .Values.serviceAccounts.agent.create -}} {{ default (include "kiam.agent.fullname" .) .Values.serviceAccounts.agent.name }} {{- else -}} {{ default "default" .Values.serviceAccounts.agent.name }} {{- end -}} {{- end -}}
Einige Funktionen, die bei der Verwendung von
define
oder einfacher partiell berücksichtigt werden müssen:
- Teilweise deklariert sind global und können in allen Dateien des
templates
. - Das Hauptdiagramm wird zusammen mit den abhängigen Diagrammen kompiliert. Wenn also zwei Teilteilnamen des gleichen Typs vorhanden sind, wird der zuletzt geladene verwendet. Wenn Sie einen Teil benennen, ist es üblich, einen Diagrammnamen hinzuzufügen, um solche Konflikte zu vermeiden:
define "chart_name.partial_name"
. define "chart_name.partial_name"
.
Variablen: $
Zusätzlich zur Arbeit mit dem Kontext können Sie Daten mithilfe von Variablen speichern, ändern und wiederverwenden:
{{ $provider := .Values.configuration.backupStorageProvider.name }} ... {{ if eq $provider "azure" }} envFrom: - secretRef: name: {{ template "ark.secretName" . }} {{ end }}
Beim Rendern einer Datei oder eines Teils hat
$
dieselbe Bedeutung wie der Punkt. Im Gegensatz zur Kontextvariablen (Punkt)
ändert sich der Wert von
$
im Kontext von Blockanweisungen nicht, sodass Sie gleichzeitig mit dem Kontextwert der Blockanweisung und der grundlegenden Helmstruktur arbeiten können (oder mit dem Wert, der an partiell übergeben wird, wenn wir über die Verwendung von
$
innerhalb partiell'a sprechen). . Unterschied Illustration:
context: {{ . }} dollar: {{ $ }} with: {{- with .Chart }} context: {{ . }} dollar: {{ $ }} {{- end }} template: {{- template "flant" .Chart -}} {{ define "flant" }} context: {{ . }} dollar: {{ $ }} with: {{- with .Name }} context: {{ . }} dollar: {{ $ }} {{- end }} {{- end -}}
Als Ergebnis der Verarbeitung dieser Vorlage stellt sich Folgendes heraus (der Übersichtlichkeit halber werden in der Ausgabe der Struktur die entsprechenden Pseudonamen ersetzt):
context: # helm dollar: # helm with: context: #.Chart dollar: # helm template: context: #.Chart dollar: #.Chart with: context: habr dollar: #.Chart
Und hier ist ein echtes Beispiel für die Verwendung dieser Funktion:
{{- if .Values.ingress.enabled -}} {{- range .Values.ingress.hosts }} apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ template "nats.fullname" $ }}-monitoring labels: app: "{{ template "nats.name" $ }}" chart: "{{ template "nats.chart" $ }}" release: {{ $.Release.Name | quote }} heritage: {{ $.Release.Service | quote }} annotations: {{- if .tls }} ingress.kubernetes.io/secure-backends: "true" {{- end }} {{- range $key, $value := .annotations }} {{ $key }}: {{ $value | quote }} {{- end }} spec: rules: - host: {{ .name }} http: paths: - path: {{ default "/" .path }} backend: serviceName: {{ template "nats.fullname" $ }}-monitoring servicePort: monitoring {{- if .tls }} tls: - hosts: - {{ .name }} secretName: {{ .tlsSecret }} {{- end }} --- {{- end }} {{- end }}
Einrückung
Bei der Entwicklung von Vorlagen können zusätzliche Ränder verbleiben: Leerzeichen, Tabulatoren, Zeilenvorschübe. Mit ihnen sieht die Datei einfach besser lesbar aus. Sie können sie entweder aufgeben oder eine spezielle Syntax verwenden, um Einrückungen um die verwendeten Muster zu entfernen:
{{- variable }}
schneidet vorherige Leerzeichen ab;{{ variable -}}
schneidet nachfolgende Leerzeichen ab;{{- variable -}}
sind beide Optionen.
Ein Beispiel für eine Datei, deren Verarbeitung der Line
habr flant helm
:
habr {{- " flant " -}} helm
Eingebaute Funktionen
Alle in die Vorlage integrierten Funktionen finden Sie unter
folgendem Link . Hier werde ich nur über einige von ihnen erzählen.
Die
index
dient zum Zugriff auf Elemente eines Arrays oder von Maps:
definitions.json: | { "users": [ { "name": "{{ index .Values "rabbitmq-ha" "rabbitmqUsername" }}", "password": "{{ index .Values "rabbitmq-ha" "rabbitmqPassword" }}", "tags": "administrator" } ] }
Die Funktion verwendet eine beliebige Anzahl von Argumenten, mit denen Sie mit verschachtelten Elementen arbeiten können:
$map["key1"]["key2"]["key3"] => index $map "key1" "key2" "key3"
Zum Beispiel:
httpGet: {{- if (index .Values "pushgateway" "extraArgs" "web.route-prefix") }} path: /{{ index .Values "pushgateway" "extraArgs" "web.route-prefix" }}/#/status {{- end }}
Boolesche Operationen werden in der Template-Engine als Funktionen (und
nicht als Operatoren) implementiert. Alle Argumente für sie werden beim Bestehen ausgewertet:
{{ if and (index .Values field) (eq (len .Values.field) 10) }} ... {{ end }}
Wenn kein Feld vorhanden
field
schlägt das Rendern
field
Vorlage fehl (
error calling len: len of untyped nil
): Die zweite Bedingung wird überprüft, obwohl die erste nicht erfüllt wurde. Es lohnt sich, eine Notiz zu machen und solche Fragen zu lösen, indem Sie sie in mehrere Prüfungen aufteilen:
{{ if index . field }} {{ if eq (len .field) 10 }} ... {{ end }} {{ end }}
Pipeline ist eine einzigartige Funktion von Go-Vorlagen, mit der Sie Ausdrücke deklarieren können, die wie eine Pipeline in einer Shell ausgeführt werden. Formal ist die Pipeline eine Befehlskette, die durch das Symbol
|
. Ein Befehl kann ein einfacher
Wert oder ein Funktionsaufruf sein . Das Ergebnis jedes Befehls wird als
letztes Argument an den nächsten Befehl übergeben , und das Ergebnis des letzten Befehls in der Pipeline ist der Wert der gesamten Pipeline. Beispiele:
data: openssl.conf: | {{ .Files.Get "config/openssl.conf" | indent 4 }}
data: db-password: {{ .Values.externalDatabase.password | b64enc | quote }}
Zusätzliche Funktionen
Sprig ist eine Bibliothek mit
70 nützlichen Funktionen zur Lösung einer Vielzahl von Aufgaben. Aus Sicherheitsgründen schließt Helm die Funktionen
env
und
expandenv
aus, die den Zugriff auf Tiller-Umgebungsvariablen ermöglichen.
Die
include
Funktion wird wie die Standardvorlagenfunktion zum Wiederverwenden von Vorlagen verwendet. Im Gegensatz zur
template
kann die Funktion in der Pipeline verwendet werden, d.h. Übergeben Sie das Ergebnis an eine andere Funktion:
metadata: labels: {{ include "labels.standard" . | indent 4 }} {{- define "labels.standard" -}} app: {{ include "hlf-couchdb.name" . }} heritage: {{ .Release.Service | quote }} release: {{ .Release.Name | quote }} chart: {{ include "hlf-couchdb.chart" . }} {{- end -}}
Die
required
Funktion gibt Entwicklern die Möglichkeit, die zum Rendern der Vorlage erforderlichen Werte zu deklarieren: Wenn der Wert vorhanden ist, wird er beim Rendern der Vorlage verwendet, andernfalls endet das Rendern mit der vom Entwickler angegebenen Fehlermeldung:
sftp-user: {{ required "Please specify the SFTP user name at .Values.sftp.user" .Values.sftp.user | b64enc | quote }} sftp-password: {{ required "Please specify the SFTP user password at .Values.sftp.password" .Values.sftp.password | b64enc | quote }} {{- end }} {{- if .Values.svn.enabled }} svn-user: {{ required "Please specify the SVN user name at .Values.svn.user" .Values.svn.user | b64enc | quote }} svn-password: {{ required "Please specify the SVN user password at .Values.svn.password" .Values.svn.password | b64enc | quote }} {{- end }} {{- if .Values.webdav.enabled }} webdav-user: {{ required "Please specify the WebDAV user name at .Values.webdav.user" .Values.webdav.user | b64enc | quote }} webdav-password: {{ required "Please specify the WebDAV user password at .Values.webdav.password" .Values.webdav.password | b64enc | quote }} {{- end }}
Mit der Funktion
tpl
können Sie eine Zeichenfolge als Vorlage rendern. Im Gegensatz zu
template
und
include
können Sie mit dieser Funktion Vorlagen ausführen, die in Variablen übergeben werden, sowie Vorlagen rendern, die nicht nur im
templates
gespeichert sind. Wie sieht es aus?
Ausführen von Vorlagen aus Variablen:
containers: {{- with .Values.keycloak.extraContainers }} {{ tpl . $ | indent 2 }} {{- end }}
... und in
values.yaml
wir folgenden Wert:
keycloak: extraContainers: | - name: cloudsql-proxy image: gcr.io/cloudsql-docker/gce-proxy:1.11 command: - /cloud_sql_proxy args: - -instances={{ .Values.cloudsql.project }}:{{ .Values.cloudsql.region }}:{{ .Values.cloudsql.instance }}=tcp:5432 - -credential_file=/secrets/cloudsql/credentials.json volumeMounts: - name: cloudsql-creds mountPath: /secrets/cloudsql readOnly: true
Rendern einer Datei, die außerhalb des
templates
gespeichert ist:
apiVersion: batch/v1 kind: Job metadata: name: {{ template "mysqldump.fullname" . }} labels: app: {{ template "mysqldump.name" . }} chart: {{ template "mysqldump.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" spec: backoffLimit: 1 template: {{ $file := .Files.Get "files/job.tpl" }} {{ tpl $file . | indent 4 }}
... im Diagramm befindet sich entlang des Pfads
files/job.tpl
die folgende Vorlage:
spec: containers: - name: xtrabackup image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy | quote }} command: ["/bin/bash", "/scripts/backup.sh"] envFrom: - configMapRef: name: "{{ template "mysqldump.fullname" . }}" - secretRef: name: "{{ template "mysqldump.fullname" . }}" volumeMounts: - name: backups mountPath: /backup - name: xtrabackup-script mountPath: /scripts restartPolicy: Never volumes: - name: backups {{- if .Values.persistentVolumeClaim }} persistentVolumeClaim: claimName: {{ .Values.persistentVolumeClaim }} {{- else -}} {{- if .Values.persistence.enabled }} persistentVolumeClaim: claimName: {{ template "mysqldump.fullname" . }} {{- else }} emptyDir: {} {{- end }} {{- end }} - name: xtrabackup-script configMap: name: {{ template "mysqldump.fullname" . }}-script
Hier endete die Einführung in die Grundlagen der Standardisierung in Helm ...
Fazit
Der Artikel beschreibt die Struktur von Helm-Diagrammen und untersucht im Detail die Hauptschwierigkeiten bei ihrer Erstellung - Vorlage: Grundprinzipien, Syntax, Funktionen und Go-Template-Operatoren, zusätzliche Funktionen.
Wie fange ich an, mit all dem zu arbeiten? Da Helm bereits ein ganzes Ökosystem ist, können Sie sich immer Beispiele für Diagramme für ähnliche Pakete ansehen. Wenn Sie beispielsweise eine neue Nachrichtenwarteschlange packen möchten, sehen Sie sich
das öffentliche RabbitMQ-Diagramm an . Natürlich verspricht Ihnen niemand ideale Implementierungen in vorhandenen Paketen, aber sie sind als Ausgangspunkt perfekt. Der Rest kommt mit Übung, in der die
Befehle zum
--dry-run
der
--dry-run
und zum
Debuggen von Helmflusen Ihnen helfen und die Installation mit der Option
--dry-run
.
Für ein umfassenderes Verständnis der Entwicklung von Helm-Diagrammen, Best Practices und verwendeten Technologien empfehle ich, dass Sie sich unter den folgenden Links (alle in englischer Sprache) mit den Materialien vertraut machen:
Und am Ende des nächsten Helm-Materials füge ich eine Umfrage bei, die hilft, besser zu verstehen, auf welche anderen Artikel über Helm die Habr-Leser warten (oder nicht warten?). Vielen Dank für Ihre Aufmerksamkeit!
PS
Lesen Sie auch in unserem Blog: