kakakakakku blog

Weekly Tech Blog : Keep on Learning 👍

Helmfile の「テンプレート機能」を試す

前回の記事では Helmfile に入門した!Helm Chart を宣言的に管理することができて便利だった💡

引き続き Helmfile を試していて,GitHub に載っている「The Helmfile Best Practices Guide」を読んでいたら「テンプレート機能」が紹介されていた.Helmfile で多くの Helm Chart を管理していくと,徐々に helmfile.yaml が長くなる可能性がある.そこで「テンプレート機能」を使って共通化をすることで可読性を高くシンプルに記述できるようになる.さっそく試していく!

github.com

「テンプレート機能」を使わずに Helmfile を記述する

まずは「テンプレート機能」を使わずに Helmfile を記述する.今回はサンプルとして bitnami/metrics-server と bitnami/nginx-ingress-controller を Helm Chart でセットアップする.

artifacthub.io

artifacthub.io

ディレクトリ構成は以下とする.helmfile.yaml と環境ごとに values.yaml を用意する.

$ tree .
.
├── helmfile.yaml
├── metrics-server
│   ├── values-development.yaml
│   ├── values-production.yaml
│   └── values-staging.yaml
└── nginx-ingress-controller
    ├── values-development.yaml
    ├── values-production.yaml
    └── values-staging.yaml

2 directories, 7 files

helmfile.yaml を以下のように記述する.複雑な記述はなく bitnami/metrics-server と bitnami/nginx-ingress-controller を含めている.

environments:
  development:
  staging:
  production:

releases:
  - name: metrics-server
    chart: bitnami/metrics-server
    namespace: kube-system
    version: 5.10.0
    values:
      - metrics-server/values-{{`{{ .Environment.Name }}`}}.yaml
  - name: nginx-ingress-controller
    chart: bitnami/nginx-ingress-controller
    namespace: kube-system
    version: 7.6.21
    values:
      - nginx-ingress-controller/values-{{`{{ .Environment.Name }}`}}.yaml

実際に helmfile apply コマンドを実行するとうまくセットアップできた.

$ helmfile -e staging apply

(中略)

UPDATED RELEASES:
NAME                       CHART                              VERSION
metrics-server             bitnami/metrics-server              5.10.0
nginx-ingress-controller   bitnami/nginx-ingress-controller    7.6.21

$ helmfile delete

「テンプレート機能」を使って Helmfile を書く

今度は「テンプレート機能」を使って Helmfile を記述する.以下のように templates を使って Helm Chart の宣言をテンプレート化できる.今回は chart と namespace と values を含めつつ .Release.Name と .Environment.Name をパラメータとして埋め込むようにしている.そして YAML 自体に実装されているマージ機能 << を使って releases を記述している.

environments:
  development:
  staging:
  production:

templates:
  default: &default
    chart: bitnami/{{`{{ .Release.Name }}`}}
    namespace: kube-system
    values:
      - "{{`{{ .Release.Name }}`}}/values-{{`{{ .Environment.Name }}`}}.yaml"

releases:
- name: metrics-server
  version: 5.10.0
  <<: *default
- name: nginx-ingress-controller
  version: 7.6.21
  <<: *default

結果は同じく helmfile apply コマンドを実行してセットアップすることができた.

$ helmfile -e staging apply

(中略)

UPDATED RELEASES:
NAME                       CHART                              VERSION
metrics-server             bitnami/metrics-server              5.10.0
nginx-ingress-controller   bitnami/nginx-ingress-controller    7.6.21

$ helmfile delete

まとめ

Helmfile で「テンプレート機能」を使うと helmfile.yaml を 共通化して可読性を高くシンプルに記述できるようになる.今回のサンプルでは「18行」→「19行」とむしろ行数が増えてしまったけど,Helm Chart を増やせばメリットが出てくるし,何しろ設定ミスを減らすことにも繋がるため,行数だけでは判断できないと思う.引き続き Helmfile を試していくぞー!

関連記事

kakakakakku.hatenablog.com

Helmfile で Helm Chart を宣言的に管理する

