client-go MergePatch 或 StragegyMergePatch for map type 字段的合并逻辑是什么?
What is the merge logic of client-go MergePatch or StragegyMergePatch for map type field?
MergePatch 或 StragegyMergePatch 在修补地图类型字段(如标签)时做什么?
当我使用MergePatch 或StragegyMergePatch 时,如果我在yaml 文件中添加一些标签,然后将整个yaml 文件的数据传输到patch 方法,它可以工作。但是如果我从 yaml 文件中删除一些标签,然后打补丁,它就不起作用了。
我已经进行了进一步调查,很多事情都取决于您想在哪个 resource
上做什么。文档可能难以理解,所以我将在这个答案中对其进行更多扩展。
背景
您指的是 Merge Patch where you have example of merge patching (adding additional container) spec.template.spec.containers
. Below you have Notes on the strategic merge patch。
The patch you did in the preceding exercise is called a strategic merge patch. Notice that the patch did not replace the containers list. Instead it added a new Container to the list. In other words, the list in the patch was merged with the existing list. This is not always what happens when you use a strategic merge patch on a list. In some cases, the list is replaced, not merged.
With a strategic merge patch, a list is either replaced or merged depending on its patch strategy. The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code.
默认补丁策略可以在Kubernetes API documentation或Kubernetes源代码
中找到
关于修补 Deployments labels
,因为 apiVersion: apps/v1
这是不可能的。您可以在 Deployments - Label selector updates.
中找到确认信息
Note: In API version apps/v1, a Deployment's label selector is immutable after it gets created.
如果您在 apiVersion: apps/v1
中尝试 update
或 patch
,您将收到 field is immutable
错误。更改 labels/selectors
的唯一方法是重新部署整个 Deployment
.
但是,如果您要使用具有 apiVersion: extensions/v1beta1
的旧 Kubernetes 版本,则可以像 Github example 中那样对其进行修补。
请记住,您还可以使用更多 patching methods
,例如 JSON merge patch
或 merge patch using the retainKeys strategy
。
测试
基于Documentation Deployment Example.
您不能更改 apiVersion: apps/v1
中的 Deployment
标签,因此您也不能 patch
它。
$ kubectl apply -f nginx-second.yaml
The Deployment "nginx-deployment" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"nginx", "test":"test"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
在您提到的 Node Selector
的评论中,可以像 中那样进行修补。
在文档 Use a strategic merge patch to update a Deployment 中,您可以找到 2 个示例,container
其中 patchStrategy:"merge"
:
The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code. For example, the Containers field of PodSpec struct has a patchStrategy of merge:
type PodSpec struct {
...
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" ...`
和 tolerations
空 patchStrategy
字段的示例。
Notice that the tolerations list in the PodSpec was replaced, not merged. This is because the Tolerations field of PodSpec does not have a patchStrategy key in its field tag. So the strategic merge patch uses the default patch strategy, which is replace.
type PodSpec struct {
...
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
两个示例(包含容器和容差)都是列表,但不同之处在于当您使用合并时它会添加新的,但是当您要替换时,key
值必须相同。
补丁-tolerations.yaml
$ cat patch-tolerations.yaml
spec:
template:
spec:
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
test1: testvalue1
test2: testvalue2
test3: testvalue3
使用相同的键替换
$ kubectl get deploy patch-demo -o yaml | grep tolerations: -A 5
tolerations:
- effect: NoSchedule
key: dedicated
value: test-team
$ kubectl patch deployment patch-demo --patch "$(cat patch-tolerations.yaml)"
$ kubectl get deploy patch-demo -o yaml | grep tolerations: -A 5
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
它仅替换了具有相同 key
的值。如果您将 patch-tolerations.yaml
更改为
spec:
template:
spec:
tolerations:
- effect: NoSchedule
test1: testvalue1
test2: testvalue2
test3: testvalue3
你会得到一个错误:
$ kubectl patch deployment patch-demo --patch "$(cat patch-tolerations.yaml)"
The Deployment "patch-demo" is invalid: spec.template.spec.tolerations[0].operator: Invalid value: "": operator must be Exists when `key` is empty, which means "match all value
s and all keys"
StatefulSet 测试
正如您询问的标签,您可以在 statefulset
中更改它们。基于 Docs Creating a StatefulSet 中的示例以及一些附加注释 metadata.labels
.
$ kubectl get sts -oyaml | grep labels: -A 3
labels:
test: test
test1: test1
name: web
--
labels:
app: nginx
spec:
containers:
---
$ cat patch-sts.yaml
metadata:
labels:
run: runtest
app: apptest
$ cat patch-sts-template.yaml
spec:
template:
metadata:
labels:
app: nginx
app2: run
test: test
---
$ kubectl patch sts web --patch "$(cat patch-sts.yaml)"
statefulset.apps/web patched
$ kubectl patch sts web --patch "$(cat patch-sts-template.yaml)"
statefulset.apps/web patched
$ kubectl get sts -oyaml | grep labels: -A 5
labels:
app: apptest
run: runtest
test: test
test1: test1
name: web
--
labels:
app: nginx
app2: run
test: test
spec:
containers:
结论
您无法更改 Deployment labels
,因为这些字段是不可变的。
当你想要修补某些东西时,你必须检查哪个是默认的patchStrategy
。
The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code.
在merge
补丁中所有信息都是混合的,当使用replace
补丁时,新旧补丁对象必须具有相同的key
。
您可以使用几种补丁方法:
In other words, the list in the patch was merged with the existing list.
A strategic merge patch is different from a JSON merge patch. With a JSON merge patch, if you want to update a list, you have to specify the entire new list. And the new list completely replaces the existing list.
如果这没有回答您的问题,请说明您想要使用哪个版本、资源和您想要修补的内容来实现。
MergePatch 或 StragegyMergePatch 在修补地图类型字段(如标签)时做什么?
当我使用MergePatch 或StragegyMergePatch 时,如果我在yaml 文件中添加一些标签,然后将整个yaml 文件的数据传输到patch 方法,它可以工作。但是如果我从 yaml 文件中删除一些标签,然后打补丁,它就不起作用了。
我已经进行了进一步调查,很多事情都取决于您想在哪个 resource
上做什么。文档可能难以理解,所以我将在这个答案中对其进行更多扩展。
背景
您指的是 Merge Patch where you have example of merge patching (adding additional container) spec.template.spec.containers
. Below you have Notes on the strategic merge patch。
The patch you did in the preceding exercise is called a strategic merge patch. Notice that the patch did not replace the containers list. Instead it added a new Container to the list. In other words, the list in the patch was merged with the existing list. This is not always what happens when you use a strategic merge patch on a list. In some cases, the list is replaced, not merged.
With a strategic merge patch, a list is either replaced or merged depending on its patch strategy. The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code.
默认补丁策略可以在Kubernetes API documentation或Kubernetes源代码
中找到关于修补 Deployments labels
,因为 apiVersion: apps/v1
这是不可能的。您可以在 Deployments - Label selector updates.
Note: In API version apps/v1, a Deployment's label selector is immutable after it gets created.
如果您在 apiVersion: apps/v1
中尝试 update
或 patch
,您将收到 field is immutable
错误。更改 labels/selectors
的唯一方法是重新部署整个 Deployment
.
但是,如果您要使用具有 apiVersion: extensions/v1beta1
的旧 Kubernetes 版本,则可以像 Github example 中那样对其进行修补。
请记住,您还可以使用更多 patching methods
,例如 JSON merge patch
或 merge patch using the retainKeys strategy
。
测试
基于Documentation Deployment Example.
您不能更改 apiVersion: apps/v1
中的 Deployment
标签,因此您也不能 patch
它。
$ kubectl apply -f nginx-second.yaml
The Deployment "nginx-deployment" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"nginx", "test":"test"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
在您提到的 Node Selector
的评论中,可以像
在文档 Use a strategic merge patch to update a Deployment 中,您可以找到 2 个示例,container
其中 patchStrategy:"merge"
:
The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code. For example, the Containers field of PodSpec struct has a patchStrategy of merge:
type PodSpec struct {
...
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" ...`
和 tolerations
空 patchStrategy
字段的示例。
Notice that the tolerations list in the PodSpec was replaced, not merged. This is because the Tolerations field of PodSpec does not have a patchStrategy key in its field tag. So the strategic merge patch uses the default patch strategy, which is replace.
type PodSpec struct {
...
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
两个示例(包含容器和容差)都是列表,但不同之处在于当您使用合并时它会添加新的,但是当您要替换时,key
值必须相同。
补丁-tolerations.yaml
$ cat patch-tolerations.yaml
spec:
template:
spec:
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
test1: testvalue1
test2: testvalue2
test3: testvalue3
使用相同的键替换
$ kubectl get deploy patch-demo -o yaml | grep tolerations: -A 5
tolerations:
- effect: NoSchedule
key: dedicated
value: test-team
$ kubectl patch deployment patch-demo --patch "$(cat patch-tolerations.yaml)"
$ kubectl get deploy patch-demo -o yaml | grep tolerations: -A 5
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
它仅替换了具有相同 key
的值。如果您将 patch-tolerations.yaml
更改为
spec:
template:
spec:
tolerations:
- effect: NoSchedule
test1: testvalue1
test2: testvalue2
test3: testvalue3
你会得到一个错误:
$ kubectl patch deployment patch-demo --patch "$(cat patch-tolerations.yaml)"
The Deployment "patch-demo" is invalid: spec.template.spec.tolerations[0].operator: Invalid value: "": operator must be Exists when `key` is empty, which means "match all value
s and all keys"
StatefulSet 测试
正如您询问的标签,您可以在 statefulset
中更改它们。基于 Docs Creating a StatefulSet 中的示例以及一些附加注释 metadata.labels
.
$ kubectl get sts -oyaml | grep labels: -A 3
labels:
test: test
test1: test1
name: web
--
labels:
app: nginx
spec:
containers:
---
$ cat patch-sts.yaml
metadata:
labels:
run: runtest
app: apptest
$ cat patch-sts-template.yaml
spec:
template:
metadata:
labels:
app: nginx
app2: run
test: test
---
$ kubectl patch sts web --patch "$(cat patch-sts.yaml)"
statefulset.apps/web patched
$ kubectl patch sts web --patch "$(cat patch-sts-template.yaml)"
statefulset.apps/web patched
$ kubectl get sts -oyaml | grep labels: -A 5
labels:
app: apptest
run: runtest
test: test
test1: test1
name: web
--
labels:
app: nginx
app2: run
test: test
spec:
containers:
结论
您无法更改 Deployment labels
,因为这些字段是不可变的。
当你想要修补某些东西时,你必须检查哪个是默认的patchStrategy
。
The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code.
在merge
补丁中所有信息都是混合的,当使用replace
补丁时,新旧补丁对象必须具有相同的key
。
您可以使用几种补丁方法:
In other words, the list in the patch was merged with the existing list.
A strategic merge patch is different from a JSON merge patch. With a JSON merge patch, if you want to update a list, you have to specify the entire new list. And the new list completely replaces the existing list.
如果这没有回答您的问题,请说明您想要使用哪个版本、资源和您想要修补的内容来实现。