PUT/Patch都可以对资源进行操作。
PUT对资源进行完整内容的修改,Patch可以对资源进行部分修改。
1.Patch类型
- JSONPatchType
- MergePatchType
- StrategicMergePatch
2.测试对象
创建deploy,下面的Patch操作以此为例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
tolerations:
- effect: NoSchedule
key: abc
value: xyz
deloy包含:
- 2个pod;
- 每个pod含1个container:nginx;
- 带1个toleration;
# kubectl get deploy,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/demo 2/2 2 2 11s
NAME READY STATUS RESTARTS AGE
pod/demo-7ff49f4cdb-d9jpc 1/1 Running 0 11s
pod/demo-7ff49f4cdb-t6lsl 1/1 Running 0 11s
3.JSONPatch:
通过client.Patch()进行JSONPatch,修改deploy的replicas=3:
var replicaPatchData = `[{"op": "replace", "path": "/spec/replicas", "value": 3}]`
ctx := context.Background()
result, err := client.AppsV1().Deployments("default").
Patch(ctx, "demo", types.JSONPatchType, []byte(replicaPatchData), metav1.PatchOptions{})
可以看到,JSONPatch的body中需要指明:
- op: 操作,比如replace/add/copy等等;
- path: 操作的目标,这里是json的路径节点;
- value: 新值;
JSONPatch由于要详细指明路径和操作符,使用较为繁琐。
4.MergePatch
通过client.Patch()进行MergePatch,修改deploy的containers:
var containerPatchData = `{"spec": {"template": {"spec": {"containers": [{"name": "redis", "image": "redis"}]}}}}`
ctx := context.Background()
result, err := client.AppsV1().Deployments("default").
Patch(ctx, "demo", types.MergePatchType, []byte(containerPatchData), metav1.PatchOptions{})
修改结束后,pod中仍然仅有1个container,但其镜像由nginx被更新为redis;
可以看到,对于MergePath中的body中指明要修改的字段,其内容被完整替换。
MergePatch的特点:
- 无法追加数组,因为它会直接替换掉原数组内容;
- 若将value=nil,则其语义=将该项删除;
5.StrategicMergePatch
这是最易于client使用的Patch类型。
1)更新containers
通过client.Patch()进行StrategicMergePatch,修改deloy的containers:
var containerPatchData = `{"spec": {"template": {"spec": {"containers": [{"name": "redis", "image": "redis"}]}}}}`
ctx := context.Background()
result, err := client.AppsV1().Deployments("default").
Patch(ctx, "demo", types.StrategicMergePatchType, []byte(containerPatchData), metav1.PatchOptions{})
修改结束后,pod中有2个container,新增了一个redis的container。
2)更新tolerations
通过client.Patch()进行StrategicMergePatch,修改deploy的tolerations:
var tolerationPathData = `{"spec": {"template": {"spec": {"tolerations": [{"effect": "NoSchedule", "key": "hij", "value": "opr"}]}}}}`
ctx := context.Background()
result, err := client.AppsV1().Deployments("default").
Patch(ctx, "demo", types.StrategicMergePatchType, []byte(tolerationPathData), metav1.PatchOptions{})
修改结束后,deploy中仅有1个tolerations,源toleration被替换为新的toleration;
3)更新原理
从上面可以看到,对于delopy中的containers和tolerations,虽然都是slice,但是:
- containers的StrategicMergePatch进行了slice元素的新增;
- tolerations的StrategicMergePatch进行了slice的整个替换;
StragegicMergePatch对字段的内容,是Merge还是replace,取决于字段的定义:
// PodSpec is a description of a pod.
type PodSpec struct {
....
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=containers"`
...
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
}
- Containers字段,patchStrategy=merge,即进行元素的新增;
- Tolerations字段,未指定patchStragegy字段,默认patchStrategy=replace,即进行元素的替换;
5.CRD类型的Patch
对于CRD类型,不支持StrategicMergePatch,即只能使用JSONPatch或MergePatch。
参考
1.https://kubernetes.io/zh/docs/tasks/manage-kubernetes-objects...
2.https://erosb.github.io/post/json-patch-vs-merge-patch/
3.https://datatracker.ietf.org/doc/html/rfc7386#section-1
4.更新的语义:https://www.cnblogs.com/FengZeng666/p/15128060.html
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。