Helm を使うと Kubernetes クラスタ上に簡単にアプリケーションなどをインストールできる.そして Helm Chart は Artifact Hub で確認できる.また values.yaml と組み合わせれば Helm Chart のデフォルト設定を変更することもできる.しかし helm コマンドを使って実行する場合,以下のようになり「宣言的に」管理できないという課題も残る.今回は Jenkins をサンプルとして使う.

$ helm install my-jenkins jenkins/jenkins --version 3.3.23 -f values.yaml

artifacthub.io

Helmfile とは ⎈

そこで Helmfile を紹介する💡Helmfile を使うと helm コマンドを実行するときの設定を YAML で「宣言的に」管理できるようになる.現在もアクティブ開発されていて利用実績も多そう.今回は Helmfile を試していく!

github.com

前提として helmfile コマンドを準備しておく.今回は Homebrew を使う.また helmfile diff コマンドを使うこともあるため helm-diff も追加でインストールしておく.それにしても v0.140 ってスゴイ👀

$ brew install helmfile
$ helm plugin install https://github.com/databus23/helm-diff

$ helmfile version
helmfile version v0.140.0

Helmfile に入門する ⎈

Helmfile では,以下のように helmfile.yaml を作るところから開始する.helm コマンド的には helm install my-jenkins jenkins/jenkins --version 3.3.23 -f values.yaml と同じ意味になる.サンプルとして values.yaml も載せておく.今回は serviceType と servicePort を変更する.

📁 helmfile.yaml

releases:
  - name: my-jenkins
    chart: jenkins/jenkins
    version: 3.3.23
    values:
      - values.yaml

📁 values.yaml

controller:
  serviceType: NodePort
  servicePort: 8888

さっそく helmfile apply コマンドを使って Helm Chart をインストールする.

$ helmfile apply

(中略)

UPDATED RELEASES:
NAME         CHART             VERSION
my-jenkins   jenkins/jenkins    3.3.23

すぐに Jenkins にアクセスできるようになる.画面右下に書いてある通り Jenkins 2.289.1 になっていた.

f:id:kakku22:20210908202659p:plain

Helm Chart を更新する ⎈

次に Helm Chart を更新する.以下のように helmfile.yaml で version: 3.3.23 → version: 3.4.1 にする.

releases:
  - name: my-jenkins
    chart: jenkins/jenkins
    version: 3.4.1
    values:
      - values.yaml

実行をする前に helmfile diff コマンドを使って差分を確認することもできる.今回はバージョン間の差が少なかった.

$ helmfile diff
Comparing release=my-jenkins, chart=jenkins/jenkins

(中略)

default, my-jenkins, StatefulSet (apps) has changed:
  # Source: jenkins/templates/jenkins-controller-statefulset.yaml
  apiVersion: apps/v1
  kind: StatefulSet
  metadata:
    name: my-jenkins
    namespace: default
    labels:
      "app.kubernetes.io/name": 'jenkins'
-     "helm.sh/chart": "jenkins-3.3.23"
+     "helm.sh/chart": "jenkins-3.4.1"
      "app.kubernetes.io/managed-by": "Helm"
      "app.kubernetes.io/instance": "my-jenkins"
      "app.kubernetes.io/component": "jenkins-controller"

(中略)

もう1度 helmfile apply コマンドを実行するとすぐに更新される!簡単!

$ helmfile apply

(中略)

UPDATED RELEASES:
NAME         CHART             VERSION
my-jenkins   jenkins/jenkins     3.4.1

1度削除をしておく.

$ helmfile delete

DELETED RELEASES:
NAME
my-jenkins

Helmfile で複数環境を作る ⎈

もう少し Helmfile の良さを試していく.Helmfile では production や staging など「複数環境」を作ることができる.helmfile.yaml に以下のように environments を設定して {{ .Environment.Name }} で参照することができる.

📁 helmfile.yaml

environments:
  development:
  staging:
  production:

releases:
  - name: my-jenkins
    chart: jenkins/jenkins
    version: 3.4.1
    values:
      - values-{{ .Environment.Name }}.yaml

