Helm: Helm sollte Deep Merge für mehrere Wertedateien durchführen

Erstellt am 9. Feb. 2018  ·  31Kommentare  ·  Quelle: helm/helm

Es sieht so aus, als ob # 1620 diese Funktionalität bereitstellen sollte, aber ich sehe, dass eine Liste in der zuletzt angegebenen Wertedatei die Liste aus der vorherigen Datei vollständig überschreibt

Ich habe 2 zusätzliche Wertedateien foo.yaml und bar.yaml wie folgt:

foo.yaml

cronjob:
  fileName: foo_job
  schedule: "0 11 * * *"
  env:
    - name: FOO
      value: bar

bar.yaml

cronjob:
  env:
  - name: BAR
    value: foo

cronjob.yaml Vorlage

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: {{ template "cronjob.fullname" . }}
  labels:
    app: {{ template "cronjob.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  schedule: {{ .Values.cronjob.schedule | quote }}
  startingDeadlineSeconds: {{ .Values.cronjob.startingDeadlineSeconds }}
  jobTemplate:
    spec:
      template:
        metadata:
          name: {{ template "cronjob.fullname" . }}
        spec:
          restartPolicy: Never
          imagePullSecrets:
          - name: quay-sts
          containers:
          - name: {{ template "cronjob.fullname" . }}
            imagePullPolicy: Always
            image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
            args:
            - npm
            - start
            - {{ .Values.cronjob.fileName }}
{{ if .Values.cronjob.env }}
            env:
{{ toYaml .Values.cronjob.env | indent 12 }}
{{ end }}

Beim Ausführen von helm install --dry-run --debug ./cronjob -f values/foo.yaml,values/bar.yaml oder beim Ausführen von helm install --dry-run --debug ./cronjob -f values/foo.yaml -f values/bar.yaml

Es gibt Folgendes aus:

tatsächliche Ausgabe

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: intended-jaguar-cronjob
  labels:
    app: cronjob
    chart: cronjob-2.0.8
    release: intended-jaguar
    heritage: Tiller
spec:
  schedule: "0 11 * * *"
  startingDeadlineSeconds: 60
  jobTemplate:
    spec:
      template:
        metadata:
          name: intended-jaguar-cronjob
        spec:
          restartPolicy: Never
          imagePullSecrets:
          - name: quay-sts
          containers:
          - name: intended-jaguar-cronjob
            imagePullPolicy: Always
            image: XXXXXXXX
            args:
            - npm
            - start
            - foo_job

            env:
            - name: BAR
              value: foo

Ich erwarte, dass die env-Listen von values.yaml, foo.yaml und bar.yaml zusammengeführt wurden, was zu Folgendem führte:

erwartete Ausgabe

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: intended-jaguar-cronjob
  labels:
    app: cronjob
    chart: cronjob-2.0.8
    release: intended-jaguar
    heritage: Tiller
spec:
  schedule: "0 11 * * *"
  startingDeadlineSeconds: 60
  jobTemplate:
    spec:
      template:
        metadata:
          name: intended-jaguar-cronjob
        spec:
          restartPolicy: Never
          imagePullSecrets:
          - name: quay-sts
          containers:
          - name: intended-jaguar-cronjob
            imagePullPolicy: Always
            image: XXXXXXXX
            args:
            - npm
            - start
            - foo_job

            env:
            # anything from the env list in values.yaml
            # ...
            - name: FOO
              value: bar
            - name: BAR
              value: foo
questiosupport

Hilfreichster Kommentar

Wir könnten das auch nutzen. +1

Alle 31 Kommentare

Ich glaube, ich habe das Problem gefunden und versuche nicht, eine PR zu eröffnen

Wenn dies implementiert ist, sollte es optional sein, dh der Zusammenführungsmodus sollte als Befehlszeilenflag angegeben werden. Alles andere wäre eine bahnbrechende Veränderung und meiner Meinung nach in den meisten Fällen nicht wünschenswert. Das Problem ist, dass Sie die Standardeinstellungen für Listen nicht überschreiben können.

Hier ein Beispiel: https://github.com/kubernetes/charts/blob/5453fc144f6f9d722c6bb433790f90d7943a4fc3/stable/docker-registry/values.yaml#L19

Für diejenigen, die aus der Java-Welt kommen, löst Maven dies für Plugin-Konfigurationen wie folgt: https://blog.sonatype.com/2011/01/maven-how-to-merging-plugin-configuration-in-complex-projects/

Hallo @connormckelvey

Es tut uns leid, dass Sie nicht die erwarteten Ergebnisse erzielt haben, und ich stimme zu, dass dies eine frustrierende Einschränkung ist. Wenn Sie daran interessiert sind, eine Funktion beizutragen, erstellen Sie bitte einen Vorschlag , in dem die Implementierung aufgeführt ist und der ein Flag wie von @unguiculus vorgeschlagen enthalten sollte.

Danke @unguiculus! Ich sehe jetzt, wie dies als eine bahnbrechende Veränderung angesehen werden würde.

Das Problem ist, dass Sie die Standardeinstellungen für Listen nicht überschreiben können.

Wollen Sie damit sagen, dass Sie nicht in der Lage sind, eine gesamte Liste zu überschreiben (z. B. eine Liste mit 3 Elementen mit einer Liste mit 1 Element zu überschreiben)? Was ich vorschlage, würde es Ihnen ermöglichen, einzelne voreingestellte Elemente in einer Liste zu überschreiben. Sie erhalten mehr Kontrolle.

Ich denke, ich verstehe nicht, warum das Zusammenführen von Karten wünschenswert ist und das Zusammenführen von Listen nicht wünschenswert ist, außer dass zum gegenwärtigen Zeitpunkt einige Projekte ein bestimmtes Verhalten erwarten, während andere ein anderes erwarten.

@ jascott1 Danke, ich werde auf jeden Fall mit meinem Team über den Vorschlag nachdenken, aber was ich wirklich brauchte, war eine schnelle Lösung, von der ich dachte, dass sie mit einer schnellen PR gelöst werden könnte. Zu diesem Zeitpunkt müssen wir uns auf unser unmittelbares Problem konzentrieren.

Wurde diese Funktionalität jemals hinzugefügt?

Ich sehe dies auch als Einschränkung, insbesondere für Projekte wie prometheus, bei denen die gesamte prometheus-Konfiguration in der Wertedatei definiert ist. Da ich nicht in der Lage bin, Unterschlüssel zusammenzuführen, muss ich fast dieselbe Konfiguration pro Umgebung kopieren, was eine enorme Wiederholung des Codes darstellt.

https://github.com/helm/helm/pull/4806 könnte relevant sein. In diesem Fall sollte dies für 2.12.0 vorhanden sein (noch nicht veröffentlicht; probieren Sie die kanarische Version zum Testen aus).

Ich bin gerade darauf gestoßen und bin verwirrt, warum dies geschlossen wurde. Wie @mlushpenko feststellt , scheint dies eine ziemlich große Einschränkung für die Verwaltung einer Bereitstellung mit angemessener Größe zu sein. In unserem Fall möchten wir in der Lage sein, Affinitätsregeln aus mehreren Ebenen zu kombinieren und einen Standardregelsatz im Basisdiagramm bereitzustellen, der bei der Bereitstellung erweitert werden kann. Derzeit müssen wir jedoch die Standard-Affinitätsregeln in jeder Datei zum Überschreiben von Werten wiederholen. Nicht einmal in der Nähe von DRY.

Hinzu kommt, dass es nicht möglich zu sein scheint, Standardwerte anzugeben, die auf Dingen wie dem Versionsnamen basieren, die erst nach Durchführung der Bereitstellung bekannt sind (vorausgesetzt, dies hat nichts damit zu tun, aber dies bedeutet, dass die übergeordnete Affinität im Wesentlichen besteht bei jedem Einsatz durchzuführen).

@sfitts hast du dir # 4806 angesehen?

@ Bacongobbler Ich habe und ich sehe nicht, wie es gilt. AFAICT behandelt nur Aktualisierungen, die während des Upgrades eines bereits bereitgestellten Diagramms vorgenommen wurden, und stellt sicher, dass vorhandene Werte nicht durch neue beeinträchtigt werden. Sicher verwandt, aber ich sehe nicht, wie es hilft, die Notwendigkeit zu vermeiden, Informationen zu wiederholen, wenn Wertedateien während der Erstinstallation kombiniert werden.

Diese Funktion würde uns auch sehr gefallen. Wir haben eine Hierarchie von Wertedateien (z. B. base.yaml <- qa.yaml), die über -f values/base.yaml,values/qa.yaml an das Ruder übergeben werden. Wie andere bereits erwähnt haben, wäre es großartig, wenn wir die qa-Werte zu den Basiswerten zusammenführen könnten, ohne alles wiederholen zu müssen.

Ich könnte das auch gebrauchen

Ich weiß, dass dieses Problem geschlossen ist, aber als Referenz für diejenigen, die hier suchen und darüber nachdenken, das Problem zu lösen, werde ich einen Vergleich mit dem Küchenchef liefern.

Dort wird dieses Problem durch einen festen Satz von Prioritäten für Werte (die sie Attribute nennen) behoben. Arrays mit derselben Priorität werden zusammengeführt, während ein Wert mit höherer Priorität Werte mit niedrigerer Priorität ersetzt.

https://docs.chef.io/attributes.html#about -deep-merge

Wenn Sie etwas Ähnliches in helm implementieren, ist es meiner Meinung nach sinnvoll, neue Versionen von --set und --values ​​einzuführen, z. B. --overrideSet und --overrideValues ​​für Werte mit hoher Priorität. Zum Festlegen von Werten in einem Diagramm kann eine andere Datei mit dem Namen overrideValues.yaml zugelassen werden, die Werte mit einer höheren Priorität als in der Datei values.yaml festlegt.

Wir könnten das auch nutzen. +1

Ich bin ein bisschen verwirrt. Das offene Ende dieses Threads gab mir den Eindruck, dass dieses verschmelzende Ding immer noch im Ruder fehlt. Nach dem Ausprobieren (wir führen ein Helm-Upgrade durch ... -f basic.yaml -f profile_extends_basic.yaml) scheint es korrekt zu funktionieren. Zumindest für mich scheint die # 4806 es geschafft zu haben.

Ich bin ein bisschen verwirrt. Das offene Ende dieses Threads gab mir den Eindruck, dass dieses verschmelzende Ding immer noch im Ruder fehlt. Nach dem Ausprobieren (wir führen ein Helm-Upgrade durch ... -f basic.yaml -f profile_extends_basic.yaml) scheint es korrekt zu funktionieren. Zumindest für mich scheint die # 4806 es geschafft zu haben.

@janotav Die # 4806 adressierte Deep Merge für das Upgrade-Szenario. Bei diesem Problem ging es um das Zusammenführen von Werten während der normalen Installation.

Ja. Diese Funktion wird benötigt. Ein weiterer Anwendungsfall besteht darin, eine Teilmenge von Umgebungsvariablen in verschiedenen Bereitstellungsumgebungen anzugeben / zusammenzuführen / zu überschreiben.

Dies ist weiterhin ein Problem mit Helm 2.x. Weiß jemand, ob Helm 3.x eine Lösung für das (optionale) Zusammenführen von Arrays während der Installation hat?

Auch ich würde diese Funktionalität gerne sehen!

Für die Leute hier, die die Liste der Umgebungsvariablen ändern müssen, die Sie an Ihre Bereitstellungsvorlage übergeben, besteht die Lösung darin, die Variablen und Standardeinstellungen als dict und nicht als list !

values.yaml:

env:
  key1: default1
  key2: default2

Werte-Produktion.yaml:

env:
  key1: prod-value

deploy.yaml:

{{- range $key, $value :=  .Values.env }}
- name: {{ $key }}
  value: {{ $value | quote }}
{{- end }}

Mit Werteproduktion gerendert:

- name: key1
  value: "prod-value"
- name: key2
  value: "default2"

@tarrall Können Sie die Steuerbefehle

Ich versuche, mein Helmdiagramm Standardwerte zu enthalten, die in eine Konfigurationskarte eingefügt werden, und dann eine umgebungsspezifische Datei zu haben, die ich in die Standardeinstellungen einfüge, aber sie wird stattdessen überschrieben.

Ich verwende das range $key,$value in meiner configmap-Vorlage.

Ist es wichtig, ob Sie übrigens helm2 oder helm3 verwenden?

Marionette mit Hiera schafft dies auch und gibt Optionen für die Art der Zusammenführung, die Sie möchten. Ich wiederhole auch Code, weil ich mehrere Pods habe, die genau dieselbe Datei aus einer Konfigurationskarte und eine andere für jeden Pod spezifisch bereitstellen müssen. Das Common sollte in einer oberen Hierarchie deklariert werden und dann die Option geben, die folgenden Werte zusammenzuführen

@bacongobbler kann dieses Problem nicht erneut öffnen, da https://github.com/helm/helm/pull/4806 dieses Problem nicht löst, da es in Karten und in einem Upgrade- Prozess tief zusammengeführt wird. Was @connormckelvey erwähnte, war die Fähigkeit, Deep Arrays durchzuführen . Diese Art der Tiefenzusammenführung sollte für Installations- und Upgrade-Situationen funktionieren.

Ich bin überrascht, dass das Ruder keine Lösung dafür hat. Die von @tarrall vorgeschlagene @connormckelvey bitte könnten Sie wieder öffnen?

Ich verwende das folgende Skript als Problemumgehung:

Yaml importieren
aus deepmerge import immer_merger

fileA = "tmp.yaml"
fileB = "feature.yaml"

mit open (fileA, 'r +') als f:
fileAdictionary = yaml.load (f)

mit open (fileB, 'r +') als f:
fileBdictionary = yaml.load (f)

result = always_merger.merge (fileAdictionary, fileBdictionary)
mit open ('newFile.yaml', 'w +') als f:
yaml.dump (Ergebnis, f)

Was @connormckelvey erwähnte, war die Fähigkeit, Deep Arrays durchzuführen . Diese Art der Tiefenzusammenführung sollte für Installations- und Upgrade-Situationen funktionieren.

Das derzeitige Verhalten beim Zusammenführen von zwei Arrays wird wahrscheinlich so bleiben, wie es ist. Ich glaube nicht, dass wir planen, das aktuelle Verhalten zu ändern, weshalb dieses Problem geschlossen ist.

Nehmen wir ein Beispiel. Hier habe ich ein einfaches values.yaml mit einem Wert als Array:

myList: [ "foo" ]

Dann führe ich folgendes aus:

helm install [...] --set myList={"bar"}

Was ist das erwartete Verhalten?

Wenn wir eine "tiefe Zusammenführung" der beiden Arrays in Betracht ziehen würden, wäre das resultierende Array [ "foo", "bar" ] .

Was ist jedoch, wenn der Benutzer die vorhandene Liste auf Null setzen möchte, was dazu führt, dass die Ausgabe [ "bar" ] ?

Das Problem bei einer tiefen Zusammenführung besteht darin, dass wir nicht bestimmen können, welches Verhalten der Benutzer erwartet. Es gibt auch keine Möglichkeit, vorhandene Werte auf Null zu setzen.

Aus diesem Grund existiert das aktuelle Verhalten wie es heute ist. Der Benutzer hat die Möglichkeit, die vom Diagrammautor in den Standardwerten festgelegten Werte sowie alle von anderen Wertedateien in der Befehlszeile festgelegten Werte auf Null zu setzen (entweder über --values/-f oder --set , --set-string , --set-file usw.). Wenn sie eine tiefe Verschmelzung durchführen möchten, können sie dies außerhalb der Band tun.

Sie können dies natürlich programmgesteuert tun, und @aknakshay beschreibt einen Weg, dies zu tun. Eine CLI ist jedoch nicht gut konzipiert, um komplexe Fälle zu vermitteln, z. B. ob --set myList={"bar"} bedeutet, dass der Benutzer eine Ersetzung oder eine gründliche Zusammenführung durchführen möchte.

Beachten Sie, dass dieselbe Nachricht bereits 2018 in einem früheren Kommentar hier übermittelt wurde. Eine Änderung des Verhaltens in eine tiefgreifende Zusammenführung von Arrays würde zu Abwärtskompatibilitätsproblemen führen und mehr Schaden als Nutzen verursachen.

Ich hoffe, dies verdeutlicht, wo dieser Vorschlag steht.

Das Zusammenführen kann immer über die Verwendung eines Befehlszeilenflags zulässig sein, wie in Kommentar 2 beschrieben (https://github.com/helm/helm/issues/3486#issuecomment-364534501). Normalerweise überschreiben die Werte des Benutzers die Standardeinstellungen, aber wenn ein Befehlszeilenflag bereitgestellt wird (z. B. --deepMergeInputs), wird eine gründliche Zusammenführung durchgeführt. Auf diese Weise würde der Benutzer mit der Notwendigkeit umgehen, vorhandene Werte auf Null zu setzen. Gibt es eine weitere Komplikation bei diesem Ansatz?

Ich bin mir nicht sicher, was "Out-of-Band" bedeutet.

Das Zusammenführen kann immer über die Verwendung eines Befehlszeilenflags zugelassen werden, so wie es in Kommentar 2 beschrieben wurde ( # 3486 (Kommentar) ). Normalerweise überschreiben die Werte des Benutzers die Standardeinstellungen, aber wenn ein Befehlszeilenflag bereitgestellt wird (z. B. --deepMergeInputs), wird eine gründliche Zusammenführung durchgeführt. Auf diese Weise würde der Benutzer mit der Notwendigkeit umgehen, vorhandene Werte auf Null zu setzen. Gibt es eine weitere Komplikation bei diesem Ansatz?

Ein solcher Alles-oder-Nichts-Ansatz ist sehr gefährlich, wenn große und / oder viele Wertedateien vorhanden sind. Ein weiteres Problem dabei ist, dass Sie das Verhalten in einem Diagramm dann nicht steuern können. Ich bevorzuge die Lösung, die ich unter https://github.com/helm/helm/issues/3486#issuecomment -477099409 beschrieben habe

Ich habe kürzlich festgestellt, dass bei Verwendung von toYaml nur das Yaml aus der Yaml-Datei mit der höchsten Priorität verwendet wird, anstatt die Tiefenzusammenführung wie für den Bereich durchzuführen.

Helmversion:
version.BuildInfo{Version:"v3.1.2", GitCommit:"d878d4d45863e42fd5cff6743294a11d28a9abce", GitTreeState:"clean", GoVersion:"go1.13.8"}

Tatsächlich unterstützt nur list das Zusammenführen nicht. Wir sind uns einig, dass alle list als map , umgeschrieben werden ( list in k8s hat im Allgemeinen einen Schlüssel namens name , und dieser name kann als Schlüssel für map )

value.yaml vor

# value.yaml 

volumeMounts:
    - mountPath: /data/log/
      name: logs

volumes:
    - emptyDir: {}
      name: logs

initContainers: []

envFrom: []

env:
  - name: NODE_ENV
    value: production
  - name: PORT
    value: "3333"
  - name: SOME_SECRET
    valueFrom:
      secretKeyRef:
        key: SOME_SECRET
        name: some-secret

value.yaml nach

# value.yaml

volumeMounts:
  logs:
    - mountPath: /data/log/
      name: logs

volumes:
  logs:
    - emptyDir: {}
      name: logs

initContainers: {}

envFrom: {}

env:
  NODE_ENV:
    - name: NODE_ENV
      value: production
  PORT:
    - name: PORT
      value: "3333"
  SOME_SECRET:
    - name: SOME_SECRET
      valueFrom:
        secretKeyRef:
          key: SOME_SECRET
          name: some-secret

deploy.yaml vor

{{- with .Values.env }}
    env:
    {{- toYaml . | nindent 8 }}
{{- end }}

deploy.yaml nach

{{- with .Values.env }}
    env:
    {{- range $key, $value := . }}
    {{- toYaml $value | nindent 8 }}
    {{- end }}
{{- end }}

Dies unterstützt die Zusammenführung von list .

Wenn Sie eine Konfiguration löschen möchten

env:
  NODE_ENV: null

Die Lösung von @tarrall funktionierte nicht für Werte vom Kartentyp, z. B. valueFrom . Der folgende Vorlagencode behandelt auch diesen Fall:

{{- range $ev_key, $ev_value :=  .Values.deployment.env }}
{{- if (typeIs "string" $ev_value) }}
          - name: {{ $ev_key }}
            value: {{ $ev_value | quote }}
{{- else }}
          - name: {{ $ev_key }}
{{ toYaml $ev_value | indent 12 }}
{{- end }}
{{- end }}
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen