Organiziranje implementacije u više k8s okruženja koristeći helmfile

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

Možete pročitati o samom helmfileu i primjerima njegove upotrebe readme и vodič za najbolje prakse.

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

Recimo da imamo paket helm grafikona (na primjer, recimo postgres i neku pozadinsku aplikaciju) i nekoliko okruženja (nekoliko kubernetes klastera, nekoliko imenskih prostora ili nekoliko od oboje). Uzimamo helmfile, čitamo dokumentaciju i počinjemo opisivati ​​naša okruženja 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 sa 2 okruženja: razviti, proizvodnja — svaki sadrži svoje vrijednosti za karte izdanja kormila. Mi ćemo im rasporediti ovako:

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

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

Što ako trebamo uvesti različite verzije pozadine u različitim okruženjima? Kako parametrirati verziju izdanja? Ekološke vrijednosti dostupne kroz {{ .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 skup aplikacija u različitim okruženjima

Odlično, ali šta ako ne trebamo production izbaciti postgres, jer znamo da ne trebamo gurati bazu podataka u k8s i za prodaju imamo divan odvojeni 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 lično više volim da opisujem koje aplikacije treba implementirati u okruženju ne koristeći argumente za pokretanje, već u opisu samih okruženja. sta da radim? Možete smjestiti opise izdanja u zasebnu mapu, kreirati listu potrebnih izdanja u opisu okruženja i "pokupiti" samo potrebna izdanja, ignorirajući ostalo

    .
    ├── 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

Napomena

Kada koristite bases: potrebno je koristiti yaml separator ---, tako da možete šablonizirati izdanja (i druge dijelove, kao što je helmDefaults) s vrijednostima iz okruženja

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

Zaobilazne globalne vrijednosti za izdanja

Naravno, sjajno je što možete postaviti vrijednosti za upravljačke karte za svako okruženje, ali šta ako imamo više opisanih okruženja, a želimo, na primjer, postaviti iste za sve affinity, ali ne želimo da ga konfiguriramo prema zadanim postavkama u samim grafikonima, koji su pohranjeni u repi.

U ovom slučaju, za svako izdanje možemo navesti 2 datoteke sa vrijednostima: prvi sa zadanim vrijednostima, koji će odrediti vrijednosti samog grafikona, a drugi sa vrijednostima za okruženje, što ć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 nivou 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 domen je isti, pa zašto ga ne staviti u neku globalnu varijablu i jednostavno zamijeniti njegovu vrijednost u grafikone? Da biste to učinili, datoteke sa vrijednostima koje želimo parametrizirati morat će imati ekstenziju .gotmpl, tako da taj helmfile zna da ga treba pokrenuti kroz mehanizam za predloške.

    .
    ├── 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 }}

Napomena

Očigledno je da je ingress u postgres grafikonu nešto krajnje sumnjivo, 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 vrijednostima okruženja

Po analogiji s gornjim primjerom, možete zamijeniti šifrirane koristeći kormilarske tajne značenja. Umjesto kreiranja 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 biti preuzete iz varijabli definiranih na nivo okruženja. A vrijednosti koje ne trebamo skrivati ​​ni od koga mogu se 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

Napomena

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

zaključak

Opisane stvari izgledaju prilično očigledne, ali informacije o prikladnom opisu implementacije u nekoliko okruženja koristeći helmfile su vrlo oskudne, a ja volim IaC (Infrastructure-as-Code) i želim imati jasan opis stanja implementacije.

U zaključku, želio bih da dodam da se varijable za zadano okruženje mogu, zauzvrat, parametrizovati sa varijablama okruženja OS-a određenog trkača iz kojeg će se pokrenuti implementacija i na taj način 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