Organiziranje implementacije u više k8s okruženja pomoću helmfilea

Helmfile - omot za kormilariti, koji vam omogućuje da opišete mnoga izdanja kormila na jednom mjestu, parametrirate njihove grafikone za nekoliko okruženja i također postavite redoslijed njihove implementacije.

O samom helmfileu i primjerima njegovog korištenja možete pročitati u obavijesna и vodič za najbolje prakse.

Upoznat ćemo se s neočitim načinima opisivanja izdanja u helmfileu

Recimo da imamo paket kormilarskih dijagrama (na primjer, recimo postgres i neku pozadinsku aplikaciju) i nekoliko okruženja (nekoliko kubernetes klastera, nekoliko prostora imena ili nekoliko oboje). Uzimamo helmfile, čitamo dokumentaciju i počinjemo opisivati ​​naše okruženje i izdanja:

    .
    ├── envs
    │   ├── devel
    │   │   └── values
    │   │       ├── backend.yaml
    │   │       └── postgres.yaml
    │   └── production
    │       └── values
    │           ├── backend.yaml
    │           └── postgres.yaml
    └── helmfile.yaml

helmfile.yaml

environments:
  devel:
  production:

releases:
  - name: postgres
    labels:
      app: postgres
    wait: true
    chart: stable/postgresql
    version: 8.4.0
    values:
      - envs/{{ .Environment.Name }}/values/postgres.yaml
  - name: backend
    labels:
      app: backend
    wait: true
    chart: private-helm-repo/backend
    version: 1.0.5
    needs:
      - postgres
    values:
      - envs/{{ .Environment.Name }}/values/backend.yaml

Završili smo s 2 okruženja: razviti, proizvodnja — svaki sadrži vlastite vrijednosti za tablice otpuštanja kormila. Rasporedit ćemo ih ovako:

helmfile -n <namespace> -e <env> apply

Različite verzije kormilarskih karata u različitim okruženjima

Što ako trebamo uvesti različite verzije pozadine u različita okruženja? Kako parametrirati verziju izdanja? Ekološke vrijednosti dostupne putem {{ .Values }}

helmfile.yaml

environments:
  devel:
+   values:
+   - charts:
+       versions:
+         backend: 1.1.0
  production:
+   values:
+   - charts:
+       versions:
+         backend: 1.0.5
...
  - name: backend
    labels:
      app: backend
    wait: true
    chart: private-helm-repo/backend
-   version: 1.0.5
+   version: {{ .Values.charts.versions.backend }}
...

Različiti skupovi aplikacija u različitim okruženjima

Super, ali što ako nam ne treba production uvesti postgres, jer znamo da ne trebamo gurati bazu podataka u k8s, a za prodaju imamo prekrasan odvojen postgres klaster? Za rješavanje ovog problema imamo oznake

helmfile -n <namespace> -e devel apply
helmfile -n <namespace> -e production -l app=backend apply

Ovo je sjajno, ali osobno radije opisujem koje aplikacije implementirati u okruženju ne koristeći argumente pokretanja, već u opisu samih okruženja. Što uraditi? Možete smjestiti opise izdanja u zasebnu mapu, izraditi popis potrebnih izdanja u opisu okruženja i “pokupiti” samo potrebna izdanja, zanemarujući ostala

    .
    ├── envs
    │   ├── devel
    │   │   └── values
    │   │       ├── backend.yaml
    │   │       └── postgres.yaml
    │   └── production
    │       └── values
    │           ├── backend.yaml
    │           └── postgres.yaml
+   ├── releases
+   │   ├── backend.yaml
+   │   └── postgres.yaml
    └── helmfile.yaml

helmfile.yaml


  environments:
    devel:
      values:
      - charts:
          versions:
            backend: 1.1.0
      - apps:
        - postgres
        - backend

    production:
      values:
      - charts:
          versions:
            backend: 1.0.5
      - apps:
        - backend

- releases:
-    - name: postgres
-      labels:
-        app: postgres
-      wait: true
-      chart: stable/postgresql
-      version: 8.4.0
-      values:
-        - envs/{{ .Environment.Name }}/values/postgres.yaml
-    - name: backend
-      labels:
-        app: backend
-      wait: true
-      chart: private-helm-repo/backend
-     version: {{ .Values.charts.versions.backend }}
-     needs:
-       - postgres
-     values:
-       - envs/{{ .Environment.Name }}/values/backend.yaml
+ ---
+ bases:
+ {{- range .Values.apps }}
+   - releases/{{ . }}.yaml
+ {{- end }}

