Benutzer-Werkzeuge

Webseiten-Werkzeuge


it-wiki:kubernetes:deployments_mit_kustomize

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
it-wiki:kubernetes:deployments_mit_kustomize [2024/03/13 11:35] – [KUSTOMIZE] markoit-wiki:kubernetes:deployments_mit_kustomize [2024/03/13 12:33] (aktuell) – [Fazit] marko
Zeile 1: Zeile 1:
 ====== Parametrisierte Kubernetes Deployments mit kustomize ====== ====== Parametrisierte Kubernetes Deployments mit kustomize ======
-kustomize ermöglicht die Anpassung von Kubernetes-Deployments zur Erzeugung mehrerer Varianten (z. B. für unterschiedliche Umgebungen). Dabei werden die originalen YAML-Dateien nicht modifiziert, sondern mit Overlays überlagert. Im Gegensatz zu Helm kommt kustomize also ganz ohne Templates auswas die Verwendung besonders einfach machtIn diesem Blog-Post stellen wir die wichtigsten Features von kustomize anhand eines Beispiels vor.+In Kubernetes wird mithilfe von YAML-Konfigurationen festgelegt, auf welche Weise Applikationen in der Infrastruktur bereitgestellt werdenAber was, wenn wir unsere Applikation für mehrere verschiedene Umgebungen konfigurieren möchten? Für jede Umgebung eine einzelne YAML-Konfiguration zu erstellen ist oft mühselige Arbeit. Zum Glück existiert mit Kustomize ein Toolwelches genau diesen Arbeitsschritt automatisieren kann. 
 +Wie funktioniert Kustomize? Bevor wir uns mit dieser Frage beschäftigen, schauen wir uns erst einmal an einem Beispiel an, wie eine manuelle Konfiguration für verschiedene Umgebungen aussieht.
  
-Jegliche Ressourcen in Kubernetes werden als YAML-Dateien definiert und per "kubectl apply" an den API-Server geschicktNun dauert es nicht langebis von einem Deployment leicht unterschiedliche Varianten notwendig werdenIm einfachsten Fall wird in PROD eine andere Datenbank-URL benötigt als in DEV. Komplexer wird es, wenn die YAML-Dateien an andere User ausgeliefert werden (z.B. in OpenSource-Projekten) und so eigentlich jede Einstellung anpassbar sein soll.+In unserem Szenario läuft auf unserer Dev-Umgebung bisher ein Service, welcher über das HTTP-Protokoll auf Port 80 erreichbar istDieser Service soll nun auch auf der Testumgebung erreichbar seindort allerdings aus Sicherheitsgründen über HTTPS auf dem Port 443Um dies umzusetzen, muss für jede Umgebung eine separate Konfiguration angelegt werden:
  
-Diese "Tooling-Lücke" hat lange Zeit "Helm" gefüllt und sich zum De-facto-Standard entwickelt, der nun zu wackeln beginnt. Warum? Gerade in Deployment-Szenarien mit überschaubarer Komplexität macht Helm die Wartbarkeit unnötig schwer, bremst die Entwicklung und erhöht die Fehleranfälligkeit. In diesem Blog-Post schauen wir uns daher kustomize als Alternative an, welche kürzlich auch in die Kubernetes-CLI kubectl integriert wurde. Um das Fazit vorwegzunehmen: Ich würde kustomize insbesondere für kleinere Projekte empfehlen! +==== Konfiguration für die Dev-Umgebung: ==== 
- +<code yaml> 
-===== DAS ORIGINAL ===== +kind: Service 
-Schauen wir uns die Alternativen Schritt für Schritt an. Ein simples Deployment eines Alpine-Linux sieht bspw. so aus: +apiVersion: v1
-<code bash+
-apiVersion: apps/v1 +
-kind: Deployment+
 metadata: metadata:
-  name: my-app+  name: env-anzeige-frontend-https
 spec: spec:
-  replicas1+  typeLoadBalancer
   selector:   selector:
-    matchLabels: +    app: env-anzeige-frontend 
-      app: my-app +  ports
-  template+  - name: http 
-    metadata: +    port80 
-      labels: +
-        app: my-app +
-    spec: +
-      containers: +
-      - name: my-app +
-        image: alpine:3.10 +
-        tty: true +
-        stdin: true +
-        env: +
-          - name: foo +
-            value: bar +
-        resources: +
-          limits: +
-            memory: "64Mi" +
-            cpu"100m"+
 </code> </code>
  
