はじめに
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)があり、どのようにマージするかを制御することもできます。
また、このパッチ方法はKustomizeでもサポートされており、一部の命令文(パッチフォーマット)はKustomizeのパッチファイルの中でも利用することができます。
Server Side Apply
先ほど載せたページに記載されているように、Strategic Merge Patchを使うClient-side Applyに代わって、現在ではServer-side Applyが新しい方法として推奨されています。
また、下記の記事では、"Old patch format"とStrategic Merge Patchが呼ばれており、いくつかバグもあるみたいです。
Kustomizeが対応しているパッチフォーマット
Server-side Applyが新しい方法として推奨されているので、Kustomizeでサポートされているパッチフォーマットを紹介します。
Kustomizeがサポートしているフォーマットは下記の通りです。
replace
delete
merge
具体的にKustomizeがサポートしているフォーマットが書かれているドキュメントは見つかりませんでしたが、下記のIssueとコードを見た感じだと、
replace
、delete
、merge
だと思います。
しかし、merge Directiveに書かれているとおり、merge
に関してはパッチファイルで使われるフォーマットではなさそうです。(実際に試してみましたが、挙動が変わるパターンが見つからなかったので、今回は紹介しないことにします)
replace
replace
は、その名の通り要素をマージする代わりに置き換えます。
$patch: replace
試してみる
Kustomizeを使って試してみます。
用意するファイル(kustomization.yaml
, deployment.yaml
, replace.yaml
)は下記の通りです。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patchesStrategicMerge:
- replace.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
ver: 1.0.0
spec:
containers:
- name: nginx
image: nginx:latest
- name: redis
image: redis:latest
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
metadata:
$patch: replace # 下の階層が置換対象
labels:
app: myapp
ver: 2.0.0
spec:
containers:
- name: busybox
image: busybox:latest
- $patch: replace # リストが置換対象
ビルドしてみます。
kustomize build
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels: # labelsの中の要素が置換
app: myapp
ver: 2.0.0
spec:
containers:
- image: busybox:latest # リストが置換
name: busybox
delete
delete
は要素の削除をします。
$patch: delete
試してみる
Kustomizeを使って試してみます。
用意するファイル(kustomization.yaml
, deployment.yaml
, delete.yaml
)は下記の通りです。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patchesStrategicMerge:
- delete.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
strategy:
type: Recreat
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx:latest
- name: redis
image: redis:latest
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
strategy:
$patch: delete # strategyを削除
template:
spec:
containers:
- name: busybox
image: busybox:latest
- $patch: delete # nginxコンテナを削除
name: nginx
ビルドしてみます。
kustomize build
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
# strategyが削除されている
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
# nginxコンテナが削除され、busyboxコンテナがマージ
- image: busybox:latest
name: busybox
- image: redis:latest
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