そして values-production.yaml や values-staging.yaml など,環境ごとに values.yaml を用意しておく.今回試す values-staging.yaml では servicePort を 8889 に変えた.

$ tree .
.
├── helmfile.yaml
├── values-development.yaml
├── values-production.yaml
└── values-staging.yaml

0 directories, 4 files

📁 values-staging.yaml

controller:
  servicePort: 8889

さっそく -e オプションを使って staging 環境を作る.指定した通り servicePort も 8889 になっている.便利!

$ helmfile -e staging apply

(中略)

UPDATED RELEASES:
NAME         CHART             VERSION
my-jenkins   jenkins/jenkins     3.4.1

$ kubectl describe services my-jenkins | egrep '^Port:'
Port:              http  8889/TCP

まとめ ⎈

今回は Helmfile に入門した.Helmfile にはまだ他にも機能があるため引き続き試していくぞー!

github.com

Deployment の maxUnavailable と maxSurge : ロールアウト中の割合を設定する

Kubernetes で Deployment を使うと Pod を安全にデプロイ(ロールアウト)できる.そのときに更新する Pod の割合として Max Unavailable と Max Surge という設定値があり,デフォルト値は以下のようにドキュメントに書いてある.今回は動作確認をしながら図解もしていく.

  • Max Unavailable(停止状態になる最大 Pod 数)
    • .spec.strategy.rollingUpdate.maxUnavailable
    • デフォルト値 : 25%(小数点切り捨て)
    • 値には 絶対値 or % を設定できる
  • Max Surge(宣言した Pod 数を超えて作れる Pod 数)
    • .spec.strategy.rollingUpdate.maxSurge
    • デフォルト値 : 25%(小数点切り上げ)
    • 値には 絶対値 or % を設定できる

kubernetes.io

デフォルト値を確認する

以下の Deployment (replicas: 10) を適用する. Max Unavailable と Max Surge のデフォルト値である 25% を考慮すると 7.5 ~ 12.5 となるため,デプロイ時には「最低 8 Running Pod」と「最高 13 Pod」になると期待できる.さっそく以下の Deployment で images を nginx:1.19-alpine から nginx:1.20-alpine に更新してデプロイをする.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-rolling-update
  labels:
    app: sandbox-rolling-update
spec:
  replicas: 10
  selector:
    matchLabels:
      app: sandbox-rolling-update
  template:
    metadata:
      labels:
        app: sandbox-rolling-update
    spec:
      containers:
      - name: nginx
        image: nginx:1.19-alpine
        ports:
          - containerPort: 80

更新中の Pod の状態を確認すると以下のようになる.「10 Running Pod」から「8 Running Pod と 5 ContainerCreating Pod」になった.期待通りの挙動となる.

$ kubectl get pods -l app=sandbox-rolling-update --sort-by=.status.phase
NAME                                      READY   STATUS    RESTARTS   AGE
sandbox-rolling-update-59c54649f5-4p2ds   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-6gfps   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-97cvh   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-b4sl2   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-crnnc   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-h5l8q   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-jkcjk   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-jnwwr   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-t746f   1/1     Running   0          20s
sandbox-rolling-update-59c54649f5-vdpkq   1/1     Running   0          20s

$ kubectl get pods -l app=sandbox-rolling-update --sort-by=.status.phase
NAME                                      READY   STATUS              RESTARTS   AGE
sandbox-rolling-update-5d4d5d6884-wkrb8   0/1     ContainerCreating   0          0s
sandbox-rolling-update-5d4d5d6884-sg8zc   0/1     ContainerCreating   0          0s
sandbox-rolling-update-5d4d5d6884-fkmdm   0/1     ContainerCreating   0          0s
sandbox-rolling-update-5d4d5d6884-bv9s6   0/1     ContainerCreating   0          0s
sandbox-rolling-update-5d4d5d6884-bdbsx   0/1     ContainerCreating   0          0s
sandbox-rolling-update-59c54649f5-t746f   1/1     Running             0          60s
sandbox-rolling-update-59c54649f5-jnwwr   1/1     Running             0          60s
sandbox-rolling-update-59c54649f5-vdpkq   1/1     Running             0          60s
sandbox-rolling-update-59c54649f5-h5l8q   1/1     Running             0          60s
sandbox-rolling-update-59c54649f5-crnnc   1/1     Running             0          60s
sandbox-rolling-update-59c54649f5-b4sl2   1/1     Running             0          60s
sandbox-rolling-update-59c54649f5-97cvh   1/1     Running             0          60s
sandbox-rolling-update-59c54649f5-6gfps   1/1     Running             0          60s

