Linux运维9 min read次阅读

Chrony 时间同步与时钟漂移排查实战

为什么时间同步是运维的隐形地基

很多故障事后复盘,根因都指向一个被忽视的维度——时钟。当集群里两台机器差了几秒甚至几分钟:

  • 数据库主从复制:MySQL GTID、PostgreSQL 逻辑复制依赖事务时间戳与有序提交,时钟跳变会导致复制中断或数据回退。
  • TLS 证书校验:证书有 notBefore/notAfter,客户端时间慢于签发时间会直接拒绝握手。
  • 分布式锁 / 选举:基于租约(lease)的锁(如 etcd、Redis 锁)依赖本地时钟判断过期,时钟回拨会让锁提前失效。
  • 日志与链路追踪:跨服务日志对不齐时间轴,排查问题如同拼一幅错位的拼图。
  • 定时任务cron 在错乱时钟下会重复执行或漏执行。

一句经验之谈:能用 NTP 的地方就别信任主机硬件时钟,尤其是虚拟机。

NTP 与 Chrony 怎么选

传统 ntpd 设计目标是"长期精密守时",对网络抖动敏感、冷启动同步慢(可能要几十分钟)。chronyd 是 NTP 协议的现代实现,特点:

维度 ntpd chronyd
冷启动同步 慢(逐步校正) 快(可步进校正)
间歇网络 表现一般 擅长(断网后仍能靠漂移模型守时)
虚拟机/笔记本 易因时钟跳变失步 对时钟跳变容忍度高
资源占用 较高 极低
命令交互 ntpq chronyc

结论:新系统一律用 Chrony,尤其是云上虚机、容器宿主、需要频繁启停的环境。

安装

# CentOS / RHEL / Rocky / Anolis
yum install -y chrony

# Ubuntu / Debian
apt-get install -y chrony

# 开机自启并启动
systemctl enable --now chronyd

架构:内网统一时间源

最佳实践不是让每台机器都直连公网 NTP,而是分层

公网 NTP (ntp.aliyun.com / time.cloudflare.com / pool.ntp.org)
        │
    ntpserver01 (内网时间源, 同步公网,  stratum 2)
    ntpserver02 (冗余时间源)
        │
   ┌────┴────┬────────┬────────┐
  Web1     DB1     K8s节点   Redis
  (全部指向内网 ntpserver01/02)

好处:内网机器不暴露公网、流量可控、时间源一致、断公网时内网仍自洽。

服务端配置(时间源节点)

/etc/chrony.conf

# 上游公网时间源(可配多个,自动选优)
server ntp.aliyun.com iburst
server time.cloudflare.com iburst
server pool.ntp.org iburst

# 允许内网网段同步过来
allow 10.0.0.0/8
allow 192.168.0.0/16

# 即使上游不可达,也以本地时钟为权威(避免一直不收敛)
local stratum 10

# 记录时钟漂移,重启后快速恢复
driftfile /var/lib/chrony/drift

# 日志
log measurements statistics tracking

iburst 让初次同步时连发 8 个包,秒级完成校准;local stratum 10 是关键容错——上游全挂时,本机仍可对外提供"近似正确"的时间,避免内网集体失步。

客户端配置(业务机器)

server ntpserver01 iburst
server ntpserver02 iburst

# 不允许客户端把自己当服务器
# (不要写 local / allow)
driftfile /var/lib/chrony/drift
rtcsync   # 把系统时间定期写回硬件时钟 RTC

rtcsync 等价于 hwclock --systohc 的自动版,保证重启后硬件时钟不至于漂太远。

日常排障命令(chronyc)

# 1. 跟踪状态:当前偏差、 stratum、已同步的上游
chronyc tracking
# Reference ID    : C0A80101 (ntpserver01)
# Last offset     : -0.000412 sec   <- 当前偏差 0.4ms,健康
# Root delay      : 0.001234 sec
# Leap status     : Normal

# 2. 看用了哪些时间源、质量如何
chronyc sources -v
# ^* ntpserver01  ...  * 表示当前选中并同步