-Hier ist nichts parametrisiert - diese YAML-Datei ist konform zur Kubernetes API-Spezifikation und wird somit direkt vom API-Server akzeptiert. Schreibt man eine solche YAML-Datei in einer IDE wie Visual Studio Code oder IntelliJ, kann man sich über Features wie Auto-Completion freuen. +==== Konfiguration für die Testumgebung mit geänderten Porteinstellungen: ==== 
- +<code yaml
-===== HELM ===== +kindService 
-Helm nutzt das Templating-System von Go und bündelt mehrere zusammengehörige Template-Dateien zu sog. Charts - häufig bleibt es ja nicht bei einem Deployment, sondern es gesellen sich noch weitere YAML-Dateien für Services, Ingresses, Secrets usw. hinzu, bevor daraus ein fachlich vollständiges Deployment-Paket wird. Mit dem Kommando helm create <app-name> kann man sich eine Vorlage erzeugen und diese weiter ausbauen. Wie sieht das Pendant für unser Alpine-Deployment aus? +apiVersion: v1
- +
-<code bash+
-# Filehelm/my-app/templates/deployment.yaml +
- +
-apiVersion: apps/v1 +
-kind: Deployment+
 metadata: metadata:
-  name: {{ include "my-app.fullname" . }} +  name: env-anzeige-frontend-https
-  labels: +
-{{ include "my-app.labels" . | indent 4 }}+
 spec: spec:
-  replicas{{ .Values.replicaCount }}+  typeLoadBalancer
   selector:   selector:
-    matchLabels: +    app: env-anzeige-frontend 
-      app.kubernetes.io/name{{ include "my-app.name" . }} +  ports
-      app.kubernetes.io/instance{{ .Release.Name }} +  - name: https 
-  template: +    port443
-    metadata: +
-      labels: +
-        app.kubernetes.io/name: {{ include "my-app.name" . }} +
-        app.kubernetes.io/instance{{ .Release.Name }} +
-    spec: +
-    {{- with .Values.imagePullSecrets }} +
-      imagePullSecrets: +
-        {{- toYaml . | nindent 8 }} +
-    {{- end }} +
-      containers: +
-        - name: {{ .Chart.Name }} +
-          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" +
-          imagePullPolicy: {{ .Values.image.pullPolicy }} +
-          tty: {{ .Values.tty }} +
-          stdin: {{ .Values.stdin }} +
-          env: +
-          {{- toYaml .Values.env | nindent 12 }} +
-          resources: +
-            {{- toYaml .Values.resources | nindent 12 }} +
-      {{- with .Values.nodeSelector }} +
-      nodeSelector: +
-        {{- toYaml . | nindent 8 }} +
-      {{- end }} +
-    {{- with .Values.affinity }} +
-      affinity: +
-        {{- toYaml . | nindent 8 }} +
-    {{- end }} +
-    {{- with .Values.tolerations }} +
-      tolerations: +
-        {{- toYaml . | nindent 8 }} +
-    {{- end }}+
 </code> </code>
  
-Lesbarkeit? Hm.+Um den Service für die Testumgebung zu konfigurieren, wurde die Dev-Konfig kopiert und nur der relevante Datensatz – die Porteinstellungen – geändert. Und genau an diesem Punkt gehen die Probleme los. Die YAMLs ständig manuell zu kopieren und anzupassen ist auf Dauer sehr zeitaufwändig. Außerdem entstehen durch das ständige "Hin-und-her-kopieren" verschiedene Konfigurationen, welche größtenteils identisch sind. Dadurch ist im Nachhinein schnell nicht mehr klar, was denn nun der aktuelle Master-Stand ist.
  
-IDE-Unterstützung wie Auto-Completion? Nicht mehr vorhandenbestenfalls rudimentär.+Kustomize kann diese Probleme lösenindem es die Anpassung bestehender Ressourcen vereinfacht und automatisiertDabei arbeitet Kustomize nach einem einfachen Grundkonzept: Es wird nur eine einzige Basiskonfiguration für die Bereitstellung der Anwendung angelegt. Für die einzelnen Umgebungen werden nur die an der Basis durchzuführenden Patches, die sogenannten Overlays, abgelegt. 
 +\\
  
-Ach so, zu der Template-Datei gehört natürlich noch eine values.yaml-Datei mit den Werten für die Platzhalter+{{ :it-wiki:kubernetes:b2ap3_large_bild1.png?nolink&600 |}} 
-<code bash> +\\ 
-# File: helm/my-app/values.yaml+ 
 +Schauen wir uns einmal an, wie wir unser Beispiel mit den Porteinstellungen in Kustomize umsetzen können. Als Erstes muss eine //kustomization.yaml// angelegt werden, welche alle benötigten Ressourcen und die zu verwendenden Patches auflistet.
  