流れを簡単に図解してみた🎨

f:id:kakku22:20210901222813p:plain

maxUnavailable と maxSurge を指定する

次に .spec.strategy.rollingUpdate.maxUnavailable: 0% と .spec.strategy.rollingUpdate.maxSurge: 100% を追加する.そして nginx:1.20-alpine を nginx:1.21-alpine に更新してデプロイをする.ようするに「最低 10 Running Pod」を維持しつつ「最高 20 Pod」まで許容する.リソースは2倍必要になるけどパフォーマンスを落とすことなくデプロイできる.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-rolling-update
  labels:
    app: sandbox-rolling-update
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0%
      maxSurge: 100%
  selector:
    matchLabels:
      app: sandbox-rolling-update
  template:
    metadata:
      labels:
        app: sandbox-rolling-update
    spec:
      containers:
      - name: nginx
        image: nginx:1.21-alpine
        ports:
          - containerPort: 80
      terminationGracePeriodSeconds: 0

更新中の Pod の状態を確認すると以下のようになる.「10 Running Pod」から「10 Running Pod と 10 ContainerCreating Pod」になった.期待通りの挙動となる.

$ kubectl get pods -l app=sandbox-rolling-update --sort-by=.status.phase
NAME                                      READY   STATUS    RESTARTS   AGE
sandbox-rolling-update-5d4d5d6884-56q4g   1/1     Running   0          8m31s
sandbox-rolling-update-5d4d5d6884-8d5gk   1/1     Running   0          8m30s
sandbox-rolling-update-5d4d5d6884-8sf46   1/1     Running   0          8m31s
sandbox-rolling-update-5d4d5d6884-bdbsx   1/1     Running   0          8m33s
sandbox-rolling-update-5d4d5d6884-bv9s6   1/1     Running   0          8m33s
sandbox-rolling-update-5d4d5d6884-fkmdm   1/1     Running   0          8m33s
sandbox-rolling-update-5d4d5d6884-hlzfp   1/1     Running   0          8m31s
sandbox-rolling-update-5d4d5d6884-sg8zc   1/1     Running   0          8m33s
sandbox-rolling-update-5d4d5d6884-wkrb8   1/1     Running   0          8m33s
sandbox-rolling-update-5d4d5d6884-z68nq   1/1     Running   0          8m31s

$ kubectl get pods -l app=sandbox-rolling-update --sort-by=.status.phase
NAME                                      READY   STATUS              RESTARTS   AGE
sandbox-rolling-update-59c54649f5-4dzbg   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-5twh4   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-8gqkt   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-btcsd   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-cf8mc   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-dmmrq   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-l7nmj   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-pbwl5   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-s8dwc   0/1     ContainerCreating   0          5s
sandbox-rolling-update-59c54649f5-x6hfz   0/1     ContainerCreating   0          5s
sandbox-rolling-update-5d4d5d6884-56q4g   1/1     Running             0          8m46s
sandbox-rolling-update-5d4d5d6884-8d5gk   1/1     Running             0          8m45s
sandbox-rolling-update-5d4d5d6884-8sf46   1/1     Running             0          8m46s
sandbox-rolling-update-5d4d5d6884-bdbsx   1/1     Running             0          8m48s
sandbox-rolling-update-5d4d5d6884-bv9s6   1/1     Running             0          8m48s
sandbox-rolling-update-5d4d5d6884-fkmdm   1/1     Running             0          8m48s
sandbox-rolling-update-5d4d5d6884-hlzfp   1/1     Running             0          8m46s
sandbox-rolling-update-5d4d5d6884-sg8zc   1/1     Running             0          8m48s
sandbox-rolling-update-5d4d5d6884-wkrb8   1/1     Running             0          8m48s
sandbox-rolling-update-5d4d5d6884-z68nq   1/1     Running             0          8m46s

