通过 patch 命令可以对集群中的资源进行部分更新,也就是以补丁 (Patch) 方式修改、更新某资源的字段,相对于 apply 命令来说,无需提供完整的资源文件,只需要提供更新的内容即可。
简介
支持如下的三种操作类型:
Strategic Patch
默认方式,会根据源码中资源对应字段中的patchMergeKey
标识。JSON Merge Patch
遵循 JSON Merge Patch RFC 7386 规范,根据提供期望更改的字段及其对应的值更新到目标中。JSON Patch
遵循 JSON Patch RFC 6902 规范,通过明确的指令表示具体的操作。
Strategic Patch
如上所述,具体 Patch 的策略由源码中资源对应字段标识,有如下三种策略:
replace
默认,可以显示指定,如果list
类型字段未设置则会替换掉整个列表。merge
将补丁中的中的元素合并到原list
中。retainKeys
仅保留 object 对象中指定的字段。
例如如下 PodSpec
中的 Containers
字段显式标识了为 merge
策略,也就是合并;而 Tolerations
字段则使用默认的 replace
策略。不同类型的资源可以从 Kubernetes API 或者 Github Swagger.json 中查看,例如 io.k8s.api.core.v1.PodSpec
。
type PodSpec struct {
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" ...`
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
}
其中 Containers 会采用 merge 策略,而 Key 为 name,也就意味着对应 name 的容器如果不存在则会新增,否则只是更新镜像信息。那么执行如下命令时会看到 Pod 中新增了一个 Container 实例。
----- 新增一个Deployment资源
# cat nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: patch-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: patch-demo-nginx
image: nginx
tolerations:
- effect: NoSchedule
key: dedicated
value: test-team
# kubectl apply -f nginx-deployment.yaml
----- 然后打一个Patch,可以查看输出
# cat patch-container.yaml
spec:
template:
spec:
containers:
- name: patch-demo
image: redis
# kubectl patch deployment patch-demo --patch "$(cat patch-containers.yaml)"
# kubectl get deployment patch-demo --output yaml
----- 源码中没有指定,则默认替换
# cat patch-tolerations.yaml
spec:
template:
spec:
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
# kubectl patch deployment patch-demo --patch "$(cat patch-tolerations.yaml)"
# kubectl get deployment patch-demo --output yaml
JSON Merge Patch
也就是遵循 JSON Merge Patch RFC 7386 规范,根据提供期望更改的字段及其对应的值更新到目标中,其规则如下:
- 提供 Patch 内容中包含目标不存在的字段则添加。
- 目标包含 Patch 中提供的字段,则替换该字段的值。
- Patch 中将目标中含有的字段设置为
null
则删除该字段。
如下是一个简单的示例。
{ |{ |{
"title": "Goodbye!", | "title": "Hello!", | "title": "Hello!", # 修改
"author": { | "author": { | "author": {
"givenName": "John", | | "givenName": "John"
"familyName": "Doe" | "familyName": null | # 删除
}, | }, | },
"tags": [ | "tags": [ | "tags": [ # 修改
"example", | "example" | "example"
"sample" | |
], | ], | ],
"content": "message" | | "content": "message",
| "phoneNumber": "1234" | "phoneNumber": "1234" # 新增
} |} |}
----->>>>> Patch ----->>>>> Result
使用 kubectl patch
更新时通过 --type merge
指定即可。
# kubectl patch deployment --type merge patch-demo --patch '
{
"spec": {
"replicas": 5
}
}'
JSON Patch
遵循 JSON Patch RFC 6902 规范,通过明确的指令表示具体的操作,在 op
字段中设置具体的操作,包含:
add
添加字段。remove
删除字段。replace
替换字段。move
删除指定字段的值,并将其添加到目标字段。copy
将指定字段的值复制到目标字段。test
测试字段的值是否等于给定值。
同样以如上的示例,转换为如下请求。
[
{"op": "replace", "path": "/title", "value": "Hello!"},
{"op": "remove", "path": "/author/familyName"},
{"op": "replace", "path": "/tags", "value": ["example"]},
{"op": "add", "path": "/phoneNumber", "value": "1234"}
]
在使用时通过 --type json
指定。