-replicaCount: 1 +<code yaml> 
-  +#base/kustomization.yaml
-image: +
-  repository: alpine:3.10 +
-  tag: stable +
-  pullPolicy: IfNotPresent +
-  +
-tty: true +
-stdin: true +
-  +
-env: +
-  - name: foo +
-    value: bar +
- +
 resources: resources:
-  limits: +- service.yaml
-    cpu: 100m +
-    memory: 64Mi+
 </code> </code>
  
-Eigentlich haben wir jetzt - neben dem sperrigen Template - eine values.yaml-Datei, die fast genauso groß ist wie das OriginalHm.+<code yaml> 
 +#overlays/test/kustomization.yaml 
 +bases: 
 +- ../../base 
 +patches: 
 +- service-ports.yaml 
 +</code>
  
-Das Problem der Wartbarkeit kann man sich an dem kleinen Beispiel bereits vorstellen, wächst aber mit der Größe des jeweiligen Projektes. Das Deployment unserer vPW-Showcase-Umgebung besteht bspw. aus knapp 90 Template-Dateien mit über 3000 Zeilen Code, wobei externe Abhängigkeiten wie Elasticsearch, Kafka und Co hier noch nicht mit eingerechnet sind. Was in überschaubaren Deployments "nur" den Spaß der Entwickler trübt, wird bei größeren Setups zu einem relevanten Risiko, denn die Fehleranfälligkeit nimmt extrem zu.+{{ :it-wiki:kubernetes:b2ap3_large_bild2.png?nolink&400 |}}
  
-===== KUSTOMIZE ===== +Durch Patches können einzelne YAML-Attribute einer Konfiguration hinzugefügt oder überschrieben werden. Hierzu wird eine neue YAML-Datei angelegt, welche den Namen der zu patchenden Ressource und alle zu ändernden Attribute beinhaltet.
-Was macht kustomize nun anders?+
  
-  * **Keine Templates:** kustomize setzt auf eine Overlay-/Patch-Strategie, dh. man schreibt "normale" YAML-Dateien, die durch Overlays ergänzt werden (also keine Templates mit Platzhaltern wie bei Helm!) +<code yaml> 
-  * **Deklarativ:** Da man jederzeit valide Kubernetes-YAML-Dateien ohne Platzhalter schreibt, hat man automatisch die volle IDE-Unterstützung inkl. Auto-Completion. +#overlays/test/service-ports.yaml 
-  * **Praktische Features:** Typische Use-Cases wie "alle Ressourcen sollen ein bestimmtes Label erhalten und in einen angegebenen Namespace deployed werden" sowie "Änderungen einer Config-Map sollen zu einem neuen Rollout des Deployments führen" werden gezielt adressiert. +kind: Service 
-  * **Flexibel und unabhängig:** Das CLI-Tool kustomize rendert letztlich nur YAML-Output nach Stdout, welcher anschließend je nach Geschmack mittels des Bash-Pipe-Operators weiterverarbeitet werden kann (z. B. kustomize build ~/someApp/overlays/production | kubectl apply -f -) +apiVersion: v1 
-  * **Integration:** Seit kubectl v.1.14 sind die kustomize-Funktionen für das Rendering in kubectl integriert, sodass keine weitere Binary benötigt wird. +metadata: 
-\\ +  #Name der zu patchenden Ressource 
-\\ +  nameenv-anzeige-frontend-https  
-=== OVERLAYS === +spec
-Statt Templates verwendet kustomize sog. Overlays. Die Idee: Man definiert eine Basis-Version der YAML-Dateien ("base") und dann Overlays für Modifikationen des Originals. Dabei handelt es sich um normale YAML-Dateien, welche nur die Attribute der "spec" enthalten, welche dann das Original überdecken/überschreiben sollen. In folgender Abbildung wird bspw. der Replica-Count eines Deployments von 1 auf 3 geändert. Neben den abweichenden Attributen muss das Overlay auch die notwendigen Informationen enthalten, um die Ressource zu identifizieren, die überlagert werden soll (hier also ein Deployment mit Namen "my-app"). Weitere Details zu diesem Mechanismus schauen wir uns im Folgenden an.+  ports#Die Porteinstellungen werden überschrieben 
 +  - namehttps 
 +    port: 443 
 +</code>
  
