Kubernetesのマニフェストを書いていくと、環境(本番やStagingなど)ごとに重複するコードが出てきます。
そのため環境差分だけどこかに切り出したいなーと思うことがあるでしょう。
そういったときに使えるのがKustomizeというツールです。
今回はKustomizeでできることを 自分が知り限りの範囲で列挙 していきます。(適宜更新していきます。)
インストール方法は公式ドキュメントをご覧ください。
今回ここでご紹介する機能以外にも機能があるので
興味がありましたらドキュメントをご覧ください。
環境ごとにイメージのタグを変える
例えば nginx
というコンテナイメージがあるとして
本番では v1.8.0
、Stagingでは v1.9.0
をデプロイしたいとします。
普通にマニフェストを書くと、イメージのタグが違うだけのDeploymentのマニフェストが2つできて無駄です。
そのような場合、以下のように環境ごとに設定を行うことができます。
sampleコードはこちら
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: sample
ports:
- containerPort: 80
resources:
- ../../base
images:
- name: sample
newName: nginx
newTag: 1.19.0
images.name
で、Deploymentで指定しているイメージ名を指定できます。この名前は自由に決められます。
images.newName
で正しいイメージ名を指定します。
images.newTag
で指定したいタグ名を指定します。
このようにすると、環境ごとに異なるタグを指定することが実現できます。
環境ごとにマニフェストの要素を書き換える
イメージタグ名以外の環境差分ももちろん表現することができます。
sampleコードはこちら
例えばDeploymentで定義するレプリカ数を本番だけ 2
にしたいとしましょう。
そういう場合以下のように書くことができます。
resources:
- ../../base
patches:
- deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 2
kustomization.yamlのpatchesで、上書きしたい要素のみを指定したマニフェストを指定することで
Kustomizeがうまいことマージしてくれます。
ちなみに要素を削除したい場合、以下のように実現できます。
argsという要素を消したい場合・・・
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
template:
spec:
containers:
- name: nginx
args: null
# 比較的新しいKustomizeのバージョンを使用している場合は以下の書き方のほうがわかりやすい
# args:
# $patch: delete
配列内の要素を書き換える
上記のpatchのやり方だと難しいのが、配列に対する変更です。
例えば、配列の0番目の要素のみ書き換えた場合、上記のやり方だとできません。
そのようなことがやりたい場合は、patchesJSON6902
を使用します。
sampleコードはこちら
たとえば以下のようなDeploymentがあったとして、argsの2番目の値を変えたいとします。
# 必要なところだけ抽出します
containers:
- name: nginx
image: nginx:1.19.0
args:
- hoge
- fuga
ports:
- containerPort: 80
これを書き換えるには以下のようにします。
resources:
- ../../base
patchesJSON6902:
- target:
group: apps
version: v1
kind: Deployment
name: sample-deployment
patch: |-
- op: replace
path: /spec/template/spec/containers/0/args/1
value: piyo
patchesJSON6902
はその他にも metadata.name
を変更できます。
通常のpatchはこの metadata.name
を元にマージ戦略を考えますが、それ自体を変更するとなると patchesJSON6902
を使う必要があります。
リソースを配置するnamespaceを環境ごとに変える
例えば本番とStagingが同じk8sクラスタに存在した場合、namespaceで分けたいことがあると思います。
それもKustomizeで簡単に実現できます。
sampleコードはこちら
namespace
をkustomization.yamlで書くだけです。
namespace: production
resources:
- ../../base
これをbaseのkustomization.yamlに書けば、全環境でリソースの配置場所を統一することもできます。
リソース名にPrefix/Suffixをつける
kustomization.yamlで指定されているリソースに関して、統一したPrefix/Suffixを付与することができます。
sampleコードはこちら
namePrefix: hoge-
nameSuffix: -fuga
resources:
- ../../base
$ kustomize build overlays/production/
apiVersion: apps/v1
kind: Deployment
metadata:
name: hoge-sample-deployment-fuga
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.19.0
name: nginx
ports:
- containerPort: 80
ファイルを元にしたConfigMap/Secretの生成
ConfigMapの中身はなんらかの設定ファイルだったり環境変数が入ったりします。
それらをConfigMapのマニフェストファイルに入れていると、編集しづらいです。
また、ConfigMapのリソース名は中身のデータを変更したとしても名前は変わりません。
そのため、そのConfigMapに依存しているDeploymentなどの更新にも気を使わないといけません。
それらの解決のために configMapGenerator
を使用します。
sampleコードはこちら
resources:
- ../../base
configMapGenerator:
- name: hoge-files
files:
- files/hoge.txt
- name: hoge-envs
envs:
- files/hoge.env
$ kustomize build overlays/production/
apiVersion: v1
data:
hoge: fuga
kind: ConfigMap
metadata:
name: hoge-envs-5hkfff6687
---
apiVersion: v1
data:
hoge.txt: |
hoge!!
kind: ConfigMap
metadata:
name: hoge-files-2bmb5dcchd
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- envFrom:
- configMapRef:
name: hoge-envs-5hkfff6687
image: nginx:1.19.0
name: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /test
name: hoge-config
volumes:
- configMap:
name: hoge-files-2bmb5dcchd
name: hoge-config
ご覧のように、configMapGenerator
で指定したファイルやenvファイルを元にConfigMapが生成されています。
また、リソース名の末尾にハッシュ値がついています。
これはConfigMap内のデータが変更されるたびに変更されるハッシュ値です。
またこの名前は自動的にDeploymentで指定しているConfigMapの名前のところも書き換えてくれます。(上記のkustomize build
実行結果参照)
このようにすることで、Deploymentの参照するConfigMapが変わりますので自動でPodが再生成されますし、
ロールバックする際も一つ前のConfigMapはそのまま残っているので簡単です。
なお、この末尾ハッシュ値が不要な場合は、kustomization.yamlで以下のように記述すれば末尾につかなくなります。
generatorOptions:
disableNameSuffixHash: true
ここまでConfigMapの話をしましたが、Secretも同様に secretGenerator
というものがあります。
使い方はConfigMapと同じです。
カスタムリソースで参照しているConfigMapの名前も自動更新させる
configMapGeneratorの項目で
またこの名前は自動的にDeploymentで指定しているConfigMapの名前のところも書き換えてくれます。
という話をしました。
これはKubernetesがデフォルトで用意しているリソースの話で、カスタムリソースでは対応していません。
けど安心してください。設定をすれば可能になります。
sampleコードはこちら
apiVersion: v1
kind: Hoge
metadata:
name: hoge
spec:
configMap:
name: hoge-envs
nameReference:
- kind: ConfigMap
version: v1
fieldSpecs:
- path: spec/configMap/name
kind: Hoge
apiVersion: v1
data:
hoge: fuga
kind: ConfigMap
metadata:
name: hoge-envs-5hkfff6687
---
apiVersion: v1
kind: Hoge
metadata:
name: hoge
spec:
configMap:
name: hoge-envs-5hkfff6687
nameReference
を使用するところで、カスタムリソースでもリソース名に関してKustomizeに情報を伝えることができます。
このようにしておくと、namePrefix
で指定したPrefixもカスタムリソースの方に反映されます。
外部のマニフェストを参照する
Kubernetesを運用していると、自分たちで作るマニフェスト以外に
外部で提供しているマニフェストを使用することがあると思います。
例えばMetrics ServerはHPAなどに使用されるため、導入している人は多いのではないでしょうか。
EKSのMetrics Serverインストール方法を見てみると・・・
$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
こんな感じでApplyに外部のマニフェストを参照できます。
ただこれを素直にやると、Kubernetesクラスタ構築時に手動でやる手順が増えてしまいます。
またこの外部のマニフェストの内容を環境ごとに違う設定にしたい!っていう要望もあると思います。
そんなときにもKustomizeは便利に使えます。
sampleコードはこちら
今回例に挙げたMetrics Serverは公式でkustomization.yamlを公開しています。
これを利用させてもらうと・・・
resources:
- https://github.com/kubernetes-sigs/metrics-server/manifests/release?ref=v0.4.4
これで kustomize build
をすれば、GitHubに配置されているkustomization.yamlを参照し、マニフェストが生成されます。
ちなみに kustomization.yamlが提供されていない場合は、直接Yamlを指定することもできます。
resources:
- https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.4/components.yaml
外部マニフェストの一部を変更したい場合は、ここでご紹介した「環境ごとにマニフェストの要素を書き換える」などの機能を使って実現します。