bigywater.tech
Kubernetes · 15

Server-Side Apply:字段所有权和冲突

kubectl apply --server-side 和老的 client-side apply 最大的不同是:服务端记录“每个字段是谁写的”。这篇用两个管理者争同一个字段,把冲突、抢占、共同拥有和删除的规则都跑了一遍,再看 kubectl scale 这种 Update 是怎么悄悄抢走 replicas 的。

1 conflict
team-b 申请 team-a 已拥有的 shared 字段时的结果,对象一个字节都没变
team-a(Apply)+team-b(Apply)
值相同之后 shared 字段的所有者
kubectl(Update, scale)
kubectl scale 之后 spec.replicas 的所有者,deployer 不再拥有它

冲突

实测 · 本机执行输出
  team-a 申请 {a: 1, shared: val-x}:退出码 0;configmap/cfg serverside-applied
      data={"a":"1","shared":"val-x"};字段所有者:a→team-a(Apply); shared→team-a(Apply)
  team-b 申请 {b: 2, shared: val-y}:退出码 1;
    error: Apply failed with 1 conflict: conflict with "team-a": .data.shared  (后面还有 11 行解决办法提示:--force-conflicts / 删掉这些字段 / 改成与现值一致来共同拥有)
      之后 data={"a":"1","shared":"val-x"};字段所有者:a→team-a(Apply); shared→team-a(Apply)

kubectl apply --server-side --field-manager=team-a 之后,managedFields 里 a 和 shared 都归 team-a。team-b 申请 {b: 2, shared: val-y} 得到 Apply failed with 1 conflict: conflict with "team-a": .data.shared,整个申请被拒绝,b 也没写进去。冲突的条件是:同一个字段、值不同、管理者不同。

抢占与共同拥有

实测 · 本机执行输出
  team-b 加 --force-conflicts:退出码 0;configmap/cfg serverside-applied
      data={"a":"1","b":"2","shared":"val-y"};字段所有者:a→team-a(Apply); b→team-b(Apply); shared→team-b(Apply)
  team-a 再按原样申请:退出码 1;error: Apply failed with 1 conflict: conflict with "team-b": .data.shared | Please review the fields above--they currently have other managers. Here | are the ways you can resolve this warning:
  team-a 改成 shared: val-y(和现值相同)再申请:退出码 0;configmap/cfg serverside-applied
      data={"a":"1","b":"2","shared":"val-y"};字段所有者:a→team-a(Apply); b→team-b(Apply); shared→team-a(Apply)+team-b(Apply)

--force-conflicts 让 team-b 抢走 shared(值变成 val-y),被抢的 team-a 按原样再申请就会反过来冲突。解决冲突还有第三种办法:把自己申请里的值改成和现值一样(val-y),不但不冲突,shared 的所有者还变成 team-a(Apply)+team-b(Apply)。

删除字段

实测 · 本机执行输出
  team-a 的申请里去掉 shared:退出码 0;configmap/cfg serverside-applied
      data={"a":"1","b":"2","shared":"val-y"};字段所有者:a→team-a(Apply); b→team-b(Apply); shared→team-b(Apply)
  team-a 的申请里连 a 也去掉:退出码 0;configmap/cfg serverside-applied
      data={"b":"2","shared":"val-y"};字段所有者:b→team-b(Apply); shared→team-b(Apply)
  team-b 的申请也清空:退出码 0;configmap/cfg serverside-applied
      data=;字段所有者:

申请就是“我期望自己负责的字段是这样”。共同拥有 shared 时 team-a 不再写它,字段还在(team-b 仍拥有);team-a 不再写 a,a 就被删除了;team-b 把申请清空,剩下的字段也跟着删掉。client-side apply 靠 last-applied 注解做到这件事,server-side apply 靠的是字段所有权。

Update 与 Apply

实测 · 本机执行输出
  deployer 申请 replicas: 1:deployment.apps/web serverside-applied
  kubectl scale 到 3:deployment.apps/web scaled
    managedFields:manager=deployer operation=Apply subresource=- 拥有 spec 下的 ['selector', 'template']
    managedFields:manager=kubectl operation=Update subresource=scale 拥有 spec 下的 ['replicas']
    managedFields:manager=kube-controller-manager operation=Update subresource=status 拥有 spec 下的 []
  deployer 再按 replicas: 1 申请:退出码 1;error: Apply failed with 1 conflict: conflict with "kubectl" with subresource "scale" using apps/v1: .spec.replicas | Please review the fields above--they currently have other managers. Here | are the ways you can resolve this warning:
  deployer 改成 replicas: 3(与现值相同)申请:退出码 0;deployment.apps/web serverside-applied

字段所有权不只属于 Apply:kubectl scale 是 Update,它改完之后 spec.replicas 归 kubectl(subresource=scale)所有,deployer 手里只剩 selector 和 template。deployer 再按 replicas: 1 申请就会冲突。典型场景:HPA 或有人手动 scale 了 Deployment,而 manifest 里还写着 replicas——要么去掉这个字段,要么用 --force-conflicts 明确夺回。

分步演示

字段所有权
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0);所有管理者用 kubectl apply --server-side --field-manager=<名字> 模拟,所有者信息来自 kubectl get --show-managed-fields -o json;对象是 k9 命名空间里的 ConfigMap cfg 和 Deployment web(busybox:1.36);测试值用 val-x / val-y(YAML 里未加引号的 y 会被 kubectl 当成布尔值 true,实验时踩到过);每种情形各一次
    • 没有验证:Apply 对列表(map 型与 atomic 型)的所有权规则;转移所有权(把 Update 管理者改成 Apply 管理者)的迁移流程;冲突时 kubectl 的 --force-conflicts 对 HPA 等控制器的后果;managedFields 的大小对 etcd 的开销;CRD 里 x-kubernetes-list-type 对合并的影响
    京ICP备2026067502号-1京公网安备11010502063487号