電通総研 テックブログ

電通総研が運営する技術ブログ

kustomizeでCustom Resourceを扱う

こんにちは。Xイノベーション本部クラウドイノベーションセンターの柴田です。

本記事ではkustomizeでCustom Resourceを扱う方法を紹介します。

kustomizeとは

kustomizeKubernetesマニフェストファイルを加工・生成するためのツールです。 ユースケースとして例えば環境毎(開発や本番など)にマニフェストの設定を上書きしたい場合などに利用できます。

kustomizeは内部にKubernetesの標準リソース( Deployment など)のスキーマを保持しています。 これにより標準リソースのマニフェストを適切に加工できます。

例をみてみましょう。今回は以下の Deployment リソースをkustomizeで加工します。

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:stable
        env:
        - name: KEY1
          value: VALUE1
        - name: KEY2
          value: VALUE2
      - name: mysidecar
        image: mysidecar:stable

同一ディレクトリに kustomization.yaml を作成します。設定内容は以下のとおりです。

  • commonLabels で全体に app.kubernetes.io/name: myapp-overwrite labelを設定します。
  • patchesmyapp コンテナに環境変数 KEY2=VALUE2-overwrite を設定します。
# kustomization.yaml (for deployment)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app.kubernetes.io/name: myapp-overwrite
resources:
- deployment.yaml
patches:
- patch: |-
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: myapp
            env:
            - name: KEY2
              value: VALUE2-overwrite

kustomize build コマンドを実行すると以下の結果が出力されます。 Deployment が期待通り加工されました。

# Output of `kustomize build` command.
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: myapp-overwrite
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp-overwrite
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp-overwrite
    spec:
      containers:
      - env:
        - name: KEY2
          value: VALUE2-overwrite
        - name: KEY1
          value: VALUE1
        image: myapp:stable
        name: myapp
      - image: mysidecar:stable
        name: mysidecar

ここでのポイントは以下の2点です。

  • containersenv について、単に配列をまるごと上書きするのではなく、 name の値をキーに適切にマージされている。
  • .metadata.labels だけでなく .spec.selector.matchLabels.spec.template.metadata.labels にも app.kubernetes.io/name labelが設定されている。

kustomizeでCustom Resourceを適切に扱う

kustomizeはデフォルトでCustom Resourceを適切に扱えない

kustomizeはデフォルトでCustom Resourceを適切に加工できません。 kustomizeがCustom Resourceのスキーマを把握していないためです。

例をみてみましょう。今回は Argo RolloutsRollout リソースをkustomizeで加工します。

# rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:stable
        env:
        - name: KEY1
          value: VALUE1
        - name: KEY2
          value: VALUE2
      - name: mysidecar
        image: mysidecar:stable

同一ディレクトリに kustomization.yaml を作成します。

# kustomization.yaml (for rollout)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app.kubernetes.io/name: myapp-overwrite
resources:
- rollout.yaml
patches:
- patch: |-
    apiVersion: argoproj.io/v1alpha1
    kind: Rollout
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: myapp
            env:
            - name: KEY2
              value: VALUE2-overwrite

kustomize build コマンドを実行すると以下の結果が出力されます。

# Output of `kustomize build` command.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  labels:
    app.kubernetes.io/name: myapp-overwrite
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
    spec:
      containers:
      - env:
        - name: KEY2
          value: VALUE2-overwrite
        name: myapp

先程の Deployment の例と比較すると以下の点が異なります。

  • containersenvpatches の内容でまるごと上書きされている。
  • .spec.selector.matchLabels.spec.template.metadata.labelsapp.kubernetes.io/name labelが更新されていない。

kustomizeでCustom Resourceを適切に扱う

kustomzieでCustom Resourceを扱うには、以下の2つの対応を行う必要があります。

Argo Rolloutsの公式ドキュメント に従って、先程のArgo Rolloutsの例を以下のとおり修正してみましょう。

  1. Argo RolloutsのOpenAPIスキーマこちら からダウンロードします。
curl -OL https://github.com/argoproj/argo-rollouts/raw/master/docs/features/kustomize/rollout_cr_schema.json
  1. kustomization.yamlopenapiconfigurations の設定を追記します。
# kustomization.yaml (for rollout)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app.kubernetes.io/name: myapp-overwrite
resources:
- rollout.yaml
patches:
- patch: |-
    apiVersion: argoproj.io/v1alpha1
    kind: Rollout
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: myapp
            env:
            - name: KEY2
              value: VALUE2-overwrite
openapi:
  path: rollout_cr_schema.json
configurations:
- https://argoproj.github.io/argo-rollouts/features/kustomize/rollout-transform.yaml

kustomize build コマンドを実行すると以下の結果が出力されます。 今度は Rollout リソースが(ほぼ)期待通り加工されました。 なお env は依然として上書きされていますが、これはArgo RolloutsのOpenAPIスキーマの問題です。 詳細は #1730 をご参照ください。