releases/postgres.yaml

releases:
  - name: postgres
    labels:
      app: postgres
    wait: true
    chart: stable/postgresql
    version: 8.4.0
    values:
      - envs/{{ .Environment.Name }}/values/postgres.yaml

releases/backend.yaml

releases:
  - name: backend
    labels:
      app: backend
    wait: true
    chart: private-helm-repo/backend
    version: {{ .Values.charts.versions.backend }}
    needs:
      - postgres
    values:
      - envs/{{ .Environment.Name }}/values/backend.yaml

Bilješka

Kada koristite bases: potrebno je koristiti yaml separator ---, tako da možete izraditi predložak izdanja (i drugih dijelova, kao što je helmDefaults) s vrijednostima iz okruženja

U ovom slučaju, postgres izdanje neće biti ni uključeno u opis za proizvodnju. Vrlo udobno!

Globalne vrijednosti koje se mogu nadjačati za izdanja

Naravno, odlično je što možete postaviti vrijednosti za karte kormila za svako okruženje, ali što ako imamo nekoliko opisanih okruženja, a želimo, na primjer, postaviti isto za sve affinity, ali ne želimo ga konfigurirati prema zadanim postavkama u samim grafikonima, koji su pohranjeni u repi.

U ovom slučaju, za svako izdanje mogli bismo navesti 2 datoteke s vrijednostima: prvu sa zadanim vrijednostima, koje će odrediti vrijednosti samog grafikona, a drugu s vrijednostima za okruženje, koje će zauzvrat nadjačati zadane.

    .
    ├── envs
+   │   ├── default
+   │   │   └── values
+   │   │       ├── backend.yaml
+   │   │       └── postgres.yaml
    │   ├── devel
    │   │   └── values
    │   │       ├── backend.yaml
    │   │       └── postgres.yaml
    │   └── production
    │       └── values
    │           ├── backend.yaml
    │           └── postgres.yaml
    ├── releases
    │   ├── backend.yaml
    │   └── postgres.yaml
    └── helmfile.yaml

releases/backend.yaml

releases:
  - name: backend
    labels:
      app: backend
    wait: true
    chart: private-helm-repo/backend
    version: {{ .Values.charts.versions.backend }}
    needs:
      - postgres
    values:
+     - envs/default/values/backend.yaml
      - envs/{{ .Environment.Name }}/values/backend.yaml

envs/default/values/backend.yaml

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 1
      podAffinityTerm:
        labelSelector:
          matchExpressions:
          - key: app.kubernetes.io/name
            operator: In
            values:
            - backend
        topologyKey: "kubernetes.io/hostname"

Definiranje globalnih vrijednosti za upravljačke karte svih izdanja na razini okruženja

Recimo da kreiramo nekoliko ulaza u nekoliko izdanja - mogli bismo ručno definirati za svaki grafikon hosts:, ali u našem slučaju domena je ista, pa zašto je ne staviti u neku globalnu varijablu i jednostavno zamijeniti njezinu vrijednost u grafikone? Da bismo to učinili, te datoteke s vrijednostima koje želimo parametrizirati morat će imati ekstenziju .gotmpl, tako da helmfile zna da se mora pokrenuti kroz predložak.

    .
    ├── envs
    │   ├── default
    │   │   └── values
-   │   │       ├── backend.yaml
-   │   │       ├── postgres.yaml
+   │   │       ├── backend.yaml.gotmpl
+   │   │       └── postgres.yaml.gotmpl
    │   ├── devel
    │   │   └── values
    │   │       ├── backend.yaml
    │   │       └── postgres.yaml
    │   └── production
    │       └── values
    │           ├── backend.yaml
    │           └── postgres.yaml
    ├── releases
    │   ├── backend.yaml
    │   └── postgres.yaml
    └── helmfile.yaml

helmfile.yaml

  environments:
    devel:
      values:
      - charts:
          versions:
            backend: 1.1.0
      - apps:
        - postgres
        - backend
+     - global:
+         ingressDomain: k8s.devel.domain

    production:
      values:
      - charts:
          versions:
            backend: 1.0.5
      - apps:
        - backend
+     - global:
+         ingressDomain: production.domain
  ---
  bases:
  {{- range .Values.apps }}
    - releases/{{ . }}.yaml
  {{- end }}

