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