# Output of `kustomize build` command.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  labels:
    app.kubernetes.io/name: myapp-overwrite
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp-overwrite
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp-overwrite
    spec:
      containers:
      - env:
        - name: KEY2
          value: VALUE2-overwrite
        image: myapp:stable
        name: myapp
      - image: mysidecar:stable
        name: mysidecar

kustomizeで標準リソースとCustom Resourceを適切に扱う

独自のOpenAPIスキーマを設定すると標準リソースを適切に扱えなくなる

kustomizeの OpenAPI Features は、build-inのスキーマ加えて 受け取ったOpenAPIスキーマを参照するのではなく、build-inのスキーマかわりに 受け取ったOpenAPIスキーマを参照します。 そのため kustomization.yamlopenapi に独自のOpenAPIスキーマを設定すると、kustomizeがKubernetesの標準リソースのスキーマを参照できず、適切に加工できなくなります。

例をみてみましょう。今回はkustomizeで DeploymentRollout の両方を加工します。 deployment.yamlrollout.yaml は先程の例と同じものを使用します。

# kustomization.yaml (for deployment and rollout)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app.kubernetes.io/name: myapp-overwrite
resources:
- deployment.yaml
- rollout.yaml
patches:
- patch: |-
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: myapp
            env:
            - name: KEY2
              value: VALUE2-overwrite
- patch: |-
    apiVersion: argoproj.io/v1alpha1
    kind: Rollout
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: myapp
            env:
            - name: KEY2
              value: VALUE2-overwrite
openapi:
  path: rollout_cr_schema.json
configurations:
- https://argoproj.github.io/argo-rollouts/features/kustomize/rollout-transform.yaml

kustomize build コマンドを実行すると以下の結果が出力されます。 kustomization.yamloepnapi にArgo RolloutsのOpenAPIスキーマを設定したため Rollout は期待通り加工できました。 しかし今度は Deploymentcontainersenvpatches の内容でまるごと上書きされてしまいました。

# Output of `kustomize build` command.
kustomize build .
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: myapp-overwrite
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp-overwrite
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp-overwrite
    spec:
      containers:
      - env:
        - name: KEY2
          value: VALUE2-overwrite
        name: myapp
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  labels:
    app.kubernetes.io/name: myapp-overwrite
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp-overwrite
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp-overwrite
    spec:
      containers:
      - env:
        - name: KEY2
          value: VALUE2-overwrite
        image: myapp:stable
        name: myapp
      - image: mysidecar:stable
        name: mysidecar

kustomizeで標準リソースとCustom Resourceを適切に扱う

この問題は

  • 標準リソース
  • Custom Resource

の両方のOpenAPIスキーマを統合して kustomization.yamloepnapi に渡すことで解決できます。

先程の例を以下のとおり修正してみましょう。 Kubernetesの標準リソースのOpenAPIスキーマこちら からダウンロードできます。

  1. 標準リソースとArgo RolloutsのOpenAPIスキーマを統合する。
curl -sOL https://github.com/kubernetes/kubernetes/raw/master/api/openapi-spec/swagger.json
curl -sOL https://github.com/argoproj/argo-rollouts/raw/master/docs/features/kustomize/rollout_cr_schema.json
jq -s '.[0] * .[1]' swagger.json rollout_cr_schema.json > openapi.json
  1. 作成したファイルを kustomization.yamlopenapi に指定する。
# kustomization.yaml (for deployment and rollout)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app.kubernetes.io/name: myapp-overwrite
resources:
- deployment.yaml
- rollout.yaml
patches:
- patch: |-
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: myapp
            env:
            - name: KEY2
              value: VALUE2-overwrite
- patch: |-
    apiVersion: argoproj.io/v1alpha1
    kind: Rollout
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: myapp
            env:
            - name: KEY2
              value: VALUE2-overwrite
openapi:
  path: openapi.json
configurations:
- https://argoproj.github.io/argo-rollouts/features/kustomize/rollout-transform.yaml

kustomize build コマンドを実行すると以下の結果が出力されます。 今度は DeploymentRollout の両方を期待通り加工できました。

# Output of `kustomize build` command.
kustomize build .
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: myapp-overwrite
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp-overwrite
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp-overwrite
    spec:
      containers:
      - env:
        - name: KEY2
          value: VALUE2-overwrite
        - name: KEY1
          value: VALUE1
        image: myapp:stable
        name: myapp
      - image: mysidecar:stable
        name: mysidecar
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  labels:
    app.kubernetes.io/name: myapp-overwrite
  name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp-overwrite
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp-overwrite
    spec:
      containers:
      - env:
        - name: KEY2
          value: VALUE2-overwrite
        image: myapp:stable
        name: myapp
      - image: mysidecar:stable
        name: mysidecar

終わりに

本記事ではkustomizeでCustom Resourceを扱う方法を紹介しました。 本記事がkustomizeを使ってKubernetesを運用する方の役に立てば幸いです。

参考


私たちは同じチームで働いてくれる仲間を探しています。クラウドアーキテクトの業務に興味がある方のご応募をお待ちしています。

執筆:@shibata.takao、レビュー:@sato.taichiShodoで執筆されました