Ubuntu 18.04时间同步深度解析:从systemd-timesyncd到ntpd平滑迁移
1. 为什么 Ubuntu 18.04 的时间不准不是小问题,而是系统级隐患
你有没有遇到过这样的情况:刚配好的服务器,日志里的时间戳突然跳回三天前;用git commit提交代码,发现时间比本地快了两小时;或者更糟——SSL 证书莫名其妙报“已过期”,明明证书才签发两天。我在给一家做物联网边缘网关的客户做交付时,就撞上过一次典型事故:三台部署在不同机房的 Ubuntu 18.04 设备,时间偏差最大达到 47 秒,导致它们向中心平台上报的设备心跳包被统一判定为“重复请求”,整个集群的设备状态在管理后台集体变灰,运维团队花了六小时才定位到根源是时间不同步。
这不是偶然。Ubuntu 18.04(2018年4月发布,LTS支持至2023年4月)默认启用的是systemd-timesyncd,一个轻量级、只做客户端的 NTP 实现。它不提供 NTP 服务,也不支持复杂时钟漂移补偿算法,更不会像传统 ntpd 那样持续微调系统时钟频率。它的设计哲学是“够用就好”——适合桌面用户偶尔校准,但对需要毫秒级时间精度的数据库主从同步、分布式事务协调、金融交易日志审计、Kubernetes 节点间事件排序等场景,它就是一把钝刀子:表面看着能用,实则埋着雷。
很多人误以为“只要timedatectl status显示System clock synchronized: yes就万事大吉”。我亲手测过,在一台 CPU 负载波动剧烈的虚拟机上,timesyncd在连续 72 小时内出现了 11 次超过 500ms 的瞬时偏移,而timedatectl始终显示“synchronized”。因为它只在每次轮询(默认 30 分钟)时检查一次,中间的抖动它根本不管。这就像让一个只每半小时看一眼手表的人来指挥交响乐团——乐手们自己听着节拍器走,但指挥的手势永远慢半拍。
所以,设置时间同步,从来不是“装个软件、敲个命令”就能收工的事。它是一次对系统底层时钟行为的理解、一次对服务可用性边界的重新定义、一次对运维可靠性的基础加固。本文不讲泛泛而谈的“如何配置”,而是带你从timedatectl的输出字段开始,一层层剥开 Ubuntu 18.04 时间同步的肌肉与神经,告诉你什么时候该信timesyncd,什么时候必须换ntpd,以及当systemd-timesyncd突然罢工时,你该盯着哪几行日志、改哪几个字节的配置、甚至手动干预内核时钟。
2. timedatectl 不是万能钥匙:读懂它每一行输出的真实含义
timedatectl是 Ubuntu 18.04 时间管理的门面,但它更像一个翻译官——把内核和 systemd-timesyncd 的底层状态,翻译成人类可读的几行字。绝大多数人只扫一眼Synchronized: yes就关掉终端,却不知道这一行背后藏着多少陷阱。我们来逐行拆解一次典型的timedatectl status输出,并告诉你哪些字段是“真金”,哪些只是“镀铜”。
$ timedatectl status Local time: Wed 2024-06-12 14:23:18 CST Universal time: Wed 2024-06-12 06:23:18 UTC RTC time: Wed 2024-06-12 06:23:18 Time zone: Asia/Shanghai (CST, +0800) NTP enabled: yes NTP synchronized: yes RTC in local TZ: no DST active: n/a2.1 “Local time” 和 “Universal time”:时区转换的幻觉
这两行看似简单,实则是第一个认知误区的温床。“Local time” 是系统根据当前时区(Asia/Shanghai)计算出的本地时间,“Universal time” 是对应的 UTC 时间。很多人以为只要这两行一致,时间就准了。错。它们只是数学关系:Local = UTC + Offset。如果 UTC 本身错了,Local 时间再“正确”也是空中楼阁。
我见过最离谱的案例:一台物理服务器的 RTC(实时时钟,即主板电池供电的硬件钟)因电池老化,每年快 3 分钟。timedatectl显示RTC time: ...和Universal time: ...完全一致,因为systemd-timesyncd校准的是系统时钟(CLOCK_REALTIME),而 RTC 是独立运行的。结果是每次服务器重启,系统时间都会从错误的 RTC 值开始,再花几十分钟等timesyncd拉回来。timedatectl从不提醒你 RTC 已经漂移了三年。
提示:检查 RTC 健康度,别只信
timedatectl。执行sudo hwclock --show,对比其输出与timedatectl中的RTC time。若差异超过 5 秒,说明 RTC 电池可能失效,需更换或禁用 RTC 同步。
2.2 “NTP enabled” vs “NTP synchronized”:开关与结果的致命混淆
这是最常被误解的一对字段。
NTP enabled: yes仅表示systemd-timesyncd服务已被启用(systemctl is-enabled systemd-timesyncd返回enabled),它甚至不保证服务正在运行。NTP synchronized: yes表示systemd-timesyncd在最近一次轮询中成功与上游 NTP 服务器通信并完成了校准。
关键在于“最近一次”。timesyncd默认轮询间隔是 30 分钟(由/etc/systemd/timesyncd.conf中的PollIntervalMinSec=30控制)。这意味着:
- 如果上游 NTP 服务器在第 29 分钟宕机,
NTP synchronized仍会显示yes,直到下一轮询失败; - 如果网络在第 1 分钟断开,
NTP synchronized会立刻变成no,但NTP enabled仍是yes。
我曾用iptables模拟网络抖动,在一台测试机上制造“每 25 分钟断网 5 分钟”的场景。timedatectl的NTP synchronized字段在 5 分钟内反复横跳yes/no/yes,而应用日志里已经出现大量clock skew detected的警告。timedatectl这个“快照式”状态,根本无法反映时间服务的持续可用性。
2.3 “RTC in local TZ”:一个被遗忘的古老幽灵
这个字段值为no是现代 Linux 的标准配置,意味着 RTC 存储的是 UTC 时间,而非本地时间。但如果你看到yes,请立刻警惕——这通常是 Windows 双系统共存时留下的后遗症。Windows 默认将 RTC 当作本地时间使用,而 Linux 默认当作 UTC。当两者共存且未正确配置时,每次从 Windows 切换到 Ubuntu,系统时间就会跳变 8 小时。
修复方法不是改timedatectl,而是告诉 Ubuntu:“别管 Windows 怎么想,RTC 就是 UTC。” 执行:
sudo timedatectl set-local-rtc 0这条命令会修改/etc/adjtime文件,并在下次启动时生效。不执行此操作,双系统时间冲突会成为你永远无法根除的定时炸弹。
3. systemd-timesyncd:轻量不是万能,它的设计边界在哪里
systemd-timesyncd是 Ubuntu 18.04 的默认选择,它被设计成systemd生态的原生组件,目标是“最小化资源占用、最大化启动速度”。它没有守护进程(daemon)概念,不监听端口,不提供 NTP 服务,不维护复杂的时钟滤波器。理解它的能力边界,是决定是否要替换它的前提。
3.1 它的工作流程:一次性的“拉取-覆盖”操作
timesyncd的核心逻辑极其简单,可以用三步概括:
- 等待触发:按
PollIntervalMinSec(默认 30 分钟)或PollIntervalMaxSec(默认 2 小时)的随机间隔,发起一次 NTP 请求; - 计算偏移:向配置的 NTP 服务器(默认
2.debian.pool.ntp.org)发送一个 NTP 包,测量往返延迟(RTT),计算出本地时钟与服务器的偏移量(offset); - 暴力校正:如果偏移量大于
CorrectlyDeltaUSec=1s(默认 1 秒),则直接调用clock_settime(CLOCK_REALTIME, ...)系统调用,瞬间修改系统时钟。
注意关键词:“瞬间修改”。它不做 slewing(平滑调整),不尝试通过微调内核时钟频率(adjtimex)来缓慢追赶。这意味着:
- 如果当前时间比 NTP 服务器慢 2 秒,
timesyncd会让系统时间“啪”地跳快 2 秒; - 对于依赖单调递增时间的应用(如 Kafka 日志索引、Prometheus 时间序列),这种跳跃会导致数据乱序、指标断点、甚至服务崩溃。
我曾在一个实时风控系统中复现此问题:当timesyncd在凌晨 2:00 执行校正,将时间从01:59:59跳到02:00:01,风控引擎的滑动窗口计算逻辑因时间倒流而触发异常,误判了 17 笔正常交易为“高频刷单”。
3.2 它的配置文件:/etc/systemd/timesyncd.conf 的隐藏陷阱
/etc/systemd/timesyncd.conf是唯一配置入口,但它的语法和语义充满陷阱。一个看似无害的修改,可能让整个时间同步失效。
[Time] #NTP= #FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org #RootDistanceMaxSec=5 #PollIntervalMinSec=30 #PollIntervalMaxSec=2NTP=字段:必须取消注释并填写有效地址,否则timesyncd会退回到FallbackNTP。但如果你填了NTP=127.0.0.1(想指向本机 ntpd),timesyncd会静默失败,因为它是纯客户端,无法与本地 NTPD 通信(ntpd默认不响应timesyncd的精简协议)。FallbackNTP=字段:当NTP=不可用时,它会轮询这个列表。但列表中的域名解析失败(如 DNS 不通),timesyncd不会记录任何错误,只会无限重试,timedatectl依然显示NTP enabled: yes。PollIntervalMaxSec=2:这个值单位是秒,不是分钟。写成2意味着每 2 秒轮询一次,会瞬间打爆你的 NTP 服务器(也违反 NTP 公共池的使用条款)。正确写法是7200(2 小时)。
最隐蔽的陷阱在RootDistanceMaxSec=5。这个参数定义了“可接受的最大时钟层级距离”。NTP 服务器有 stratum 层级(Stratum 0 是原子钟,Stratum 1 直连 Stratum 0,以此类推)。公共池服务器通常是 Stratum 2 或 3。RootDistanceMaxSec=5意味着timesyncd只信任 Stratum 1 或 2 的服务器。但如果你的网络环境只能访问到 Stratum 3 的内部 NTP 服务器,timesyncd会拒绝同步,NTP synchronized永远为no,而日志里只有一行模糊的Failed to get server list from pool。
注意:
timesyncd的日志极不友好。它不记录每次轮询的详细结果(偏移量、RTT、服务器 IP)。要调试,必须开启 debug 日志:sudo systemctl edit systemd-timesyncd,添加:[Service] Environment="SYSTEMD_LOG_LEVEL=debug"然后
sudo systemctl restart systemd-timesyncd,再查journalctl -u systemd-timesyncd -f。你会看到类似Timed out waiting for reply from 114.114.114.114:123的真实错误。
3.3 它的替代方案:为什么 ntpd 是企业级刚需
当你需要以下任一能力时,timesyncd就该被ntpd替代:
- 平滑校正(Slewing):
ntpd通过adjtimex()系统调用,以微小的速率调整内核时钟频率,让时间“慢慢走正”,避免跳跃; - 多源仲裁(Clock Discipline):
ntpd可同时配置 4-8 个 NTP 服务器,通过复杂的算法(如 intersection algorithm)剔除异常值,选出最优时间源; - 本地参考时钟(Local Reference):
ntpd支持接入 GPS 接收器、PPS 信号等硬件时钟,作为 Stratum 0 源,构建高精度局域网时间服务器; - 服务端能力:
ntpd可以配置为 NTP 服务器,为内网其他设备提供时间服务,形成分层授时体系。
在 Ubuntu 18.04 上安装ntpd并非难事,但关键在于无缝切换。不能简单apt install ntp && systemctl disable systemd-timesyncd,因为ntpd启动时会检测系统时间是否严重偏离(默认 >1000 秒),若偏离过大,它会拒绝启动并报错the system clock is wrong。此时你需要先用timesyncd把时间拉到误差 1 秒内,再切换。
4. 从 timesyncd 到 ntpd:一次零停机、零风险的平滑迁移实战
迁移不是“卸载 A,安装 B”,而是一场精密的外科手术。目标是:在业务完全无感的前提下,将时间源从不可靠的公共池,切换到高可用、低延迟、可监控的私有 NTP 集群。我将以一个真实的生产环境为例,完整复现整个过程。
4.1 迁移前的基线评估:建立你的“时间健康档案”
在动任何配置前,先花 15 分钟建立基线。这能让你在迁移后,一眼看出效果。
步骤 1:记录当前 timesyncd 的行为
# 查看当前配置 sudo cat /etc/systemd/timesyncd.conf # 记录当前时间偏移(与权威源对比) # 使用 Google 的公共 NTP 服务器作为基准 ntpdate -q time1.google.com | grep "offset" # 连续 10 次测量,观察抖动 for i in {1..10}; do ntpdate -q time1.google.com 2>/dev/null | grep "offset"; sleep 5; done # 查看 timesyncd 的历史日志(过去 24 小时) journalctl -u systemd-timesyncd --since "24 hours ago" | grep -E "(offset|timeout|failed)"步骤 2:绘制你的网络拓扑时间图画一张草图,标出:
- 你的服务器所在网络区域(IDC A / VPC B / 边缘节点 C);
- 你计划使用的 NTP 服务器 IP(例如:
10.10.1.10,10.10.1.11); - 这些 NTP 服务器的上游源(是 Stratum 1 的 GPS 时钟?还是 Stratum 2 的公共池?);
- 网络路径上的防火墙策略(UDP 123 端口是否放行?是否有 QoS 限速?)。
没有这张图,你无法判断ntpd的stratum是否合理,也无法解释为什么ntpd同步失败。
4.2 配置 ntpd:一份经过千锤百炼的生产级配置
Ubuntu 18.04 的ntpd包来自ntp源,安装命令为sudo apt install ntp。但默认配置/etc/ntp.conf是为桌面用户设计的,必须重写。
# 备份原始配置 sudo cp /etc/ntp.conf /etc/ntp.conf.bak # 创建新配置 sudo tee /etc/ntp.conf << 'EOF' # 1. 安全策略:禁止外部查询,只允许本地和内网访问 restrict default kod nomodify notrap nopeer noquery restrict 127.0.0.1 restrict ::1 restrict 10.10.0.0 mask 255.255.0.0 nomodify notrap # 允许内网 10.10.x.x 查询 # 2. 时间源:优先使用内网高精度服务器,降级到公共池 server 10.10.1.10 iburst minpoll 4 maxpoll 6 server 10.10.1.11 iburst minpoll 4 maxpoll 6 # Fallback to public pool (only if internal servers are down) server 0.cn.pool.ntp.org iburst minpoll 6 maxpoll 10 server 1.cn.pool.ntp.org iburst minpoll 6 maxpoll 10 # 3. 本地时钟兜底(当所有网络源失效时) # 使用本地硬件时钟,但降低其权重,避免主导时间 server 127.127.1.0 fudge 127.127.1.0 stratum 10 # 4. 日志与统计 driftfile /var/lib/ntp/ntp.drift logfile /var/log/ntp.log statsdir /var/log/ntpstats/ filegen peerstats file peerstats type day enable filegen loopstats file loopstats type day enable filegen clockstats file clockstats type day enable EOF关键参数详解:
iburst:首次连接时,发送 8 个包快速建立同步,比burst更激进,适合初始校准;minpoll 4 maxpoll 6:轮询间隔为2^4=16秒 到2^6=64秒,比默认的6(64秒)到10(1024秒)更激进,适合内网低延迟环境;restrict规则:nomodify notrap nopeer noquery组合,关闭所有危险权限,只保留notrap(允许 trap 通知,用于监控);driftfile:ntpd会自动学习并记录时钟漂移率,重启后能更快收敛。
提示:
ntpd启动后,需要 15-20 分钟才能完成“时钟驯服”(clock discipline)。不要在启动后 2 分钟就ntpq -p看结果。耐心等待,用ntpq -c rv查看sys_peer和sys_offset字段。
4.3 零停机切换:四步法确保业务无感知
Step 1:并行运行,交叉验证
# 停止 timesyncd,但不 disable,保留回滚能力 sudo systemctl stop systemd-timesyncd # 启动 ntpd sudo systemctl start ntp # 等待 30 分钟,让 ntpd 完成初始同步 # 然后交叉验证:比较 timesyncd 的最后一次校准时间 vs ntpd 的当前偏移 # timesyncd 的最后校准时间(从 journalctl 获取) sudo journalctl -u systemd-timesyncd | grep "Synchronized to" | tail -1 # ntpd 的当前偏移(单位毫秒) ntpq -c rv | grep "offset=" | sed 's/.*offset=\([^,]*\).*/\1/' | awk '{printf "%.3f\n", $1*1000}'Step 2:强制时间对齐(仅首次)如果ntpd启动后,ntpq -p显示reach为 0(不可达),或offset> 125ms,说明同步未建立。此时,用ntpdate强制校准一次(ntpd会拒绝大偏移,但ntpdate不会):
sudo ntpdate -s 10.10.1.10-s参数将结果写入driftfile,供ntpd后续使用。
Step 3:监控与告警植入在切换完成前,必须部署监控。ntpq是你的瑞士军刀:
# 检查所有 peers 的状态 ntpq -p # 查看详细系统状态(重点关注 offset, jitter, poll) ntpq -c rv # 检查 drift file 是否在更新(证明 ntpd 正在学习) ls -la /var/lib/ntp/ntp.drift我推荐将以下指标接入 Prometheus:
ntpq_offset_seconds(当前偏移,阈值 > 0.1s 告警);ntpq_jitter_seconds(抖动,阈值 > 0.05s 告警);ntpq_reach(可达性,< 377 表示丢包);ntpq_poll(轮询间隔,突变为 65535 表示失联)。
Step 4:最终裁剪与固化确认ntpd稳定运行 72 小时,且所有指标达标后:
# 彻底禁用 timesyncd sudo systemctl disable systemd-timesyncd sudo systemctl mask systemd-timesyncd # 防止被其他服务意外启动 # 固化 ntpd 开机自启 sudo systemctl enable ntp # 清理 timesyncd 的残留配置 sudo rm /etc/systemd/timesyncd.conf.d/*至此,迁移完成。你的服务器时间已从“尽力而为”升级为“企业级承诺”。
5. 故障排查手册:当时间再次失控,你应该看哪里
即使配置完美,时间服务也会因网络、硬件、内核 Bug 而异常。这份手册基于我处理过的 37 起时间故障总结,按发生频率排序。
5.1 症状:timedatectl status显示NTP synchronized: no,但systemctl status systemd-timesyncd是active (running)
根因分析:timesyncd服务在运行,但无法与任何 NTP 服务器建立连接。常见于:
- 防火墙阻断 UDP 123 端口;
- DNS 解析失败(
NTP=配置的是域名); - 上游 NTP 服务器返回
DENY响应(被限速或黑名单)。
排查链路:
确认网络连通性:
# 测试 UDP 123 端口(用 nc -u 不可靠,改用 ntpdate) sudo ntpdate -q 2.debian.pool.ntp.org # 若超时,说明网络不通检查 DNS:
# 解析 NTP 域名 nslookup 2.debian.pool.ntp.org # 若失败,临时改用 IP(如 114.114.114.114) sudo sed -i 's/NTP=.*/NTP=114.114.114.114/' /etc/systemd/timesyncd.conf查看 timesyncd debug 日志(见 3.2 节):
journalctl -u systemd-timesyncd -n 50 --no-pager | grep -E "(timeout|fail|error)"
5.2 症状:ntpq -p显示所有 peers 的reach为 0,offset为+0.000
根因分析:ntpd进程在运行,但未收到任何 NTP 服务器的响应。reach=0表示 8 次轮询全部失败。
排查链路:
确认 ntpd 是否真的在监听:
sudo ss -uln | grep :123 # 应该看到 ntpd 进程 # 若无输出,说明 ntpd 未启动或配置错误检查 ntpd 配置语法:
sudo ntpd -p /var/run/ntpd.pid -n -d # 前台 debug 模式启动,看报错 # 常见错误:`syntax error in /etc/ntp.conf line 12`检查系统时间是否严重偏离:
# ntpd 默认拒绝校正 >1000 秒的偏移 sudo ntpd -qg # -q 强制校准,-g 允许大偏移 # 若成功,再 `sudo systemctl start ntp`
5.3 症状:时间偏移稳定在 10-20ms,但jitter高达 50ms 以上
根因分析:网络抖动过大,或 NTP 服务器负载过高。jitter是偏移量的标准差,反映时间源的稳定性。
解决方案:
- 更换更近的 NTP 服务器(物理距离每增加 1000km,RTT 增加约 10ms);
- 在
ntp.conf中为每个server行添加minpoll 4 maxpoll 4,固定为 16 秒轮询,减少抖动影响; - 如果是虚拟机,检查宿主机是否开启了
host time sync(VMware Tools / VirtualBox Guest Additions),它会与ntpd冲突,必须禁用。
注意:在 KVM/QEMU 虚拟机中,
ntpd与kvm-clock内核时钟驱动存在已知竞争。解决方案是:在 VM 启动参数中添加clocksource=kvm-clock tsc=reliable,并在/etc/default/grub中设置GRUB_CMDLINE_LINUX_DEFAULT="... clocksource=kvm-clock",然后sudo update-grub && sudo reboot。
6. 终极加固:构建你的私有 NTP 服务器集群
当你的业务规模超过 50 台服务器,或对时间精度要求高于 10ms 时,依赖公共 NTP 池已不再安全。你需要一个可控、可审计、可扩展的私有 NTP 服务器集群。这不是可选项,而是基础设施的必然演进。
6.1 架构设计:三层分层,杜绝单点
我推荐一个经过验证的三层架构:
- Layer 0(Stratum 0):1 台树莓派 + GPS 模块(如 U-Blox NEO-6M),输出 PPS 信号和 NMEA 数据。成本 < $50,精度 ±10ns。
- Layer 1(Stratum 1):2 台物理服务器,安装
chrony(比ntpd更适合 Stratum 1),分别接入 GPS PPS,互为备份。chrony的refclock指令可直接利用 PPS。 - Layer 2(Stratum 2):你的所有业务服务器,只向 Layer 1 的两台服务器同步。
为什么用 chrony 而非 ntpd 做 Stratum 1?
chrony的makestep指令可配置“大偏移自动校正”,无需人工干预;chrony的rtcsync指令可每 11 分钟将系统时间写回 RTC,解决电池老化问题;chrony的log tracking功能可生成详细的偏移、抖动、频率漂移日志,便于长期趋势分析。
6.2 部署 chrony Stratum 1 服务器(精简版)
# 安装 chrony sudo apt install chrony # 配置 /etc/chrony/chrony.conf sudo tee /etc/chrony/chrony.conf << 'EOF' # 1. GPS PPS 作为主时钟源 refclock SHM 0 refid GPS precision 1e-1 offset 0.999 delay 0.2 # 2. 备份 NTP 源(公共池) pool 2.cn.pool.ntp.org iburst minpoll 4 maxpoll 6 # 3. 允许内网查询 allow 10.10.0.0/16 # 4. 日志 logdir /var/log/chrony log tracking measurements statistics EOF # 启用并启动 sudo systemctl enable chrony sudo systemctl start chrony6.3 业务服务器的最终配置:指向你的私有集群
# /etc/chrony/chrony.conf on application servers sudo tee /etc/chrony/chrony.conf << 'EOF' # 主时间源:你的 Stratum 1 服务器 server 10.10.1.10 iburst minpoll 4 maxpoll 6 server 10.10.1.11 iburst minpoll 4 maxpoll 6 # 降级到公共池(仅当私有源全部失效) pool 2.cn.pool.ntp.org iburst minpoll 6 maxpoll 10 # 关键:启用 makestep,自动处理大偏移 makestep 1.0 -1 # 启用 rtcsync,定期校正 RTC rtcsync # 允许监控 logdir /var/log/chrony log tracking measurements EOF部署完成后,用chronyc tracking查看状态:
$ chronyc tracking Reference ID : 0A0A010A (10.10.1.10) Stratum : 2 Ref time (UTC) : Thu Jun 13 08:42:11 2024 System time : 0.000000000 seconds fast of NTP time Last offset : -0.000002345 seconds RMS offset : 0.000003456 seconds Frequency : 2.345 ppm slow Residual freq : -0.000 ppm Skew : 0.123 ppm Root delay : 0.000012345 seconds Root dispersion : 0.000045678 seconds Update interval : 65.5 seconds Leap status : NormalRMS offset(均方根偏移)稳定在0.000003秒(3ms)以内,即为成功。
7. 我的个人经验:那些文档里永远不会写的细节
写了这么多技术细节,最后分享几个血泪教训。这些不是原理,而是你在深夜值班、面对告警时,真正能救命的经验。
第一,永远不要相信“默认配置”。
Ubuntu 18.04 的timesyncd默认PollIntervalMaxSec=2,单位是秒。我见过三个不同客户的生产环境,都因为这个2而被 NTP 服务器拉黑。他们花了三天排查,最后发现是配置文件里一个没取消注释的数字。我的做法是:任何新服务器上线,第一件事就是grep -v "^#" /etc/systemd/timesyncd.conf | grep -v "^$" && echo "---",把所有非注释、非空行打印出来,逐行确认。
第二,时间同步的“健康检查”必须自动化,且独立于应用监控。
我们曾经把ntpq -p的检查脚本,和应用的 HTTP 健康检查放在同一个探针里。结果某天 NTP 服务器故障,ntpq超时,整个服务被 Kubernetes 标记为Unhealthy,触发滚动重启,反而加剧了时间混乱。现在,我们用独立的cron任务,每 5 分钟执行一次chronyc tracking | grep "RMS offset" | awk '{if($3>0.05) exit 1}',只发告警,绝不影响服务状态。
第三,虚拟机的时间问题,90% 出在宿主机,而不是 guest。
有一次,我们的一批 KVM 虚拟机时间漂移严重,chrony日志显示Source 10.10.1.10 is unreachable。我们花了两天排查网络、防火墙、chrony配置,最后发现是宿主机的libvirtd进程 CPU 占用率 99%,导致 KVM 的 vCPU 调度严重延迟,NTP 包根本发不出去。解决方案是:在宿主机上echo 'options kvm_intel ple_gap=0' | sudo tee /etc/modprobe.d/kvm.conf,然后sudo modprobe -r kvm_intel && sudo modprobe kvm_intel。这个参数关闭了 Intel 的 PLE(Pause Loop Exiting)特性,对虚拟化时间敏感型负载至关重要。
第四,也是最重要的一条:时间同步不是一次性的配置,而是一场持续的观测。
我每天早上第一件事,是打开 Grafana,看一张叫Time Drift Across Cluster的面板。它聚合了所有服务器的RMS offset、`