流れを簡単に図解してみた🎨

f:id:kakku22:20210901222833p:plain

まとめ

今回は Deployment に設定できる Max Unavailable と Max Surge の挙動を試した.ドキュメントを読むだけでも把握できるけど,やっぱり実際に試すと理解が深まる.今後も手を動かすことを意識していくぞー💪

Argo CD で kustomize プロジェクトを GitOps 化する

Argo CD は kustomize をサポートしているため,簡単に kustomize プロジェクトを GitOps 化できる.さっそく試していく!

argo-cd.readthedocs.io

検証環境

前回書いた記事で使った kustomize プロジェクトを使う. Namespace + Service + Deployment (nginx) という構成で,replicas と images を kustomize で変更している.詳しくは以下に置いてある.

github.com

Argo CD Application

今回は Argo CD v2.0.5+4c94d88 を使う.まずは GitHub リポジトリと紐付けるために Argo CD Application を作る.Argo CD の Web UI を使っても作れるし,argocd app create コマンドを使っても作れるけど,今回はマニフェストで宣言をする.以下のように application.yaml を作った.ポイントは大きく2点ある.

  • spec.source.path : overlays/dev など kustomize で作る環境ディレクトリを指定する
  • spec.syncPolicy : automated.selfHeal: true を指定して「自動同期」と「自己回復 (Self-Healing)」を有効化する
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sandbox-kustomize-argocd
  namespace: argocd
spec:
  destination:
    namespace: kakakakakku-dev
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: https://github.com/kakakakakku/sandbox-kustomize.git
    path: overlays/dev
    targetRevision: HEAD
  syncPolicy:
    automated:
      selfHeal: true

リソース確認

次に application.yaml を適用すると,Argo CD によって自動的にリソースが作られる.なお,Argo CD には Tool Detection という機能があり自動的にプロジェクトを判別する.具体的には kustomization.yaml / kustomization.yml / Kustomization ファイルを発見した場合に kustomize プロジェクトと判別する.

argoproj.github.io

実際に Argo CD の実装をザッと読むと,ドキュメントと同様に Tool Detection や kustomize build コマンドを実行している感じだった.

github.com

適用後に kubectl コマンドを実行すると Namespace と Service と Deployment が作られている.

$ kubectl get namespaces kakakakakku-dev
NAME              STATUS   AGE
kakakakakku-dev   Active   3m30s

$ kubectl get services -n kakakakakku-dev kakakakakku-dev-nginx
NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kakakakakku-dev-nginx   ClusterIP   10.98.69.104   <none>        80/TCP    3m40s

$ kubectl get deployments -n kakakakakku-dev kakakakakku-dev-nginx
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
kakakakakku-dev-nginx   5/5     5            5           4m20s

Web UI でもリソースを確認できる.

f:id:kakku22:20210819170100p:plain

f:id:kakku22:20210819170414p:plain

レプリカ数を強制的に変更してみる

意図しない操作として kustomization.yaml に設定しているレプリカ数を 7 に変更してみる.一瞬 7 Pods になったけど,直後に Argo CD によって削除されていた.「自己回復 (Self-Healing)」も含めて GitOps を実現できている.Argo CD と kustomize の連携は簡単だった!

$ kustomize build overlays/dev | kubectl apply -f -

$ kubectl get pods -n kakakakakku-dev
NAME                                     READY   STATUS    RESTARTS   AGE
kakakakakku-dev-nginx-7c7bbd5d59-2tgww   2/2     Running   0          5s
kakakakakku-dev-nginx-7c7bbd5d59-8rfsj   2/2     Running   0          8m30s
kakakakakku-dev-nginx-7c7bbd5d59-cq4vt   2/2     Running   0          5s
kakakakakku-dev-nginx-7c7bbd5d59-dptvl   2/2     Running   0          8m30s
kakakakakku-dev-nginx-7c7bbd5d59-mb5xs   2/2     Running   0          8m30s
kakakakakku-dev-nginx-7c7bbd5d59-p6w9n   2/2     Running   0          8m30s
kakakakakku-dev-nginx-7c7bbd5d59-wqpm8   2/2     Running   0          8m30s

