PUT/Patch都能够对资源进行操作。

PUT对资源进行残缺内容的批改,Patch能够对资源进行局部批改。

1.Patch类型

  • JSONPatchType
  • MergePatchType
  • StrategicMergePatch

2.测试对象

创立deploy,上面的Patch操作以此为例:

apiVersion: apps/v1kind: Deploymentmetadata:  name: demospec:  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,podNAME                   READY   UP-TO-DATE   AVAILABLE   AGEdeployment.apps/demo   2/2     2            2           11sNAME                        READY   STATUS    RESTARTS   AGEpod/demo-7ff49f4cdb-d9jpc   1/1     Running   0          11spod/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