immutable: true 为什么能减轻 apiserver 压力?它到底锁了什么?删了重建会怎样?这篇改了又改、删了又建,再用 apiserver 的 /metrics 数 watch 连接,看到差别。
改 data:退出码 1;The ConfigMap "fixed" is invalid: data: Forbidden: field is immutable when `immutable` is set
新增一个键:退出码 1;The ConfigMap "fixed" is invalid: data: Forbidden: field is immutable when `immutable` is set
把 immutable 改回 false:退出码 1;The ConfigMap "fixed" is invalid: immutable: Forbidden: field is immutable when `immutable` is set
改 labels/annotations:退出码 0;configmap/fixed patched(元数据仍可改)
可变的 ConfigMap 补上 immutable: true:退出码 0;configmap/mutable patched(可以单向锁定)
锁定之后再改 data:退出码 1给 ConfigMap 加 immutable: true 后,改 data 返回 Forbidden: field is immutable when `immutable` is set,新增键同样被拒,把 immutable 改回 false 也被拒;但 labels、annotations 这些元数据仍可修改。可变的 ConfigMap 可以随时补上 immutable: true,方向只能是 false → true。
初始:/f/level='info'(immutable);/m/level='info'(可变)
删除重建 immutable 的 fixed(值 debug),同时 patch 可变的 mutable 为 debug:可变的那个 87 秒后 /m/level=debug
等了 100 秒:/f/level='info'(immutable 的 ConfigMap 被删后重建,挂载的文件依然是旧值);/m/level='debug'Pod 挂着可变的 mutable 和 immutable 的 fixed。把 fixed 删掉重建成新值 debug,同时 patch mutable:mutable 在 87 秒后 /m/level 变 debug;等了 100 秒,/f/level 仍是 info——kubelet 把 immutable 对象视为不会变,不再同步,新建的同名对象也不会替换运行中的 Pod 已挂载的内容。要用新值只能换名字并滚动更新 Pod。
基线:按名字 watch 单个 ConfigMap 的长连接数(apiserver_longrunning_requests,verb=WATCH、scope=resource) 16 可变的 20 个 ConfigMap + 20 个 Pod(1 秒全部 Running):按名字 watch ConfigMap 的连接数 16 → 36(增加 20) immutable的 20 个 ConfigMap + 20 个 Pod(1 秒全部 Running):按名字 watch ConfigMap 的连接数 14 → 16(增加 2) 差别:可变 +20,immutable +2
kubelet 对可变的 ConfigMap 为每个被挂载的对象保持一个按名字的 watch。20 个 Pod 各挂一个自己的 ConfigMap:可变版本让 apiserver_longrunning_requests{verb="WATCH",resource="configmaps",scope="resource"} 从 16 增加到 36(+20);immutable 版本从 14 增加到 16(+2)。那 +2 应该是新命名空间里本来就有的可变对象(比如 kube-root-ca.crt),我没有逐个确认。在节点和 Pod 很多的集群里,这是 apiserver 的压力来源之一。