现场是这样的。K8s 里跑 CentOS 基础镜像,Dockerfile 里 COPY 了 /etc/localtime,运行时又挂 -v /etc/localtime:/etc/localtime:ro,容器内 date 还是 UTC,日志时间差八小时。

真正麻烦的地方在于,几个原因的现象几乎一样。镜像里没有 /usr/share/zoneinfo,COPY 进来的是软链,指不到目标文件;宿主机 /etc/localtime 本身是符号链接,挂进容器后被解析成空文件;应用只读 TZ 环境变量,根本不看 /etc/localtime。

先看容器内的时间与时区文件

kubectl exec -it app-0 -- date; kubectl exec -it app-0 -- ls -l /etc/localtime

然后挂真实文件而不是软链

volumeMounts 里挂 /usr/share/zoneinfo/Asia/Shanghai 到 /etc/localtime

同时注入 TZ 变量

env: [{name: TZ, value: Asia/Shanghai}]

等前面都确认过,再确认容器内时区缩写

kubectl exec -it app-0 -- date +%Z

排查用的命令都是临时敲的,没有写成脚本,事后才整理。

手上没有现成的复现脚本,就照着线上请求手工拼了一个。

恢复的判定其实很直接。容器内 date 输出 CST 且带 +0800,应用日志时间与宿主机 date 一致,Pod 重建后依然生效(配置写在 Deployment 里)。

容易忽略的是,挂软链是容器时区最常见的坑,要挂 zoneinfo 下的实体文件;只改运行时挂载不改镜像,换环境时还会再犯一次。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189