$ kubectl get pods -n kakakakakku-dev
NAME                                     READY   STATUS    RESTARTS   AGE
kakakakakku-dev-nginx-7c7bbd5d59-8rfsj   2/2     Running   0          8m50s
kakakakakku-dev-nginx-7c7bbd5d59-dptvl   2/2     Running   0          8m50s
kakakakakku-dev-nginx-7c7bbd5d59-mb5xs   2/2     Running   0          8m50s
kakakakakku-dev-nginx-7c7bbd5d59-p6w9n   2/2     Running   0          8m50s
kakakakakku-dev-nginx-7c7bbd5d59-wqpm8   2/2     Running   0          8m50s

Argo CD 側で kustomize の設定を変更する

ドキュメントを読んでいたら Argo CD は以下の kustomize 設定をサポートしていると書いてあったけど,ドキュメントを読むだけでは正直よくわからなかった.試した結果,正しく表現するなら Argo CD Application の設定で一部の kustomize 設定を変更できるという意味だった.

  • namePrefix
  • nameSuffix
  • images
  • commonLabels
  • commonAnnotations

f:id:kakku22:20210830121332p:plain

今回はサンプルとして commonAnnotations を使って Annotation を追加する.Argo CD Application の YAML は以下のようになり spec.source.kustomize に commonAnnotations を設定している.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sandbox-kustomize-argocd
  namespace: argocd
spec:
  destination:
    namespace: kakakakakku-dev
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: https://github.com/kakakakakku/sandbox-kustomize.git
    path: overlays/dev
    targetRevision: HEAD
    kustomize:
      commonAnnotations:
        my-key: my-value
  syncPolicy:
    automated:
      selfHeal: true

Argo CD Application を更新する前後の Annotation は以下のようになった.ちゃんと my-key: my-value が追加されている.どういうときに使うと便利なのか今のところは思い付かないけど,kustomize の一部設定を kustomization.yaml ではなく Argo CD Application で管理したいときに使えそう!

$ kubectl describe pod -n kakakakakku-dev | grep Annotations
Annotations:  <none>
Annotations:  <none>
Annotations:  <none>
Annotations:  <none>
Annotations:  <none>

$ kubectl describe pod -n kakakakakku-dev | grep Annotations
Annotations:  my-key: my-value
Annotations:  my-key: my-value
Annotations:  my-key: my-value
Annotations:  my-key: my-value
Annotations:  my-key: my-value

kustomize で patchesStrategicMerge を使わずに簡単に replicas と images を変更する

今まで kustomize を使って Deployment の replicas を変更するときなどは kustomization.yaml に patchesStrategicMerge を設定していた.例えば,1年前に kustomize に入門したときに書いた以下の記事でもそういう手順になっている.

kakakakakku.hatenablog.com

最近 kustomize のドキュメントを読み直していたら replicas や images など,簡単に kustomization.yaml に設定できる機能があることに気付いた💡今まで知らなかった!検証も兼ねて試していく.

kubectl.docs.kubernetes.io

kubectl.docs.kubernetes.io

kustomize v4.2.0

なお,今回は kustomize v4.2.0 を使う.kubectl kustomize コマンドだとバンドルされているバージョンが古い可能性があり,正確には kubectl v1.20 までは kustomize v2.0.3 がバンドルされている.詳しくは GitHub に載っている.

$ brew install kustomize
$ kustomize version --short
{kustomize/v4.2.0  2021-07-01T00:44:28+01:00  }

github.com

replicas と images を試す

まず,以下のようなディレクトリ構成で base/ と overlays/ を準備する.Namespace + Service + Deployment (nginx) という基本構成で,今回は overlays/dev/ に設定している通り dev 環境を kustomize で作る.

.
├── README.md
├── base
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   ├── namespace.yaml
│   └── service.yaml
└── overlays
    └── dev
        └── kustomization.yaml