# 3. 源评分(哪些被选、哪些被弃)
chronyc sourcestats -v

# 4. 强制立即同步(谨慎,会步进时间)
chronyc makestep

# 5. 看是否有大的时钟跳变记录
chronyc tracking | grep 'Leap status'

健康信号:Last offset 在毫秒级、stratum 合理(内网源通常 ≤ 3)、Leap status: Normal

时钟漂移:为什么虚拟机最坑

物理机有稳定的晶振,漂移通常每天几毫秒。虚拟机时钟由宿主机内核模拟( kvm-clock / pvclock / TSC),问题在:

  1. 休眠 / 快照恢复 / 热迁移后,虚机时钟可能"冻结"再"瞬移",一次性偏掉几秒到几分钟。
  2. CPU 长期空闲时某些虚拟化时钟源会走慢(漏 tick)。
  3. 多 NUMA / 不同物理 CPU 的 TSC 不一致,跨核读取时间有偏差。

应对:

  • 虚机内务必跑 chronyd,并启用 rtcsync;别指望靠 RTC 校准。
  • KVM 虚机优先用 kvm-clockdmesg | grep clocksource 确认),避免 acpi_pm 这类慢时钟源。
  • 容器不要各自跑 chrony(共享宿主时钟),只需宿主校准;在容器里跑 NTP 反而会与宿主打架。
  • 对时间极度敏感的服务(如金融交易),考虑 chronyd + PTP(精密时间协议,亚微秒级)硬件方案。

闰秒(Leap Second):定时炸弹

UTC 偶尔插入闰秒,操作系统默认行为(ntp leap smear 或内核 11-minute mode)可能让时间"倒退 1 秒",触发:

  • 依赖单调时钟的程序算出负间隔 → 崩溃或死循环。
  • 数据库唯一时间索引出现重复/乱序。

现代做法:

  • 闰秒 smear(推荐):让时间源在闰秒前后把 1 秒平滑分摊到若干小时(如 Google 的 20 小时线性 smear),对外不出现跳变。内网时间源配 leapsecmode slew + smoothtime
  • 应用层一律用单调时钟CLOCK_MONOTONIC / Go 的 time.Now().UnixNano 做间隔测量,而非绝对时间做序)。

与 TLS / 数据库的硬性关联

  • 证书校验窗口通常 ±5 分钟(有的 CA 更窄)。机器慢了 6 分钟,HTTPS 握手直接失败——表现为"时好时坏",极难定位。
  • MySQL 启用了 sslbinlog 时间戳、MongoDB oplog 时间排序,都依赖节点时钟一致。
  • Kafka 不依赖时钟做顺序(靠 offset),但监控、审计日志仍依赖。

生产铁律:任何证书错误 / 复制中断的排查清单里,第一步先看时钟。

10 条避坑底线

  1. 新机器默认装 Chrony,别用 ntpd,尤其虚机/云主机。
  2. 内网统一时间源,业务机不要直连公网 NTP,减少暴露与抖动。
  3. 时间源至少 2 个且独立(不同公网源 + 不同内网节点),防单点。
  4. 时间源节点配 local stratum 10,上游全挂时内网仍自洽。
  5. 业务机配 rtcsync,定期把系统时间写回硬件时钟。
  6. 虚机务必跑 chronyd + 确认 kvm-clock 时钟源,快照/迁移后主动 chronyc makestep 校准。
  7. 容器不要各自跑 NTP,只校准宿主;共享宿主时钟即可。
  8. 闰秒用 smear(平滑) 而非硬跳变,应用层用单调时钟做间隔测量。
  9. 监控 chronyc trackingLast offset,超过阈值(如 > 100ms)告警。
  10. 证书失败 / 复制中断 / 诡异定时任务,第一反应查时钟,而不是先改业务代码。

时钟是分布式系统的"地基下的地基"——平时无感,一歪全塌。把 Chrony 配对、监控好偏移,能提前消灭一大类"查无实据"的灵异故障。

分享:

评论区