helmfile を使用した複数の k8s 環境へのデプロイメントの整理

ヘルムファイル - ラッパー これにより、多くの Helm リリースを XNUMX か所で記述し、複数の環境のチャートをパラメータ化し、デプロイの順序を設定することもできます。

Helmfile 自体とその使用例については、次の記事で読むことができます。 README и ベストプラクティスガイド.

Helmfile でリリースを記述するための非自明な方法について説明します。

ヘルム チャートのパック (たとえば、postgres といくつかのバックエンド アプリケーション) といくつかの環境 (いくつかの Kubernetes クラスター、いくつかの名前空間、またはその両方) があるとします。 helmfile を取得し、ドキュメントを読み、環境とリリースについて説明し始めます。

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

異なる環境における異なるバージョンの Helm チャート

異なるバージョンのバックエンドを異なる環境にロールアウトする必要がある場合はどうすればよいでしょうか? リリースバージョンをパラメータ化するにはどうすればよいですか? を通じて得られる環境価値 {{ .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 postgres をロールアウトします。データベースを k8s にプッシュする必要がなく、販売用の素晴らしい個別の postgres クラスターがあるからです。 この問題を解決するためにラベルを用意しました

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: yaml区切り文字を使用する必要があります ---、環境からの値を使用してリリース (および helmDefaults などの他の部分) をテンプレート化できるようにします。

この場合、postgres リリースは運用環境の説明にも含まれません。 とっても快適!

リリースのための上書き可能なグローバル値

もちろん、環境ごとにヘルム チャートの値を設定できるのは素晴らしいことですが、複数の環境が記述されており、たとえばすべての環境に同じ値を設定したい場合はどうなるでしょうか。 affinityですが、カブに保存されているチャート自体にデフォルトで設定することは望ましくありません。

この場合、リリースごとに値を含む 2 つのファイルを指定できます。最初のファイルにはチャート自体の値を決定するデフォルト値が含まれ、XNUMX 番目のファイルには環境の値が含まれ、これにより環境の値が上書きされます。デフォルトのもの。

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

すべてのリリースのヘルム チャートのグローバル値を環境レベルで定義する

複数のリリースで複数の Ingress を作成するとします。チャートごとに手動で定義できます。 hosts:, しかし、この場合はドメインが同じなので、それをグローバル変数に入れて、その値をチャートに単純に代入してみてはどうでしょうか? これを行うには、パラメータ化したい値を持つファイルには拡張子が必要です。 .gotmplこれにより、helmfile はテンプレート エンジンを通じて実行する必要があることがわかります。

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

備考

明らかに、postgres チャートの Ingress は非常に疑わしいものであるため、この記事は、単に Ingress を説明するためだけに記事に新しいリリースを導入しないように、真空の球状の例として提供されています。

環境値からシークレットを置き換える

上記の例から類推すると、暗号化されたものを次のように置き換えることができます。 舵の秘密 意味。 チャートの暗号化された値を定義できる独自のシークレット ファイルをリリースごとに作成する代わりに、単にリリースで定義された変数から取得される値をdefault.yaml.gotmplで定義できます。環境レベル。 また、誰からも隠す必要のない値は、特定の環境でのリリース値で簡単に再定義できます。

    .
    ├── 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 - helmfile 内の go テンプレート用の特別な関数。 .Values.secrets 存在せず、エラーはスローされませんが、関数を使用して結果を取得できます default デフォルト値を置き換える

まとめ

説明されている内容は非常に明白に思えますが、helmfile を使用した複数の環境へのデプロイメントの便利な説明に関する情報は非常に不足しています。私は IaC (Infrastructure-as-Code) が大好きなので、デプロイメントの状態を明確に説明したいと考えています。

結論として、デフォルト環境の変数は、デプロイメントが開始される特定のランナーの OS の環境変数でパラメータ化できるため、動的な環境を取得できることを付け加えたいと思います。

helmfile.yaml

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

出所: habr.com

コメントを追加します