用 subPath 挂的 ConfigMap 文件,为什么怎么改都不更新?这篇把同一个 ConfigMap 分别整体挂载和 subPath 挂载,对比文件类型、mountinfo 的来源路径和重启后的行为,直接看到原因。
初始:/whole/app.conf='v1';/etc/app.conf='v1' 改成 v2:整体挂载的 /whole/app.conf 62 秒后变成 v2 再等 60 秒(总共 122 秒):/whole/app.conf='v2';/etc/app.conf='v1'(subPath 的文件一直是 v1)
把同一个 ConfigMap 整体挂到 /whole,又用 subPath: app.conf 把单个文件挂到 /etc/app.conf。把 app.conf 从 v1 改成 v2:整体挂载的 /whole/app.conf 在 62 秒后变成 v2(同步延迟在不同次运行里有 1~86 秒的差别,见上一篇);/etc/app.conf 即使等到 122 秒仍是 v1。
ls -la /whole:
lrwxrwxrwx 1 root root 31 Oct 10 14:57 ..data -> ..2026_10_10_14_57_45.338504384
lrwxrwxrwx 1 root root 15 Oct 10 14:56 app.conf -> ..data/app.conf
lrwxrwxrwx 1 root root 17 Oct 10 14:56 other.conf -> ..data/other.conf
ls -la /etc/app.conf:
-rw-r--r-- 0 root root 2 Oct 10 14:56 /etc/app.conf
mountinfo:挂载点 /whole;来源路径 …/volumes/kubernetes.io~configmap/cfg
mountinfo:挂载点 /etc/app.conf;来源路径 …/volumes/kubernetes.io~configmap/cfg/..2026_10_10_14_56_43.971564555/app.conf//deleted
节点上卷目录里的 ..data 现在指向:..2026_10_10_14_57_45.338504384;目录里 app.conf 的内容 'v2'/whole/app.conf 是指向 ..data/app.conf 的符号链接,更新靠切换 ..data;而 /etc/app.conf 是一个普通文件,它是 bind mount。mountinfo 里这个挂载的来源是 …/cfg/..2026_10_10_14_56_43.…/app.conf//deleted——启动时那个时间戳目录里的文件,更新后这个目录被 kubelet 删掉了,所以带 //deleted。bind mount 绑定的是当时的文件本身,不是路径,新内容写在新的目录里,它永远看不到。节点上的 ..data 此时已指向新目录,里面的 app.conf 是 v2。
容器重启后(restartCount=1,Pod 没重建):/etc/app.conf='v2'(新容器启动时从卷里重新取了 v2)
重启容器(Pod 不用重建)就够了:用 crictl 停掉容器,kubelet 重启后 restartCount=1,/etc/app.conf 变成 v2——新容器启动时重新做了 subPath 的绑定。实际操作里常用 kubectl rollout restart,或者干脆不用 subPath(把配置挂到独立目录再用 --config 指过去),或者借助 reloader 之类的外部控制器。
没挂卷时 /var 里有:['run', 'spool', 'www'] 把整个卷挂到 /var 之后 /var 里只剩:['app.conf', 'other.conf', 'run'](原来的内容被遮住) 用 subPath 挂单个文件到 /var/app.conf 后 /var 里有:['app.conf', 'run', 'spool', 'www'](原来的文件都在,多了 app.conf)
把整个卷挂到 /var,原来 /var 下的 spool、www 就被遮住了(只剩 app.conf、other.conf 和 run;run 应该是为 /var/run/secrets 的令牌挂载留下的);用 subPath 把单个文件挂到 /var/app.conf,原有的 run、spool、www 都还在——这是 subPath 存在的理由,代价就是不会更新。
两个 Pod 共用节点上的 hostPath /tmp/k57-shared,各自 subPathExpr=$(POD_NAME):节点上 ['w1/out.log=w1', 'w2/out.log=w2']
subPathExpr 可以用环境变量展开路径:两个 Pod 共用节点上的 hostPath /tmp/k57-shared,各自 subPathExpr: $(POD_NAME)(POD_NAME 由 downward API 注入),节点上得到 w1/out.log 和 w2/out.log,互不覆盖。