「Kustomize」超入門――複数環境の重過ぎKubernetesマニフェスト、どう管理すればいいのか:Cloud Nativeチートシート(2)
Kubernetesやクラウドネイティブをより便利に利用する技術やツールについて概要や使い方を凝縮して紹介していく連載。今回は、「Kustomize」を取り上げます。
Kubernetesやクラウドネイティブをより便利に利用する技術やツールについて概要や使い方を凝縮して紹介していく本連載「Cloud Nativeチートシート」。今回は「Kustomize」を取り上げます。
目次
- 複数環境の重過ぎKubernetesマニフェスト、どう管理すればいいのか
- 「Kustomize」とは
- Kustomizeの構成
- Kustomizeのインストール
- Kustomizeを使って差分情報を管理する方法
- 主なプラグイン、17の使い方
- Kustomizeをカスタマイズ
- 「Helm」との使い分け
- まとめ
複数環境の重過ぎKubernetesマニフェスト、どう管理すればいいのか
Kubernetesへのデプロイは「マニフェスト」を使っている方が多いのではないでしょうか。手動でデプロイする場合であれば、下記のようなコマンドを実行すると思います。CI/CD(継続的インテグレーション/継続的デリバリー)ツールなどを使ってデプロイをする際でも、手動の場合と同じようにマニフェストを使うことがほとんどでしょう。
kubectl apply -f manifest.yaml
このようにKubernetesでは、デプロイに関する記述をマニフェストというコードの形式で管理できるため、IaC(Infrastructure as Code)を手軽に実現できます。しかし、商用サービスを開発するようなケースでは、開発/試験/本番環境といった複数環境を利用することが求められます。このようなケースでは、例えば下記のような設定は、それぞれの環境において異なる値が設定される可能性があるため、環境差分としてこれらの情報を管理する必要があります。
- アプリケーションのバージョン
- 接続先のエンドポイント情報
- データベースへのクレデンシャル情報
では、どのようにしてこれらの環境差分を管理したらいいのでしょうか?
CI/CDツールなどを利用している場合、CI/CDツールをメンテナンスする若干名しか詳細を把握しておらず「最終的に、どのような状態になるか」が分かりにくくなるため、IaCの実現に苦労している方も多いと思います。環境ごとにGitのブランチを分けたり、フォルダを分けたりして、環境ごとにそれぞれのマニフェストを管理している方もいるかもしれませんが、マニフェストの記述量が増えると、環境差分の管理が大変になります。ファイルやブランチで管理していると、環境間でのファイルやブランチのマージにおいて“漏れ”なども発生します(図1)。
「Kustomize」とは
そこで、「Kustomize」を利用すると、この環境差分の管理が簡単にできるようになります。Kustomizeでは、ベースとなるマニフェストと、そのマニフェストに対する環境差分を管理し、ベースのマニフェストに対して環境差分情報のパッチを当てるという形でデプロイするマニフェストを生成、管理します(図2)。
そのため、上述した問題点を解消し、複数環境で開発しないといけない場合でも手軽にIaCを実現できます。
Kustomizeは、このように環境差分だけを管理し、同じ設定を重複して管理する必要がないため、「DRY(Don't Repeat Yourself)」の原則をサポートするためのツールと紹介されることもあります。
Kustomizeの構成
Kustomizeの構成を簡単に説明すると、図3のようになります。
開発環境(dev)と商用環境(prod)へそれぞれ別の設定でデプロイしたいとしましょう。まず、環境共通のマニフェスト「base」を定義します。baseに対し、それぞれの環境用の差分を「overlay」(上書き用のパッチ)として用意します。最終的にそれぞれのパッチが適用されたマニフェストを生成することができます。
具体的にファイル構成を見ていくと、次のようになります。
├── base │ ├── deployment.yaml │ ├── kustomization.yaml │ └── service.yaml └── overlays ├── dev │ ├── kustomization.yaml │ └── patch.yaml ├── prod │ ├── kustomization.yaml │ └── patch.yaml └── staging ├── kustomization.yaml └── patch.yaml
※本稿で利用しているサンプルは、「https://github.com/cloudnativecheetsheet/kustomize」から「git clone」コマンドで取得できるので、参考にしてください。
フォルダ構成を見ると、baseとoverlaysの2つのフォルダを確認できます。baseのフォルダには、全ての環境のベースとなるマニフェストを管理し、overlaysフォルダにある環境ごとの管理フォルダ(dev、prod)で、環境ごとの差分となる設定ファイル(マニフェスト)をパッチとして管理します。
各フォルダには、kustomizationファイル(kustomization.yaml)が配置されていますが、kustomizationファイルの中に環境ごとのパッチの処理を記述します。
具体的な設定方法や適用イメージについては、後述の「Kustomizeを使ってみよう」で見ていきます。
Kustomizeのインストール
Kustomizeを利用するには、「kubectl」コマンド組み込みのKustomizeを、「-k」オプションで利用する方法と、Kustomizeバイナリを導入してkustomizeコマンドで利用する方法があります。
2020年12月の執筆時時点でKustomizeの最新バージョンは、3.8.7ですが、kubectl組み込みのKustomizeは2.0.3と若干古いバージョンとなっています(※kubectl組み込みのKustomizeも将来的にバージョンアップされる予定があります)。
また、kubectlコマンドを利用する場合、「kubectl apply --dry-run=client -k」のように明示的に「--dry-run=client」オプションを付与しないと、「クラスタへのデプロイが発生します。kubectlコマンドを利用すると、生成されるYAMLを確認したかったのに、誤ってデプロイする」という可能性もあるので、Kustomizeを個別に導入することをお勧めします。
本稿では、最新のKustomizeを個別に導入して解説します。
インストール方法は、「curl」「bash」コマンドが使えるOSなら、「root」もしくは「sudo」ユーザーで下記コマンドを実行するだけです。
$ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
インストーラがOSを自動的に判別し、適切なバイナリをインストールしてくれます。なおWindowsの場合は、bashがデフォルトでは利用できないので、Kustomizeのリリースサイトの「Assets」から、exeファイルをダウンロードしインストールしてください。直接端末からインターネットに接続できない環境で利用する場合も、上記のリリースサイトからバイナリをダウンロード、コピーして、インストールしてください。
インストールが完了したら、シェルでkustomizeのコマンドやオプションを補完できるようにしておくと便利です。例えば、bashシェルの補完を利用するには、下記のようなコマンドを実行して、一度ログアウトしてログインし直します。
$ kustomize completion bash >> ~/.bashrc
bash以外にも、「zsh」「fish」「PowerShell」などの補完もサポートしています。
Kustomizeを使って差分情報を管理する方法
Kustomizeを使って差分情報を管理する方法は大きく2通りあります。
- patchマニフェストに差分を記述し、「kustomization」ファイルとは別ファイルとして管理
- プラグインを利用してkustomizationファイルに記述して管理
基本的に差分が別ファイルにばらばらに管理されると、変更内容の全体を把握するのが大変なので、2のプラグインを利用する方法がお勧めです。プラグインを利用すると、コンテナイメージのバージョンや「ConfigMap」など、環境ごとに頻繁に変わる設定については、kustomizationファイルに簡易な記述をするだけでパッチを当てることができます。
プラグインで対応できない場合は、1のpatchマニフェストを利用するとよいでしょう。
1.patch機能によるマニフェスト管理の実践
ここでは、nginxのレプリカ数(replica)を、prod環境で「3」に変更します。
「base」フォルダ
「deployment.yaml」「service.yaml」については、今までと変わりなく定義できます。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
kind: Service apiVersion: v1 metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: http
baseのkustomization.yamlには先ほどのマニフェストへのパスを「resources」に定義します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - deployment.yaml - service.yaml
baseのファイルが完成したら、baseディレクトリの親ディレクトリで下記のコマンドを実行すると、baseのファイルから生成される各環境のパッチを当てる前のマニフェストを確認できます。
$ ls -F base/ $ kustomize build base apiVersion: v1 kind: Service metadata: name: nginx-service ...
「overlays」フォルダ
例ではdev、staging、prodと3つ挙げていますが、1つ実践してみれば、同じ要領で使えるので、ここではprodのみを対象にします。以下、prodディレクトリ以下にファイルを作成していきます。
パッチ対象とパッチ内容「replicas: 3」を記述します。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3
最後にoverlays/prodのkustomization.yamlを作成します。resourcesにはbaseへのパスを定義し、patchesには先ほどのパッチ内容を記述したマニフェストへのパスを定義します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base patches: - patch.yaml
パッチを当てたマニフェストを出力してみます。baseディレクトリとoverlaysディレクトリを配置した親ディレクトリで下記のコマンドを実行します。
$ ls -F base/ overlays/ $ kustomize build overlays/prod apiVersion: v1 kind: Service metadata: name: nginx-service ...(中略)... --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment ...(中略)...
1つのマニフェストとして出力されたことを確認できたかと思います。次にbaseマニフェストとの差分を確認してみましょう。
$ diff -u <(kustomize build base) <(kustomize build overlays/prod) ... spec: - replicas: 1 + replicas: 3 selector: ...
上記のようにreplicasが3に変更されていることを確認できます。Kustomizeで生成されたマニフェストからKubernetesのリソースを作成するには、次のようにします。
$ kustomize build overlays/prod | kubectl apply -f -
2.プラグインを利用したKustomizeの利用
次に、Kustomizeが提供しているプラグインを使った差分管理の方法を見ていきます。プラグインを利用して、先ほどのreplicasの1を3に変更してみます。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base #patches: # - patch.yaml # patchesの代わりにreplicasを利用して、deploymentのreplicasを設定 replicas: - name: nginx-deployment count: 3
上記のように、replicasを記述して、「Deployment」のリソース名と変更するレプリカ数を記述するだけで、値を変更できます。
patchはどのような変更にも対応できますが、プラグインが利用できる場合は、プラグインを利用すると、patchに比べて直感的に変更内容を指定できます。できるだけプラグインを利用して環境ごとにカスタマイズした方がいいでしょう。また、patchなしでbaseだけでマニフェストが適用できるようにしておけば、baseマニフェストのテストが簡単になり、環境個別の部分だけをpatchで記述すればよくなります。
主なプラグイン、17の使い方
2020年12月の原稿執筆時点で、Kustomizeでは下記のプラグインを標準で提供しています。
プラグイン名 | 概要 |
---|---|
resources | Kustomizeで扱うマニフェスト、baseへのパスなどを定義 |
images | imageのバージョンタグなどのパッチを定義 |
replicas | replicasの値のパッチを定義 |
namespace | デプロイ先のnamespaceのパッチを定義 |
namePrefix | デプロイ名(metadata.name)に指定したプレフィックスを付与するパッチを定義 |
nameSuffix | デプロイ名(metadata.name)に指定したサフィックスを付与するパッチを定義 |
commonLabels | デプロイ対象全てに指定したラベルをmetadata.labelsに付与するパッチを定義。Deployment、「StatefulSet」「DaemonSet」については、「Pod Template」の「spec.template.metadata.labels」にも付与される |
commonAnnotations | デプロイ対象全てに指定したラベルをmetadata.annotationsに付与するパッチを定義。Deployment、StatefulSet、DaemonSetについては、Pod Templateのspec.template.metadata.annotationsにも付与される |
configMapGenerator | ConfigMapを生成するためのプラグイン。さまざまな生成方法をサポート |
secretGenerator | 「Secret」を生成するためのプラグイン。さまざまな生成方法をサポート |
generatorOptions | configMapGenerator、secretGeneratorなどのジェネレータープラグインで生成されるSecret、ConfigMapリソースの生成方法を定義 |
patches | 任意のパッチを定義。「strategic-merge-style patch(SMP)」形式、もしくは「JSON Patch」形式で定義可能 |
patchesJson6902 | 任意のパッチを定義。patchesにおける「JSON Patch」形式のみを記述する場合に利用 |
patchesStrategicMerge | 任意のパッチを定義。patchesにおける「strategic-merge-style patch(SMP)」 |
crds | Kustomizeで「CustomResourceDefinition(CRD)」を扱う場合に、対象のCRDを指定 |
components | 複数のオーバーレイ(overlays)から再利用可能な設定ロジックを定義。複数のオプション機能をサポートしているアプリケーションで、異なるオーバーレイでそれらのサブセットだけを有効にしたい場合に利用 |
vars | あるリソースのフィールドから文字列を取得し、その文字列を別の設定値に挿入するために使用。例えば、「Service」で定義したサービス名(metadata.name)の名前をDeploymentで実行するPodのコマンドラインの引数(args)や環境変数(env)に渡すような使い方が可能 |
以前は、「bases」も提供されていましたが、「resources」で代替可能となり、非推奨となりました。
以下、主なプラグインを上記表の記述順に解説します。resourcesについては既に紹介しているので、解説は省略します。
images
デプロイ対象のコンテナイメージを確認ごとに変更したいときに利用します。例えば、staging環境で新規イメージの動作を確認してから、prod環境のイメージを変更したいときなどに利用するとよいでしょう。パッチできる内容は下記の通りです。
フィールド | 概要 |
---|---|
name | パッチ対象のコンテナイメージ名を指定 |
newTag | コンテナイメージのtagを指定 |
digest | コンテナイメージのdigestを指定 |
newName | パッチ対象のコンテナイメージ名を変更したい場合に、変更後のイメージ名を指定 |
例えば、イメージ名「nginx」のコンテナのタグに1.8.0を指定したい場合は、次のようにします。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base images: - name: nginx newTag: 1.8.0
imagesプラグインによるbaseマニフェストからの差分を確認してみましょう。
$ diff -u <(kustomize build base) <(kustomize build overlays/prod) - - image: nginx:1.14.2 + - image: nginx:1.8.0
このように、イメージタグが変更され、古いイメージをデプロイできるようになりました。
replicas
デプロイ対象のspec.replicasの値に変更するための機能です。以下のリソースを指定できます。
- Deployment
- ReplicaSet
- StatefulSet
- ReplicationController
フィールド | 概要 |
---|---|
name | パッチ対象のリソース名(metadata/nameの値)を指定 |
count | レプリカ数を指定 |
利用方法については、Deploymentリソースのreplicasの変更例を既に紹介済みなので省略します。
namespace
デプロイ対象のネームスペースを変更するための機能です。resourcesで指定したリソースの全てのネームスペースを指定した値に変更します。同一Kubernetesクラスタ内でネームスペースを変えて異なるステージング環境にデプロイしたいときなどに利用すると便利です。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base namespace: prod
パッチの内容を確認してみましょう。
$ kustomize build overlays/prod apiVersion: v1 kind: Service metadata: name: nginx-service namespace: prod spec: ... 省略 --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment namespace: prod spec: ... 省略
7行目、17行目の通り、全てのリソースのネームスペースが変更されました。
namePrefix、nameSuffix
デプロイ対象のリソース名の前にプレフィックスとサフィックスを付与するための機能です。例えば、namePrefixは「xxx」という名前のリソースに「pre-xxx」のようにリソース名の前にプレフィクスを追加できます。nameSuffixはリソース名の後ろに「xxx-post」のようにサフィックスを追加できます。
ここでは、namePrefixの利用例を紹介します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base namePrefix: pre-
パッチの内容を確認してみましょう。
$ diff -u <(kustomize build base) <(kustomize build overlays/prod) - name: nginx-service + name: pre-nginx-service ... - name: nginx-deployment + name: pre-nginx-deployment
また、このパッチは「PodSpec」から参照されているConfigMapやSecretのリソース名にも適用されます。
commonLabels
全てのリソースに指定したラベルを追加します。ServiceやDeploymentのセレクタ(spec.selector)にもラベルが追加され、リソース参照の整合性を取るようになっています。
例えば、次のように定義します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base commonLabels: app: nginx environment: prod
パッチの内容を確認してみましょう。
$ kustomize build overlays/prod apiVersion: v1 kind: Service metadata: labels: app: nginx environment: prod name: nginx-service spec: ports: - port: 80 protocol: TCP targetPort: http selector: app: nginx environment: prod --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx environment: prod name: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx environment: prod template: metadata: labels: app: nginx environment: prod spec: containers: - image: nginx:1.14.2 name: nginx ports: - containerPort: 80
6〜8行目、16〜17行目、22〜24行目、29〜31行目、34〜36行目の通り、ラベルが追加されているのを確認できます。
commonAnnotations
リソースにアノテーションを追加します。デプロイしたリソースが明示的に「どの環境にデプロイしたものか」を分かりやすくするのに利用できます。現在チェックしているリソース環境の取り違いを防止できます。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base commonAnnotations: env: prod**
パッチの内容を確認してみましょう。
$ kustomize build overlays/prod apiVersion: v1 kind: Service metadata: annotations: env: prod name: nginx-service spec: ... 省略 --- apiVersion: apps/v1 kind: Deployment metadata: annotations: env: prod labels: app: nginx name: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: annotations: env: prod ... 省略
6〜7行目、15〜16行目、27〜28行目の通り、アノテーションが追加されているのを確認できます。
configMapGenerator
configMatpGeneratorは、ConfigMapリソースを作成するための機能です。例えば、baseで次のように定義します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization configMapGenerator: - name: my-configmap files: - common.properties literals: - port=8080
nameにConfigMap名を、filesにプロパティが記述されたファイルパスを、literalsでプロパティを指定します。ここでは、filesで指定するプロパティファイルに、下記を作成してみます。
proxy=proxy.example.com
ファイルが準備できたら、baseディレクトリでkustomizeを実行して確認してみます。
$ kustomize build . apiVersion: v1 data: common.properties: | proxy=proxy.example.com port: "8080" kind: ConfigMap metadata: name: my-configmap-g5c5m5cdtb
kind(8行目)とmetadata(10行目)の位置が通常と異なるので分かりづらいですが、ConfigMapリソースの定義が作成されているのを確認できます。
またリソース名には、「my-configmap」と指定したリソース名に「-g5c5m5cdtb」というように、configMapGeneratorで定義された内容からハッシュ値が追加され、定義した内容に対し、値が一意の値になっています。
次に、prod環境のkustomizationファイルと設定を準備します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base configMapGenerator: - name: my-configmap behavior: merge files: - env.properties - secret.properties
ConfigMapGeneratorのbehaviorにmergeを指定してbaseと同様に定義していきます。「merge」と記載すると、baseの内容とprodに記載した内容をマージします。replaceとすると、baseで定義した内容が上書きされます。
ここでは、下記のプロパティファイルを用意します。
host=prod-server.example.com
proxyPassword=proxyPasswordForProd
baseとprodの差分を確認してみます。
$ diff -u <(kustomize build base) <(kustomize build overlays/prod) ... data: common.properties: | proxy=proxy.example.com + env.properties: | + host=prod-server.example.com port: "8080" + secret.properties: | + proxyPassword=proxyPasswordForProd kind: ConfigMap metadata: - name: my-configmap-g5c5m5cdtb + annotations: {} + labels: {} + name: my-configmap-5kfgt2259c
prodのconfigMapGeneratorで追加したプロパティが追加されているのが分かります。また、ConfigMapの内容が変更になったので、リソース名に付与されたハッシュ値が「g5c5m5cdtb」から「5kfgt2259c」に変更されているのが分かります。リソース名にハッシュ値が追加されていますが、DeploymentリソースなどでConfigMapを参照している場合は、自動的にハッシュ値が付与されたConfigMapのリソース名に変更され、整合性が自動的に取られます。
毎回ハッシュ値が追加されてリソース名が変更されるのが嫌な場合は、後述のgeneratorOptionsの「disableNameSuffixHash」で「false」と設定します。
secretGenerator
configMapGeneratorと同様にSecretリソースを生成するための機能です。configMapGeneratorと使い方はほぼ同じで、追加でSecretリソースの「type」フィールドを定義できるようになっています。他の点は、configMapGeneratorと同様なので、事前にconfigMapGeneratorを一読してください。
例えば、baseで次のように定義します。typeにはSecretリソースのtypeで指定する「Opaque」「kubernetes.io/tls」などの値を定義します。ここでは、kubernetes.io/tlsを利用した例を紹介します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization secretGenerator: - name: app-tls files: - "tls.crt" - "tls.key" type: "kubernetes.io/tls"
base/kustomization.yamlでは、証明書や秘密鍵を下記のように指定します。
-----BEGIN CERTIFICATE----- MIID1zC... (中略) -----END CERTIFICATE-----
-----BEGIN PRIVATE KEY----- MIIEvgI.... (中略) -----END PRIVATE KEY-----
ファイルが準備できたら、baseディレクトリでkustomizeを実行して確認してみます(4〜5行目、8〜9行目)。
$ kustomize build . apiVersion: v1 data: tls.crt: LS0tLS1CRUdJTiBDRVJ... tls.key: LS0tLS1CRUdJTiBQUkl... kind: Secret metadata: name: app-tls-tf8km6hb9h type: kubernetes.io/tls
prodについてはconfigMapGeneratorと同様に記述することができます。
generatorOptions
configMapGeneratorやsecretGeneratorで生成するマニフェストにannotations、labelsを付与できます。また、generatorによって生成されたマニフェストのnameにはハッシュ値が付与されますが、disableNameSuffixHashによってこのハッシュ値を付与するかどうかを制御できます。
例えば、baseで次のように定義します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization secretGenerator: - name: app-tls files: - "tls.crt" - "tls.key" type: "kubernetes.io/tls" generatorOptions: labels: kustomize.generated.resources: base annotations: kustomize.generated.resource: base disableNameSuffixHash: true
ファイルが準備できたら、baseディレクトリでkustomizeを実行して確認してみます。
$ kustomize build . apiVersion: v1 data: tls.crt: LS0tLS1CRUdJTiBDRVJ... tls.key: LS0tLS1CRUdJTiBQUkl... kind: Secret metadata: annotations: kustomize.generated.resource: base labels: kustomize.generated.resources: base name: app-tls type: kubernetes.io/tls
annotations(9行目)、labels(11行目)に値が付与されていることが分かります。また、nameの値にハッシュ値が付与されていないことを確認できます(12行目)。
patches、patchesJson6902、patchesStrategicMerge
patches、patchesJson6902、patchesStrategicMergeは任意のパッチを適用するための機能です。patchesがサポートしているパッチの定義方法は下記リストの通りです。「記述スタイル」「記述箇所」「パッチ対象」を組み合わせることで複数の方法でパッチ定義を表現できます。
- 記述スタイル
- JSON Patch
- strategic-merge-style patch(SMP)
- 記述箇所
- ファイル
- インライン文字列
- パッチ対象
- 単一リソース
- 複数リソース
まずは、基本構文から解説し、JSON Patch、SMPのそれぞれの記述スタイルによる定義方法を解説していきたいと思います。なお、patchesJson6902はJSON Patchの記述スタイルのみ、patchesStrategicMergeはSMPの記述スタイルのみのサポートとなります。patchesでどちらの形式もサポート可能なので、patchesのみを対象に解説します。
パッチは、次のフォーマットで記述します。
patches: - path: パッチ内容を記述したファイルへのパス target: group: パッチ対象のリソースのgroupを指定 version: パッチ対象のリソースのversionを指定 kind: パッチ対象のリソースのkindを指定 name: パッチ対象のリソースのmetadata.nameを指定。正規表現でも記述することが可能 namespace: パッチ対象のリソースのnamespaceを指定 labelSelector: パッチ対象のリソースに設定されているmetadata.labelsに対するラベルセレクタを指定 annotationSelector: パッチ対象のリソースに設定されているmetadata.annotationsに対するセレクタを指定
パッチ内容を別ファイルではなく、kustomization.yamlファイル内にインライン文字列として記述することもできます。
patches: - patch: |- パッチ内容をインライン文字列で記述 ...
・JSON Patchの記述スタイル
JSON Patchを利用するとパッチをJSON形式で記述することもできます。ここでは、「overlays/prod/patch.json」ファイルにnginxのDeploymentに「livenessProbe」を追加するパッチを定義します。
[ { "op": "add", "path": "/spec/template/spec/containers/0/livenessProbe", "value": { "httpGet": { "port": 80, "path": "/" }, "failureThreshold": 5, "periodSeconds": 5 } } ]
「op」に変更操作(ここでは追加「add」)を、「path」に変更するパスを、「value」に内容を追加します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base patches: - path: patch.json target: group: apps version: v1 kind: Deployment name: nginx-deployment
パッチの内容を確認してみましょう。
$ kustomize build overlays/prod ... --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:1.14.2 livenessProbe: failureThreshold: 5 httpGet: path: / port: 80 periodSeconds: 5 name: nginx ports: - containerPort: 80
23〜28行目にある通り、nginxのDeploymentにlivenessProbeが追加できていることを確認できました。
次にインライン文字列で定義する方法を解説します。パッチの内容は先ほどと同様です。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base patches: - patch: |- - op: add path: /spec/template/spec/containers/0/livenessProbe value: httpGet: port: 80 path: / failureThreshold: 5 periodSeconds: 5 target: group: apps version: v1 kind: Deployment name: nginx-deployment
結果を確認すると、ファイルで定義した場合と同様な結果が得られることが分かります。target.nameには「nginx-.*」のように正規表現を指定でき、パターンにマッチするリソースを一括して指定可能です。
・SMPの記述スタイル
次に、もう一つの記述スタイルであるSMPを解説していきます。パッチを記述すファイルは、「overlays/prod/patch.yaml」とします。先ほどと同じnginxのDeploymentにlivenessProbeを定義するパッチは下記のようになります。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: template: spec: containers: - name: nginx livenessProbe: failureThreshold: 5 httpGet: path: / port: 80 periodSeconds: 5
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base patches: - path: patch.yaml target: group: apps version: v1 kind: Deployment name: nginx-deployment
kustomizationファイル内で下記のようにインラインでも記述できます。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base patches: - patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: template: spec: containers: - name: nginx livenessProbe: failureThreshold: 5 httpGet: path: / port: 80 periodSeconds: 5 target: group: apps version: v1 kind: Deployment name: nginx-deployment
vars
あるリソースのフィールドから文字列を取得し、その文字列を別の設定値に挿入できます。例えば、Serviceで定義したリソース名(metadata.name)をDeploymentで実行するPodのコマンドラインの引数(args)や環境変数(env)に渡すような使い方が可能なので、自サービスの公開サービス名を確認変数から渡したいケース、互いのサービスを呼び出すようなケースなどで利用できます。
サンプルを見ていきましょう。まずは下記のようにbaseに変数を用意しておきます。変数は「$(変数名)」のように設定します(24行目)。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 env: - name: NGINX_HOST value: $(NGINX_SERVICE)
続いて、overlays/prodで「$(NGINX_SERVICE)」に値を代入します。「objref」「fieldref」を用いて代入する値の取得元を指定します。objrefにはKubernetesのオブジェクト名を、fieldrefには当該オブジェクトにおける値の取得元フィールドを指定します。fieldrefは省略可能で、省略するとリソース名がデフォルト値になります。ここでは、代入する値はnginxのServiceリソースのリソース名とする例を示します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base vars: - name: NGINX_SERVICE objref: kind: Service apiVersion: v1 name: nginx-service fieldref: fieldpath: metadata.name
パッチを適用した結果を確認してみましょう。
$ kustomize build overlays/prod apiVersion: v1 kind: Service metadata: name: nginx-service spec: ports: - port: 80 protocol: TCP targetPort: http selector: app: nginx --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - env: - name: NGINX_HOST value: nginx-service image: nginx:1.14.2 name: nginx ports: - containerPort: 80
$(NGINX_SERVICE)にnginxのServiceリソースのリソース名nginx-serviceが代入されたことを確認できました(34行目)。
変数に代入できる箇所は決まっており、「/api/konfig/builtinpluginconsts/varreference.go」に記述されている箇所のみなので、注意が必要です。
デフォルトで代入できない場所に変数を代入したい場合は、「configurations」と「varReference」を利用します。varReferenceファイルに変数を代入するパスを指定しconfigurationsでvarReferenceファイルを指定します。記述方法は、参照先と同様にkustomization.yamlに記述します。
試しに、下記のようにbase/deployment.yamlに変数を設定してみます。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx service: $(NGINX_SERVICE) template: metadata: labels: app: nginx service: $(NGINX_SERVICE) spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 env: - name: NGINX_HOST value: $(NGINX_SERVICE)
すると、下記の26行目、31行目のように変数に値が代入されていないことが分かります。
$ kustomize build base apiVersion: v1 kind: Service metadata: name: nginx-service spec: ports: - port: 80 protocol: TCP targetPort: http selector: app: nginx --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx service: $(NGINX_SERVICE) template: metadata: labels: app: nginx service: $(NGINX_SERVICE) spec: containers: - env: - name: NGINX_HOST value: nginx-service image: nginx:1.14.2 name: nginx ports: - containerPort: 80
上記に対し、configurations、varReferenceを使って変数に値を代入できるようにします。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base vars: - name: NGINX_SERVICE objref: kind: Service apiVersion: v1 name: nginx-service fieldref: fieldpath: metadata.name configurations: - varReference.yaml
overlays/prod/varReference.yamlには、/api/konfig/builtinpluginconsts/varreference.goに記述されているように、「kind」「path」を使って変数を代入するリソースとパスを指定します。
varReference: - path: spec/selector/matchLabels/service kind: Deployment - path: spec/template/metadata/labels/service kind: Deployment
パッチを提供すると、先ほどまで変数に置換されていなかった値が変数で置換されていることを確認できます。
$ kustomize build prod ... apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx service: nginx-service template: metadata: labels: app: nginx service: nginx-service spec:
14行目、19行目のように指定した箇所の変数にも値が代入されていることを確認できました。
Kustomizeをカスタマイズ
Kustomizeではプラグインの仕組みが提供されており、自分でもパッチ機能を作ることができます。今まで紹介した機能もプラグインの仕組みで実現しています。
今回は解説しませんが、ご興味がある読者の方は「Extending Kustomize」をぜひ確認してみてください。
「Helm」との使い分け
Kustomize以外にも、アプリケーションをデプロイするためのツールとして「Helm」があります。
Helmは、Kubernetes上でのパッケージマネジャーとして、広く利用されています。Linuxを利用したことがある読者なら「yum」「RPM」、macOSを利用しているなら「Homebrew」などのツールと同類と考えると理解しやすいでしょう。
Helmは次回紹介しますが、使い分けの観点で簡単に比較しておきます。
メリット | デメリット | |
---|---|---|
Kustomize | ・学習コストが低い ・Kubernetes標準のコマンドラインツールに統合されている ・カスタマイズしやすい(Kustomizeというだけある……) |
・さまざまな設定が想定されるようなアプリケーションでは、利用者側のカスタマイズが多くなり利便性が下がる |
Helm | ・配布の仕組みが整っている ・条件分岐などが記述できるので、さまざまな設定が想定されるアプリケーションの管理に向いている |
・Helmの記述方法を学習するコストが高い ・「どこまで共通的に利用できるテンプレートにすべきか」の設計が難しい ・テンプレートに書いてある以上のことができないので、カスタマイズ性が低い ・設定値がどのように反映されるのか把握しにくい |
上記の比較を踏まえ、自分が開発、運用しているシステム内のマイクロサービスをデプロイするためのツールはKustomizeが適していると筆者は考えます。また、Helmは公開されているアプリケーションをKubernetes上にデプロイ(インストール)する、もしくは自分のアプリケーションを公開するツールとして利用することに適していると考えています。
まとめ
今回は、Kustomizeについて、基本的な機能を一通り紹介しました。Kustomizeは、複数環境でのCI/CDを実施していく上で今後、必須のツールになります。「複数環境のマニフェストの管理が煩雑だ」と感じた人はぜひ使ってみてください。また、これからCI/CDを始める人は、Kustomizeを前提にCI/CDを設計することをお勧めします。
今回のサンプル
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- Kubernetesの自前運用は難しい? はてなの撤退事例
はてなのMackerelチームはKubernetesクラスタを自前で構築して運用していたが、撤退を選択したという。なぜ、Kubernetesの運用を諦めて撤退を選んだのか。はてなのMackerelチームでSREを務める今井隼人氏が語った。 - Kubernetesを手元で試せる「Minikube」「MicroK8s」とは
「コンテナ技術」やコンテナ実行環境の「Docker」、大量のコンテナ管理や負荷分散を実現する「Kubernetes」について概要から本番活用の仕方まで解説する「これから始める企業のためのコンテナ実践講座」。第4回は、Kubernetesのパッケージマネジャー「Helm」と手元で試せる「Minikube」「MicroK8s」を紹介します。 - Kubernetes 1.14がリリース、Windowsコンテナサポートが安定版に到達
Kubernetesプロジェクトは2019年3月25日(米国時間)、Windowsノードの本番サポートなどを盛り込んだKubernetes 1.14をリリースしたと発表した。Kubernetes 1.14では、安定性に重点を置き、既にβ版などとして搭載している機能を成熟させることに力を注いだという。