envs/default/values/backend.yaml.gotmpl

ingress:
  enabled: true
  paths:
    - /api
  hosts:
    - {{ .Values.global.ingressDomain }}

envs/default/values/postgres.yaml.gotmpl

ingress:
  enabled: true
  paths:
    - /
  hosts:
    - postgres.{{ .Values.global.ingressDomain }}

Bilješka

Očito je ingress u postgres grafikonu nešto krajnje dvojbeno, pa je ovaj članak dat jednostavno kao sferni primjer u vakuumu i kako se ne bi uvodilo neko novo izdanje u članak samo radi opisa ingressa

Zamjena tajni iz vrijednosti okoline

Po analogiji s gornjim primjerom, šifrirane možete zamijeniti pomoću tajne kormila značenja. Umjesto stvaranja vlastite tajne datoteke za svako izdanje, u kojoj možemo definirati šifrirane vrijednosti za grafikon, možemo jednostavno definirati u izdanju default.yaml.gotmpl vrijednosti koje će se uzeti iz varijabli definiranih na razina okoline. A vrijednosti koje ne trebamo skrivati ​​ni od koga možemo lako redefinirati u vrijednostima izdanja u određenom okruženju.

    .
    ├── envs
    │   ├── default
    │   │   └── values
    │   │       ├── backend.yaml
    │   │       └── postgres.yaml
    │   ├── devel
    │   │   ├── values
    │   │   │   ├── backend.yaml
    │   │   │   └── postgres.yaml
+   │   │   └── secrets.yaml
    │   └── production
    │       ├── values
    │       │   ├── backend.yaml
    │       │   └── postgres.yaml
+   │       └── secrets.yaml
    ├── releases
    │   ├── backend.yaml
    │   └── postgres.yaml
    └── helmfile.yaml

helmfile.yaml

  environments:
    devel:
      values:
      - charts:
          versions:
            backend: 1.1.0
      - apps:
        - postgres
        - backend
      - global:
          ingressDomain: k8s.devel.domain
+     secrets:
+       - envs/devel/secrets.yaml

    production:
      values:
      - charts:
          versions:
            backend: 1.0.5
      - apps:
        - backend
      - global:
          ingressDomain: production.domain
+     secrets:
+       - envs/production/secrets.yaml
  ---
  bases:
  {{- range .Values.apps }}
    - releases/{{ . }}.yaml
  {{- end }}

envs/devel/secrets.yaml

secrets:
    elastic:
        password: ENC[AES256_GCM,data:hjCB,iv:Z1P6/6xBJgJoKLJ0UUVfqZ80o4L84jvZfM+uH9gBelc=,tag:dGqQlCZnLdRAGoJSj63rBQ==,type:int]
...

envs/production/secrets.yaml

secrets:
    elastic:
        password: ENC[AES256_GCM,data:ZB/VpTFk8f0=,iv:EA//oT1Cb5wNFigTDOz3nA80qD9UwTjK5cpUwLnEXjs=,tag:hMdIUaqLRA8zuFBd82bz6A==,type:str]
...

envs/default/values/backend.yaml.gotmpl

elasticsearch:
  host: elasticsearch
  port: 9200
  password: {{ .Values | getOrNil "secrets.elastic.password" | default "password" }}

envs/devel/values/backend.yaml

elasticsearch:
  host: elastic-0.devel.domain

envs/production/values/backend.yaml

elasticsearch:
  host: elastic-0.production.domain

Bilješka

Usput, getOrNil - posebna funkcija za go predloške u helmfileu, koja, čak i ako .Values.secrets neće postojati, neće izbaciti pogrešku, ali će dopustiti rezultat pomoću funkcije default zamjenska zadana vrijednost

Zaključak

Opisano se čini sasvim očiglednim, ali informacije o prikladnom opisu implementacije u nekoliko okruženja pomoću helmfilea su vrlo rijetke, a ja volim IaC (Infrastructure-as-Code) i želim imati jasan opis stanja implementacije.

Zaključno bih želio dodati da se varijable za zadano okruženje mogu pak parametrizirati s varijablama okruženja OS-a određenog runnera iz kojeg će se pokrenuti implementacija i tako dobiti dinamička okruženja

helmfile.yaml

environments:
  default:
    values:
    - global:
        clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
        ingressDomain: {{ env "INGRESS_DOMAIN" }}

Izvor: www.habr.com

Dodajte komentar