【Kustomize】patchesJson6902の使い方と利用シーン
Kustomizeを使うとき、 patches
でファイルを指定してbaseファイルを部分的に変更することが多いと思う。しかし先日、 patches
ではなく patchesJson6902
という指定をしているファイルを見かけたので、どう使うのか調べてみた。
patchesJson6902とは
patchesJson6902は、名前の通りRFC6902に沿った方法でPatch処理を行うことができる。RFC6902ではJSON Patchについて定義されている。
Kustomizeは公式ドキュメントをたどりづらいが、Kubernetesのドキュメントの中に詳しい使い方が記載されている。 kubernetes.io
patchesStrategicMerge
と patchesJson6902
の違い
Kustomizeでは、patchを行う際に patchesStrategicMerge
と patchesJson6902
の2つの方式に対応している。 patch
フィールドは渡したファイルまたはPatchをもとに、どちらの方式かを自動で判定して適用してくれる。
この2つの方式がどう違うのかというと、 patchesStrategicMerge
はマージの挙動をKubernetesの設定ファイルに最適化されるように変更している。例えば、以下のようなdeployment.yamlがあるとする。
# base/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.1 ports: - containerPort: 80 - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 - name: nginx image: nginx:1.14.3 ports: - containerPort: 80 # base/kustomization.yaml resources: - deployment.yaml
overlaysを以下のようにする。
# overlays/test/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: template: spec: containers: - name: busybox image: busybox:1.33 ports: - containerPort: 80 # overlays/test/kustomization.yaml bases: - ../../base patchesStrategicMerge: - deployment.yaml
このとき、buildした結果は以下のようになる。overlaysで指定したコンテナが、 containers
に追加されていることがわかる。
$ kustomize build . apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: busybox:1.33 name: busybox ports: - containerPort: 80 - image: nginx:1.14.1 name: nginx ports: - containerPort: 80 - image: nginx:1.14.2 name: nginx ports: - containerPort: 80 - image: nginx:1.14.3 name: nginx ports: - containerPort: 80
一方で、これと同じことを patchesJson6902
で行おうとすると、overlaysを以下のようにしなければならない。
# overlays/test/kustomization.yaml bases: - ../../base patchesJson6902: - target: group: apps version: v1 kind: Deployment name: nginx-deployment patch: |- # patchの内容は別ファイルに指定しても良い - op: add path: /spec/template/spec/containers/0 value: {"image": "busibox:1.33", "name": "busybox", "ports": [{"containerPort": 80}]}
patch
内の path
でJSON pathを指定する必要があり、ここで配列のインデックス番号を指定したうえで、配列に入れる新たな要素を定義する必要がある。 patchesStrategicMerge
の場合と同じようにしてしまうと、 containers
が丸々入れ替わって busybox
のみになってしまう。
patchesJson6902
を使うべきシーン
逆に「配列の中の特定の一要素を入れ替えたい場合」は patchesJson6902
の方を使うべき。
# overlays/test/kustomization.yaml bases: - ../../base patchesJson6902: - target: group: apps version: v1 kind: Deployment name: nginx-deployment patch: |- - op: replace path: /spec/template/spec/containers/0 value: {"image": "busibox:1.33", "name": "busybox", "ports": [{"containerPort": 80}]}
op
を replace
に変更したことで、 containers
配列の0番目の要素のみを入れ替えることができる。結果は以下の通り。
$ kustomize build . apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: busibox:1.33 name: busybox ports: - containerPort: 80 - image: nginx:1.14.2 name: nginx ports: - containerPort: 80 - image: nginx:1.14.3 name: nginx ports: - containerPort: 80
これに対して patchesStrategicMerge
の場合、 $patch: replace
を指定することで containers
配列全体を入れ替えることはできるが、特定の要素を指定してそこだけ入れ替える機能はない。baseの containers
配列全体をoverlaysに書いてそこに新しい要素を加えるという方法はあるが、配列の要素が多い場合は非効率である。
各Patch方式の詳細な挙動は、以下が参考になる。
community/strategic-merge-patch.md at master · kubernetes/community · GitHub kustomize/inlinePatch.md at master · kubernetes-sigs/kustomize · GitHub