K8s Patch

为什么要有 patch ?

K8s 使用乐观锁管理数据,当使用 update 更新资源对象的时候必须带上 resourceVersion ,这就需要先从 K8s 获取到最新的资源信息,修改字段后再提交给 K8s。如果 apiserver 发现版本比当前存的版本落后就会更新失败。patch 就没有这个问题,可以指定字段立即更新。

Patch 操作的 3 种类型

执行 kubectl patch 命令时 --type 共有三个可选值,strategic 为默认值,其余还有 jsonmerge

Parameter Value Merge Type
json JSON Patch, RFC 6902
merge JSON Merge Patch, RFC 7386
strategic Strategic Merge Patch

1. Strategic merge patch (不支持自定义资源)

strategic 是默认的 patch 类型,通过命令行操作比较简单:写一个 YAML 指明要更新的字段然后执行即可。例如更新一个 deployment: kubectl patch deploy patch-demo --patch-file patch-file.yaml。最终行为结果是 replace 还是 merge 取决于被更新字段对 patch 行为的默认定义。

spec:
  template:
    spec:
      containers:
      - name: patch-demo-ctr
        image: uhub.service.ucloud.cn/library/redis:2.8.8

比如 pod.spec.containers 的 patch 策略是 merge , patchMergeKey 为 name,上面这个 patch-file.yaml 提交后会针对 image name 为 patch-demo-ctr 的 container 项做合并。如果 patch-demo-ctr 的 container 不存在,则插入新的 container 到 containers List。Tolerations 字段没有 patchStrategy tag ,所以其默认 patch 策略是 replace,直接做替换。

type PodSpec struct {
  ...  
  Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`  
  Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name"
  ...
}

2. JSON Merge Patch

处理方式参照 RFC7386 ,大致思路就是:使用当前指定的字段替换原字段。比如下面这个 YAML ,将直接覆盖 containers 字段。

spec:
  template:
    spec:
      containers:
      - name: patch-demo-ctr-3
        image: gcr.io/google-samples/hello-app:2.0

如果想删除一个字段的话,指定 value 为 null 即可,比如删除 deployment 内 pod 的 hostIPC 字段(patch file 也可以是 JSON 格式)。

{"spec":{"template":{"spec":{"hostIPC":null}}}}

3. JSON Patch

处理方式参照 RFC6902,会按照指定的 JSON 表达规范来执行修改操作。

如下示例会针对 deployment 里的 pod 增加 hostIPC 字段为 true。

[{
    "op": "add",
    "path": "/spec/template/spec/hostIPC",
    "value": true
}]

对比与思考

patch 的三种方法各有优劣:

© 2022 - 2025 · Stay foolish · Theme Simpleness Powered by Hugo ·