Организовање примене у више к8с окружења користећи хелмфиле

Хелмфиле - омот за кормило, који вам омогућава да опишете многа издања кормила на једном месту, параметризујете њихове графиконе за неколико окружења, а такође поставите редослед њихове примене.

Можете прочитати о самом хелмфиле-у и примерима његове употребе у РЕАДМЕ и водич за најбоље праксе.

Упознаћемо се са неочигледним начинима за описивање издања у хелмфиле-у

Рецимо да имамо пакет хелм графикона (на пример, рецимо постгрес и неку позадинску апликацију) и неколико окружења (неколико кубернетес кластера, неколико именских простора или неколико од оба). Узимамо хелмфиле, читамо документацију и почињемо да описујемо наша окружења и издања:

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

Завршили смо са 2 окружења: девел, производња — сваки садржи своје вредности за карте издања кормила. Ми ћемо им распоредити овако:

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

Различите верзије карата кормила у различитим окружењима

Шта ако треба да уведемо различите верзије позадине у различита окружења? Како параметризовати верзију издања? Еколошке вредности доступне кроз {{ .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 }}
...

Различити скуп апликација у различитим окружењима

Одлично, али шта ако не треба production избацимо постгрес, јер знамо да не морамо да гурамо базу података у к8с и да за продају имамо диван одвојени постгрес кластер? Да бисмо решили овај проблем, имамо етикете

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

Ово је сјајно, али лично више волим да опишем које апликације треба применити у окружењу не користећи аргументе за покретање, већ у опису самих окружења. Шта да радим? Можете поставити описе издања у посебну фасциклу, креирати листу потребних издања у опису окружења и "покупити" само неопходна издања, игноришући остало

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

Белешка

Када користите bases: потребно је користити иамл сепаратор ---, тако да можете шаблонска издања (и друге делове, као што је хелмДефаултс) са вредностима из окружења

У овом случају, постгрес издање неће бити ни укључено у опис за производњу. Веома удобно!

Глобалне вредности за издања које се могу заобићи

Наравно, сјајно је што можете подесити вредности за управљачке карте за свако окружење, али шта ако имамо неколико описаних окружења, а желимо, на пример, да поставимо исто за све affinity, али не желимо да га подразумевано конфигуришемо у самим графиконима, који се чувају у репи.

У овом случају, за свако издање могли бисмо да наведемо 2 датотеке са вредностима: први са подразумеваним вредностима, који ће одредити вредности самог графикона, а други са вредностима за окружење, што ће заузврат заменити подразумеване.

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

Дефинисање глобалних вредности за карте свих издања на нивоу окружења

Рецимо да креирамо неколико улаза у неколико издања - могли бисмо ручно да дефинишемо за сваки графикон hosts:, али у нашем случају је домен исти, па зашто га не ставити у неку глобалну променљиву и једноставно заменити његову вредност у графиконе? Да бисте то урадили, оне датотеке са вредностима које желимо да параметризујемо мораће да имају екстензију .gotmpl, тако да тај хелмфиле зна да треба да се покрене кроз механизам шаблона.

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

Белешка

Очигледно је улазак у постгрес графикон нешто крајње сумњиво, па је овај чланак дат једноставно као сферни пример у вакууму и да се не би уводило неко ново издање у чланак само ради описа ингреса.

Замена тајни из вредности животне средине

По аналогији са горњим примером, можете заменити шифроване користећи кормиларске тајне значења. Уместо да креирамо сопствену датотеку тајни за свако издање, у којој можемо да дефинишемо шифроване вредности за графикон, можемо једноставно да дефинишемо у издању дефаулт.иамл.готмпл вредности које ће бити преузете из променљивих дефинисаних у ниво окружења. А вредности које не морамо да кријемо ни од кога могу се лако редефинисати у вредностима издања у одређеном окружењу.

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

Белешка

Узгред, getOrNil - посебна функција за го шаблоне у хелмфајлу, која, чак и ако .Values.secrets неће постојати, неће избацити грешку, али ће дозволити резултат помоћу функције default замени подразумевану вредност

Закључак

Описане ствари изгледају прилично очигледне, али информације о прикладном опису примене у неколико окружења које користе хелмфиле су веома оскудне, а ја волим ИаЦ (Инфраструцтуре-ас-Цоде) и желим да имам јасан опис стања примене.

У закључку, желео бих да додам да се варијабле за подразумевано окружење могу, заузврат, параметризовати са варијаблама окружења ОС-а одређеног покретача са којег ће се покренути имплементација, и на тај начин добити динамичка окружења

helmfile.yaml

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

Извор: ввв.хабр.цом

Додај коментар