主题
K8s 集群时间同步故障:apparmor 拦截 chronyd 导致节点时间漂移
结论:K8s 节点时间停在过去(kubelet 证书失效、kubectl exec 报 Unauthorized)时,根因往往是宿主机 apparmor 拦截了容器内 chronyd。删除
/etc/apparmor.d/usr.sbin.chronyd并重启 apparmor 与容器运行时即可恢复。本案例最终 9 台节点时统指标全部达标:软件同步单点精度 ≤40μs(指标 ≤1ms),全系统时统偏差 35μs(指标 ≤10ms)。
适用范围与环境
- 集群:master-1(麒麟 V10 ARM64,NTP 源,chronyd 监听 123+323)+ 9 台 computing(Ubuntu x86)
- 时间同步链路:chrony DaemonSet(hostNetwork)作为 NTP 源 → 各节点 timesyncd/chrony 同步
- 故障节点:computing-1(172.16.11.14)
- 现象链:节点时间停在 2023 → kubelet 证书过期 →
kubectl exec报 Unauthorized → 时间同步持续超标(-1.8ms)
排障步骤
1. 现象确认
bash
date # 发现系统时间停在 2023
kubectl exec -it <pod> -- bash # 报 Unauthorized(kubelet 证书因时间错误失效)
timedatectl status # NTP service: n/a2. 手动校正时间破局
bash
date -s "2026-08-25 15:00:00" # 先手动把时间拉回,让 kubelet 证书恢复有效
systemctl restart kubelet # 再重启 kubelet时间恢复后 kubectl exec 即恢复正常——这是第一步破局,但没有解决根因,时间会继续漂移。
3. 排查时间同步链路
bash
# 确认 NTP 源可达(chronyd 即 123 端口,不要被"没用 123"误导)
ss -ulnp | grep -E ":123|:323" # master-1 上 chronyd 同时监听 123+323
# 单点精度测试(持续超标判定)
for i in 1 2 3 4 5; do ntpdate -q 172.16.11.11 2>/dev/null | grep offset; sleep 3; done
# 故障节点持续输出 -0.001817s(-1.8ms),远超 1ms 指标曾一度怀疑 NTP 客户端 timesyncd 二进制版本不匹配(此前从其他节点拷贝恢复)、bond 多播、交换机 PTP 转发等,均不是根因。
4. 根因定位:apparmor 拦截 chronyd
bash
dmesg | grep -i apparmor | tail -20 # 关键!看到 chronyd 相关 DENIED 记录
journalctl -k --no-pager | grep -i "denied" | tail -20apparmor 的 usr.sbin.chronyd profile 拦截了容器内 chronyd 的关键操作(写 /var/run/chrony、绑定端口等),表现为进程能启动、能部分工作,但时间同步静默失败——日志里没有明显报错,这是最迷惑人的地方。
5. 修复
bash
# 删除 chronyd 的 apparmor profile
sudo rm -f /etc/apparmor.d/usr.sbin.chronyd
sudo systemctl restart apparmor
# 重启容器运行时,使容器内 chrony 重新加载
sudo systemctl restart containerd # Containerd 运行时
# 或 sudo systemctl restart docker # Docker 运行时修复后单点 offset 回落到 0.000040s(40μs)。
原因与机制
- chrony 以容器(Pod)方式运行在节点上,Ubuntu 宿主机的 apparmor profile(
usr.sbin.chronyd)默认限制 chronyd 的写路径与端口操作 - apparmor 拦截是静默的:进程存活、部分功能正常,只有
dmesg里有DENIED记录,容器日志不一定有报错 - 时间漂移 → kubelet 证书失效 → API 鉴权失败的因果链,掩盖了真正的时间源问题
指标验证方法
指标 1:软件同步精度不低于 1ms(单点)
bash
# 每台节点连续 5 轮采样,取最差值
for i in 1 2 3 4 5; do ntpdate -q 172.16.11.11 2>/dev/null | grep offset | awk '{print $NF}'; sleep 3; done | sort | tail -1
# 输出 ≤ 0.001(1ms)即达标指标 2:信号级仿真全系统时统精度不低于 10ms(全系统)
bash
# 每台节点各测一轮 offset
ntpdate -q 172.16.11.11 2>/dev/null | grep offset
# 全系统偏差 = max(所有节点 offset) - min(所有节点 offset),≤ 0.01 即达标验证结果(已验证)
| 节点 | 修复前 offset | 修复后 offset |
|---|---|---|
| 1-9 台(含故障节点) | 故障节点 -1817μs ❌ | 全部 ≤40μs ✅ |
- 软件同步单点精度:9/9 台 ≤40μs,指标 ≤1ms,余量 25 倍
- 全系统时统偏差:max−min = 40−5 = 35μs,指标 ≤10ms,余量 285 倍
风险与边界
- 删除 apparmor profile 降低了宿主机对 chronyd 的强制访问控制,内网可信环境可接受;公网/多租户环境应改为编写更细的 apparmor profile 而非删除
- 手动
date -s只作破局,不能替代根因修复;时间大幅回拨会触发 kubelet 证书验证失败,务必随后重启 kubelet - 单点采样有波动,指标验证建议多轮采样取最差轮次
教训
容器内时间服务(chrony/NTP)异常时,第一步查宿主机安全机制:
bash
dmesg | grep -i apparmor | tail -20
journalctl -k --no-pager | grep -i denied | tail -20有 DENIED 即 apparmor/SELinux/seccomp 在拦截。其他节点正常、单节点异常时,优先对比宿主机层差异(包来源、apparmor 状态、内核参数),而不是在网络层反复排查。