-{{ :it-wiki:kubernetes:overlay.png?nolink&600 |}} +Durch die Erstellung von Patch-Dateien können einzelne YAML-Attribute einer Konfiguration hinzugefügt oder überschrieben werden. Um anspruchsvollere Veränderungen an den Dateien durchzuführen, bietet Kustomize zusätzlich das Verändern von Ressourcen unter Verwendung des [[https://tools.ietf.org/html/rfc6902|JSON6902]] Standards an. Dieser beinhaltet sechs weitere Operatoren zur Veränderung von Ressourcen und ist damit umfangreicher als der Standard-Patch.
-\\+
  
-=== ORDNERSTRUKTUR === +^JSON6902 Operator ^Beschreibung^ 
-Der Code zum folgenden Beispiel ist vollständig auf GitHub verfügbar: https://github.com/viadee/kustomize-examples+| Add | fügt ein Attribut am angegebenen Pfad hinzu | 
 +| Remove | entfernt ein Attribut | 
 +| Replace | überschreibt das Attribut am angegebenen Pfad mit einem neuen Wert | 
 +| Move | verschiebt ein Attribut an einen anderen Pfad | 
 +| Copy | kopiert ein Attribut und fügt es an einem anderen Pfad wieder ein | 
 +| Test | überprüft, ob ein bestimmtes Attribut den angegebenen Wert besitzt |
  
-Die Verzeichnisstruktur kann grundsätzlich frei gewählt werden, etabliert hat sich jedoch:+ Im Folgenden wird der Service-Patch mit der JSON-Methode durchgeführt: 
 +<code yaml> 
 +#kustomization.yaml 
 +patchesJson6902: 
 +- target: 
 +    version: v1 
 +    kind: Service 
 +    name: env-anzeige-frontend-https 
 +  path: service-patch.yaml 
 +</code> 
 + 
 +<code yaml> 
 +#service-patch.yaml 
 +- op: replace 
 +  path: /spec/ports 
 +  value:  
 +  - name: https 
 +    port: 443 
 +</code> 
 + 
 +Die herkömmlichen Patches haben einen kleineren Funktionsumfang als der JSON-Patch, dadurch sind sie aber auch lesbarer. Außerdem reichen die Operationen hinzufügen und überschreiben für die meisten Anwendungsfälle völlig aus. Ein JSON-Patch sollte daher nur verwendet werden, wenn die zusätzlichen Operatoren (Attribut entfernen/kopieren/verschieben/testen) benötigt werden. 
 + 
 +Nachdem wir unsere Patches in Kustomize deklariert haben, können wir nun die einsetzbaren YAML-Konfigurationen erstellen. Kustomize ist fest in der aktuellen Version von kubectl implementiert. Mit dem Befehl **kubectl kustomize** kann die gepatchte YAML Konfigurationen ausgeben lassen. 
 + 
 +<code bash>> kubectl kustomize ./overlays/test/</code> 
 +<code yaml> 
 +apiVersionv1 
 +kind: Service 
 +metadata: 
 +  name: env-anzeige-frontend-https 
 +spec: 
 +  ports: 
 +  - name: https 
 +    nodePort: 30951 
 +    port: 443 
 +  selector: 
 +    app: env-anzeige-frontend 
 +  type: LoadBalancer 
 +</code> 
 + 
 +Alternativ können die Ressourcen mit dem Befehl **kubectl apply -k** ohne Zwischenschritt direkt in das Cluster geladen werden.
 <code bash> <code bash>
-~/my-app +> kubectl apply -./overlays/test/ 
-├── base +service/env-anzeige-frontend-https created
-│   ├── deployment.yaml +
-│   └── kustomization.yaml +
-└── overlays +
-    ├── prod +
-    │   ├── deployment_env.yaml +
-    │   ├── deployment_replicas.yaml  +
-    │   ├── deployment_volume.yaml  +
-    │   └── kustomization.yaml +
-    └── dev +
-    │   ├── kustomization.yaml +
-    │   └── ... +
-    └── ...+
 </code> </code>
-  * ./base: Als Verzeichnis für die originalen Kubernetes YAMl-Dateien. 
-  * ./overlays/<env>: Eigener Unterordner je Umgebung, in welchem die Overlays mit den jeweiligen Modifikationen gesammelt werden. 
  
-=== ./BASE === +\\ 
-Neben der originalen deployment.yaml-Datei (siehe oben), müssen wir noch eine kustomization.yaml-Datei anlegen. Letztlich enthält sie einfach nur eine Liste aller Ressourcen, die von kustomize berücksichtigt werden sollen.+===== Fazit ===== 
 +Kustomize vereinfacht den Konfigurationsprozess für verschiedene Umgebungen erheblichWeitere Vorteile von Kustomize sind die feste Implementierung in kubectl. Dadurch ist keine weitere Konfiguration oder Installation notwendig.
it-wiki/kubernetes/deployments_mit_kustomize.1710329731.txt.gz · Zuletzt geändert: von marko