为什么 kubectl apply 能删掉你从 YAML 里去掉的字段,却不动别人手工加的字段?靠的是 metadata.annotations 里的 last-applied-configuration。这篇把三方合并的每一个输入都打印出来,再看它的几个坑:没有注解时的行为、server-side 的区别,以及大对象 apply 会撞上的注解上限。
第一次 apply {a: 1, b: 2}:configmap/cfg created
last-applied 注解里的 data:{'a': '1', 'b': '2'};集群里:{'a': '1', 'b': '2'}
有人手工 patch 了 {c: 3, a: hand-edited} 之后:集群里 {'a': 'hand-edited', 'b': '2', 'c': '3'};last-applied 仍是 {'a': '1', 'b': '2'}
再 apply {a: 10}(去掉了 b):configmap/cfg configured
结果:集群里 {'a': '10', 'c': '3'};last-applied 现在是 {'a': '10'}
解读:a 被改成 10(新的赢);b 在上次 apply 里有、这次没有 → 被删除;c 不在任何一次 apply 里 → 保留client-side apply 比较三样东西:上次 apply 的配置(存在 kubectl.kubernetes.io/last-applied-configuration 注解里)、这次的 manifest、集群里现在的对象。实验里第一次 apply {a: 1, b: 2},有人手工 patch 加了 c: 3 并改了 a,再 apply {a: 10}:a 以这次的为准变成 10;b 在上次 apply 里有、这次没有,被删除;c 从没出现在任何一次 apply 里,保留。
kubectl create 出来的 made:last-applied=None
去掉 k2 再 apply:退出码 0;configmap/made configured | Warning: resource configmaps/made is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be
结果:集群里 {'k2': '2', 'x': '1'}(k2 没有被删,因为没有“上次”可比);last-applied 现在是 {'x': '1'}kubectl create 出来的对象没有这个注解(除非加 --save-config)。第一次 apply 时 kubectl 提示 missing the kubectl.kubernetes.io/last-applied-configuration annotation,因为没有“上次”可比,去掉的字段 k2 没有被删,但这次 apply 会把注解补上。所以先 create 再 apply,想删的字段要等第二次 apply 才删得掉。
server-side apply:configmap/ss serverside-applied;last-applied 注解:None
--server-side 创建的对象没有 last-applied 注解,字段归属改由 managedFields 记录(上一篇的内容),也不再有“上次配置”这个概念。
kubectl create 一个 data 约 270000 字节的 ConfigMap:退出码 0;configmap/big created kubectl apply 同样大小:退出码 1;The ConfigMap "big2" is invalid: metadata.annotations: Too long: may not be more than 262144 bytes kubectl apply --server-side 同样大小:退出码 0;configmap/big3 serverside-applied
last-applied 把整份配置又存了一遍到注解里,而一个对象的所有注解加起来不能超过 262144 字节。data 约 270000 字节的 ConfigMap 用 kubectl create 没问题,用 kubectl apply 就报 metadata.annotations: Too long: may not be more than 262144 bytes;--server-side 没有这个问题。大 ConfigMap、嵌入大段配置的 CRD 是最常撞上的地方。