bigywater.tech
Kubernetes · 62

ConfigMap 更新:挂载的文件多久变,环境变量不变

改了 ConfigMap,容器里多久能看到?环境变量会跟着变吗?更新是原子的吗?把 ConfigMap 删了会怎样?这篇在真集群里改三次、测三次延迟,读符号链接,重启容器,逐个回答。

60~86 秒
改 ConfigMap 后挂载的文件在容器里更新所需的时间
环境变量不变
无论等多久,只有容器重启才会取新值
..data
更新靠切换这个符号链接,而不是改文件

文件会变,环境变量不会

实测 · 本机执行输出
  初始:环境变量 LEVEL='v1';文件 /etc/cfg/level='v1'
  连续改 3 次 ConfigMap(v2 → v3 → v4),从 apply 到容器里读到新内容的延迟(秒):[60.0, 66.7, 76.0]
  此时环境变量 LEVEL='v1'(进程启动时就固定了,之后不会再变);文件 /etc/cfg/level='v4'

Pod 里同时用 env.valueFrom.configMapKeyRef 和挂载。连续改 3 次 ConfigMap,挂载的文件分别在 60.0、66.7、76.0 秒后才在容器里读到新值(另一次测到 86 秒)——kubelet 靠周期同步,不是 watch 到变化马上写。环境变量始终是 v1:它在容器启动时一次性注入,之后无论怎么改 ConfigMap 都不会变。

原子切换靠 ..data

实测 · 本机执行输出
  更新前:
    ..data -> ..2026_10_10_14_43_46.3905505594
    level -> ..data/level
    ..2026_10_10_14_43_46.3905505594
  更新后(86 秒):
    ..data -> ..2026_10_10_14_45_14.1016284082
    level -> ..data/level
    ..2026_10_10_14_45_14.1016284082
  旧的时间戳目录是否还在:False

挂载目录里每个键是 level -> ..data/level 的符号链接,..data 再指向一个带时间戳的目录。更新时 kubelet 先把完整的新目录写好,再把 ..data 一次性改指向新目录,最后删掉旧目录:读文件的进程不会读到“一半新一半旧”。这也是 subPath 挂载不更新的根源(下一篇)。

环境变量要等容器重启

实测 · 本机执行输出
  现在 ConfigMap 里 level='v5',容器环境变量 LEVEL='v1'
  用 crictl 停掉容器、kubelet 重启它(restartCount=1,Pod uid 没变:True)后:LEVEL='v5'(重启时重新读 ConfigMap)

ConfigMap 已经是 v5,环境变量还是 v1。用 crictl 停掉容器,kubelet 重启它(restartCount=1,Pod uid 没变),新容器里 LEVEL 就是 v5。所以改 ConfigMap 想让环境变量生效,重启容器就够,不一定要重建 Pod;常见做法是 kubectl rollout restart。

删掉 ConfigMap

实测 · 本机执行输出
  删除 ConfigMap 后 5 秒:Pod phase=Running;文件 /etc/cfg/level='v5'
  100 秒后:Pod phase=Running;文件 /etc/cfg/level='v5'(kubelet 同步失败只是产生 FailedMount 事件,不会清掉文件)
    事件里的 FailedMount:['FailedMount: MountVolume.SetUp failed for volume "cfg" : configmap "cfg" not found']

删除 ConfigMap 之后,运行中的 Pod 仍是 Running,/etc/cfg/level 5 秒后和 100 秒后都还是 v5:kubelet 同步失败只产生一条 FailedMount: … configmap "cfg" not found 事件,不会把已有文件清掉。但此时新建的 Pod 没法挂载它,会卡在 ContainerCreating。

分步演示

ConfigMap 更新
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0);延迟是每 0.5 秒 kubectl exec 读一次文件得到的相对 apply 的时间;kubelet 默认同步周期约 1 分钟加缓存延迟,所以延迟在 60~90 秒间波动;容器用 crictl 在节点上停止来触发 kubelet 重启;每种情形各一次(第一节连测 3 次)
    • 没有验证:kubelet 配置 configMapAndSecretChangeDetectionStrategy 不同取值(Watch / Cache / Get)对延迟的影响;syncFrequency 参数调小之后的延迟;Secret 挂载是否同样 60~90 秒(同一机制,但本文没有单独测);immutable ConfigMap(见后面一篇);二进制数据 binaryData;应用用 inotify 监听 ..data 的行为
    京ICP备2026067502号-1京公网安备11010502063487号