【Kubernetes】Strategic Merge Patchについてざっくり理解する
はじめに
Kubernetesで使われるStrategic Merge Patchについて、ざっくり理解していきます。
また、Strategic Merge Patchで使われる命令文の中からKustomizeでサポートされているものを紹介します。
Strategic Merge Patchとは
Strategic Merge PatchはKubernetesで使われているJSON merege patchをカスタマイズしたパッチ方法です。
JSON Merge Patchの場合、JSON Objectは全てマージされ、リストは全て置換されるようになっています。しかし、Kubernetesだと都合が悪い場合があるので、Strategic Merge Patchでは、Kubernetesのオブジェクトがいい感じにマージされるように制御されています。
このパッチ方法は、kubectl apply
、kubectl edit
、kubectl patch
で使われており、専用の命令文(directive)があり、どのようにマージするかを制御することもできます。
community/contributors/devel/sig-api-machinery/strategic-merge-patch.md at master · kubernetes/community
Kubernetes community content. Contribute to kubernetes/community development by creating an account on GitHub.
また、このパッチ方法はKustomizeでもサポートされており、一部の命令文(パッチフォーマット)はKustomizeのパッチファイルの中でも利用することができます。
patchesStrategicMerge
Patch resources using the strategic merge patch standard.
Server Side Apply
先ほど載せたページに記載されているように、Strategic Merge Patchを使うClient-side Applyに代わって、現在ではServer-side Applyが新しい方法として推奨されています。
また、下記の記事では、"Old patch format"とStrategic Merge Patchが呼ばれており、いくつかバグもあるみたいです。
Server Side Apply Is Great And You Should Be Using It
Server-side apply (SSA) has now been GA for a few releases, and I have found myself in a number of conversations, recommending that people / teams in various situations use it. So I’d like to write down some of those reasons. Obvious (and not-so-obvious) benefits of SSA A list of improvements / niceties you get from switching from various things to Server-side apply! Versus client-side-apply (that is, plain kubectl apply): The system gives you conflicts when you accidentally fight with another actor over the value of a field!
Kustomizeが対応しているパッチフォーマット
Server-side Applyが新しい方法として推奨されているので、Kustomizeでサポートされているパッチフォーマットを紹介します。
Kustomizeがサポートしているフォーマットは下記の通りです。
replace
delete
merge
具体的にKustomizeがサポートしているフォーマットが書かれているドキュメントは見つかりませんでしたが、下記のIssueとコードを見た感じだと、
replace
、delete
、merge
だと思います。
kyaml is not respecting `$patch replace|retainKeys` directives · Issue #2037 · kubernetes-sigs/kustomize
tree: . ├── base │ ├── kafka.yaml │ └── kustomization.yaml └── overlays ├── kustomization.yaml ├── output.yaml └── patch.yaml base content: # kustomization.yaml resources: - kafka.yaml # kafka.yaml...
kustomize/kyaml/yaml/merge2/smpdirective.go at master · kubernetes-sigs/kustomize
Customization of kubernetes YAML configurations. Contribute to kubernetes-sigs/kustomize development by creating an account on GitHub.
しかし、merge Directiveに書かれているとおり、merge
に関してはパッチファイルで使われるフォーマットではなさそうです。(実際に試してみましたが、挙動が変わるパターンが見つからなかったので、今回は紹介しないことにします)
replace
replace
は、その名の通り要素をマージする代わりに置き換えます。
1$patch: replace
試してみる
Kustomizeを使って試してみます。
用意するファイル(kustomization.yaml
, deployment.yaml
, replace.yaml
)は下記の通りです。
1apiVersion: kustomize.config.k8s.io/v1beta1
2kind: Kustomization
3
4resources:
5- deployment.yaml
6
7patchesStrategicMerge:
8- replace.yaml
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myapp
5spec:
6 replicas: 1
7 selector:
8 matchLabels:
9 app: myapp
10 template:
11 metadata:
12 labels:
13 app: myapp
14 ver: 1.0.0
15 spec:
16 containers:
17 - name: nginx
18 image: nginx:latest
19 - name: redis
20 image: redis:latest
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myapp
5spec:
6 template:
7 metadata:
8 $patch: replace # 下の階層が置換対象
9 labels:
10 app: myapp
11 ver: 2.0.0
12 spec:
13 containers:
14 - name: busybox
15 image: busybox:latest
16 - $patch: replace # リストが置換対象
ビルドしてみます。
1kustomize build
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myapp
5spec:
6 replicas: 1
7 selector:
8 matchLabels:
9 app: myapp
10 template:
11 metadata:
12 labels: # labelsの中の要素が置換
13 app: myapp
14 ver: 2.0.0
15 spec:
16 containers:
17 - image: busybox:latest # リストが置換
18 name: busybox
delete
delete
は要素の削除をします。
1$patch: delete
試してみる
Kustomizeを使って試してみます。
用意するファイル(kustomization.yaml
, deployment.yaml
, delete.yaml
)は下記の通りです。
1apiVersion: kustomize.config.k8s.io/v1beta1
2kind: Kustomization
3
4resources:
5- deployment.yaml
6
7patchesStrategicMerge:
8- delete.yaml
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myapp
5spec:
6 strategy:
7 type: Recreat
8 replicas: 1
9 selector:
10 matchLabels:
11 app: myapp
12 template:
13 metadata:
14 labels:
15 app: myapp
16 spec:
17 containers:
18 - name: nginx
19 image: nginx:latest
20 - name: redis
21 image: redis:latest
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myapp
5spec:
6 strategy:
7 $patch: delete # strategyを削除
8 template:
9 spec:
10 containers:
11 - name: busybox
12 image: busybox:latest
13 - $patch: delete # nginxコンテナを削除
14 name: nginx
ビルドしてみます。
1kustomize build
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: myapp
5spec:
6 # strategyが削除されている
7 replicas: 1
8 selector:
9 matchLabels:
10 app: myapp
11 template:
12 metadata:
13 labels:
14 app: myapp
15 spec:
16 containers:
17 # nginxコンテナが削除され、busyboxコンテナがマージ
18 - image: busybox:latest
19 name: busybox
20 - image: redis:latest
21 name: redis
最後に
Strategic Merge Patchに関しては、ドキュメントがあまり見当たらなかったため、もし謝っている箇所があれば教えていただけるとうれしいです。
参考
- community/strategic-merge-patch.md at master · kubernetes/community
- unknown field "setElementOrder/containers" & "setElementOrder/env" · Issue #2954 · kubernetes-sigs/kustomize
kustomize build
not honoring theretainKeys
patchStrategy · Issue #3981 · kubernetes-sigs/kustomize- kyaml is not respecting
$patch replace|retainKeys
directives · Issue #2037 · kubernetes-sigs/kustomize - kustomize/kyaml/yaml/merge2 at master · kubernetes-sigs/kustomize
- kubernetes - Kubectl patch $deleteFromPrimitiveList directive - Stack Overflow
- Server Side Apply Is Great And You Should Be Using It | Kubernetes
- patchesStrategicMerge | SIG CLI