以下に base/ の代表的なファイルを載せておく.ポイントは base/deployment.yaml の replicas: 2 と image: nginx:1.20-alpine で,今回は kustomize で replicas: 5 と image: nginx:1.21-alpine に変更していく.

📁 base/kustomization.yaml

resources:
- namespace.yaml
- deployment.yaml
- service.yaml

📁 base/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20-alpine

次に overlays/ の dev 環境用の kustomization.yaml を載せる.ポイントは以下の2点となる.

  • replicas : Deployment のレプリカ数を count として設定できる
  • images : Deployment のイメージ名とタグ名を newName と newTag として設定できる

📁 overlays/dev/kustomization.yaml

resources:
  - ../../base
namespace: kakakakakku-dev
namePrefix: kakakakakku-dev-
commonLabels:
  app: kakakakakku-dev
replicas:
- name: kakakakakku-dev-nginx
  count: 5
images:
  - name: nginx
    newName: nginx
    newTag: 1.21-alpine

さっそく kustomize build overlays/dev コマンドを実行すると,期待通りに replicas: 5 と image: nginx:1.21-alpine に変更できている💡簡単!これなら patchesStrategicMerge を使わずに kustomization.yaml だけでシンプルに設定できる.

apiVersion: v1
kind: Namespace
metadata:
  labels:
    app: kakakakakku-dev
  name: kakakakakku-dev
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: kakakakakku-dev
  name: kakakakakku-dev-nginx
  namespace: kakakakakku-dev
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: kakakakakku-dev
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: kakakakakku-dev
  name: kakakakakku-dev-nginx
  namespace: kakakakakku-dev
spec:
  replicas: 5
  selector:
    matchLabels:
      app: kakakakakku-dev
  template:
    metadata:
      labels:
        app: kakakakakku-dev
    spec:
      containers:
      - image: nginx:1.21-alpine
        name: nginx

patchesStrategicMerge と組み合わせる

とは言え replicas と images では複雑な設定はできないため,要件によってはやはり patchesStrategicMerge と組み合わせることになる.例えば nginx に加えて fluentbit をサイドカーとして追加する場合,images ではイメージの追加には対応していなかったりする.以下のように overlays/dev/kustomization.yaml に patchesStrategicMerge を追加した.

📁 overlays/dev/kustomization.yaml

resources:
  - ../../base
namespace: kakakakakku-dev
namePrefix: kakakakakku-dev-
commonLabels:
  app: kakakakakku-dev
replicas:
- name: kakakakakku-dev-nginx
  count: 5
images:
  - name: nginx
    newName: nginx
    newTag: 1.21-alpine
patchesStrategicMerge:
  - deployment.yaml

そして overlays/dev/deployment.yaml に追加する fluentbit を差分として設定する.

📁 overlays/dev/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: fluentbit
        image: fluent/fluent-bit:1.8

もう1度 kustomize build overlays/dev コマンドを実行すると,今度は fluentbit も追加できている.

apiVersion: v1
kind: Namespace
metadata:
  labels:
    app: kakakakakku-dev
  name: kakakakakku-dev
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: kakakakakku-dev
  name: kakakakakku-dev-nginx
  namespace: kakakakakku-dev
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: kakakakakku-dev
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: kakakakakku-dev
  name: kakakakakku-dev-nginx
  namespace: kakakakakku-dev
spec:
  replicas: 5
  selector:
    matchLabels:
      app: kakakakakku-dev
  template:
    metadata:
      labels:
        app: kakakakakku-dev
    spec:
      containers:
      - image: fluent/fluent-bit:1.8
        name: fluentbit
      - image: nginx:1.21-alpine
        name: nginx

まとめ

今まで kustomize で知らなかった replicas と images を使って,patchesStrategicMerge を使わずに簡単にマニフェストを変更できた.要件次第では patchesStrategicMerge と組み合わせることになるだろうけど,基本的な変更なら kustomization.yaml だけで完結できそう.引き続き kustomize も勉強していくぞ!今回検証に使ったプロジェクトは以下で確認できる.

github.com

関連記事

kakakakakku.hatenablog.com