Chrony 时间同步服务部署与排障:内网时钟源的正确搭法
时间不一致是分布式系统里最阴险的故障源:日志对不上、证书莫名失效、数据库主备切换异常,最后查出来都是时钟问题。内网的正确做法是选一两台机器做内部时钟源,其余机器只向它同步。本文用 Chrony 在 Rocky Linux 9 上搭这套结构,并给出排障方法。
为什么选 Chrony
- 对比 ntpd:chrony 收敛更快,网络抖动、间歇联网、虚拟机暂停恢复等场景下表现明显更好,RHEL 系从 8 起已是默认。
- 对比 systemd-timesyncd:timesyncd 只是个轻量客户端,不能对外提供时间服务,也没有 chronyc 这样完整的观测命令;要做内网时钟源只能用 chrony 或 ntpd。
- chrony 对时钟频率的估算更准,长期漂移小,且一条
chronyc命令就能看清同步状态。
前置条件
- 时钟源一台(node-01,192.0.2.10)能访问外网 NTP 或上级时钟源;客户端在内网 192.0.2.0/24;
- 所有机器有 sudo/root 权限,能改防火墙;
- 虚拟机需注意宿主机时间注入与 chrony 打架的问题,见常见问题一节。
第一步:安装并配置服务端
sudo dnf install -y chrony
sudo systemctl enable --now chronyd
编辑 /etc/chrony.conf,服务端关键配置如下:
# 上游源:优先上级时钟源,iburst 让启动时快速收敛
server ntp.example.com iburst
pool pool.ntp.org iburst
# 允许哪些网段来向本机同步
allow 192.0.2.0/24
# 上游全部不可达时,是否用本地时钟继续对外提供服务(慎用,见下)
# local stratum 10
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
几个配置项的取舍要说清:
- allow 是服务端开关:不写 allow,这台机器只做客户端、不会响应别人的同步请求。按最小原则只放行内网网段。
- local stratum 10 要慎用:它表示上游全断时用本机时钟冒充 stratum 10 继续对外服务。好处是内网时间保持一致,坏处是全网会一起漂错。孤立内网可以开;有外网源的环境默认不开,出问题先修上游。
- makestep 1.0 3:启动后前 3 次测量中,若偏差大于 1 秒,直接步进调整而不是缓慢斜移。只在启动初期生效是刻意的——运行中大步进会让时间倒流,足以搞乱数据库和日志顺序。
- Ubuntu 差异:包名同为 chrony,服务名也是 chrony(无 d),配置文件为 /etc/chrony/chrony.conf。
放行防火墙并重载配置:
sudo firewall-cmd --permanent --add-service=ntp
sudo firewall-cmd --reload
sudo systemctl restart chronyd
NTP 走 UDP 123。用了自定义防火墙时等价规则是放行 udp/123 入站;注意出站方向也要允许本机访问上游的 123/UDP。
第二步:配置客户端
客户端的 chrony.conf 只需要把源指向内网时钟源,关掉自带的公网 pool 避免双源打架:
server 192.0.2.10 iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
sudo systemctl enable --now chronyd
chronyc sources -v
有多台内网时钟源时写多行 server,主源宕机后 chrony 会自动在剩余源里按层级和质量重新选择,不需要额外做高可用。
第三步:学会读 chronyc
chronyc tracking
chronyc sources
chronyc sourcestats
- tracking 看全局:
System time是当前估计偏差(越接近 0 越好,毫秒级正常);Stratum是本机层级(源是 stratum 2 时本机为 3);Leap status: Normal表示已同步,若显示 Not synchronised 说明还没同步上或源全挂了。 - sources 看每个源:行首
^*是正在使用的源,^?表示不可达或还没测出有效值,Reach是八进制的可达性寄存器,377 表示最近 8 次探测全成功,数值掉得厉害先查网络和防火墙。 - sourcestats 看趋势:
Offset列的偏差走势比单点值更能说明问题,持续单向变大通常是时钟频率估算不准或宿主机在抢时间。
验证
timedatectl # 看 "System clock synchronized: yes"
chronyc tracking | grep -E "System time|Stratum|Leap"
ss -ulnp | grep 123 # 服务端确认在监听 UDP 123
预期:客户端 sources 中内网源带 ^* 标记,tracking 偏差在毫秒量级,timedatectl 显示已同步。
常见问题
- 源一直不可达(Reach 为 0):按序排查——服务端 chrony.conf 是否写了 allow 且已重启;服务端防火墙是否放行 udp/123;中间网络是否拦截 UDP。服务端可临时开
chronyc clients看有没有客户端请求进来。另注意一份老坑:服务端本身 Leap status 不是 Normal 时,它会拒绝给别人提供可信时间,先修服务端自己的同步。 - 时间漂移越来越大:先看 sourcestats 的频率误差;虚拟机上常见原因是宿主机性能调度导致 TSC 不稳,可在内核启动参数加
clocksource=hpet对比。driftfile 权限错误也会导致频率估算存不下来,检查 /var/lib/chrony 属主为 chrony。 - 虚拟机时间跳变:虚拟机从快照恢复、宿主机休眠唤醒后时间会突然跳。两点处理:一是关掉虚拟化平台的「宿主机时间同步」功能(VMware Tools、Hyper-V 时间集成服务、qemu-guest-agent 的时间注入),时间只归 chrony 管,避免两方打架;二是对偏差过大的机器做一次性强制同步(见下条注意点)。
- 一次性大步进同步 makestep 的注意点:存量机器偏差已经几分钟时,斜移收敛太慢,可以执行
sudo chronyc makestep立即步进。但必须选业务低峰、提前知会:时间向前跳会让日志出现空洞,向后跳(更危险)会让同一秒的日志重叠、定时任务重复触发、依赖单调时间的程序异常。数据库、消息队列等对时间敏感的服务,应停服同步后再启动,禁止带业务直接步进。
小结
内网时间同步的结构很简单:一两台 chrony 对上游、其余机器只指内网源、allow 按网段最小放行。日常排障靠 chronyc 三件套:tracking 看偏差与同步状态、sources 看源可达性、sourcestats 看漂移趋势。最需要克制的是 local stratum 和 makestep:一个决定全网是否一起漂错,一个决定是否为修时间引入更大的业务风险,都不能顺手乱开。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。






