chrony时间同步配置实战:从NTP基础到生产环境排障

📅 发布时间:2026/10/19 8:31:21
chrony时间同步配置实战:从NTP基础到生产环境排障
1. 为什么还要折腾时间同步先聊聊NTP这点事很多线上系统的监控告警、日志审计、分布式事务协作全都依赖一个底层前提各节点的时间得基本一致。如果某台机器的时间慢了五分钟日志时间戳对不上排查问题时能把你绕进死胡同。更麻烦的是某些服务之间做签名校验或票据认证时间偏差超过阈值会直接拒绝请求。这就引出了NTPNetwork Time Protocol它让设备从远程时间服务器同步标准时间把误差从分钟级压到毫秒甚至微秒级。前面这些属于背景铺垫真正让我决定弃用旧方案、全面转向chrony的是一次生产事故。当时线上某台数据库主机的时钟漂移严重峰值偏差达到了几百毫秒业务高峰期出现了竞态条件导致的脏数据。我检查后发现那台机器还在用传统的ntpd做同步而它面对大跨度时钟跳变时的修正策略偏保守收敛慢而且配置和维护方式也比较重。这时候我把目光放到了chrony身上它是NTP协议的另一种实现设计目标更现代同步速度快、精度高对网络抖动和丢包的容忍度也更好。不少发行版已经默认用它替代了ntpd。这篇文章就从配置出发把我在实际环境中踩过的坑、验证过的参数一并梳理出来。先说清楚目标人群如果你在维护几十台以内的小集群或者家里有个装着Linux的服务器折腾各类自建服务完全可以用chrony替换掉系统默认的时间同步方案。这篇内容不止讲配置命令会把参数含义、选型逻辑、验证手法都拆开讲确保你照着做就能得到稳定可靠的同步结果。2. 内核里的时间体系与chrony的同步机制2.1 时钟来源、时区与时间标准先分清楚动手配置chrony之前必须把几个容易混淆的概念理顺硬件时钟RTC、系统时钟、时区、UTC。硬件时钟是主板上那块靠电池维持的独立计时芯片断电后依然走时系统时钟是操作系统内核维护的软件计数开机时从硬件时钟读取初值之后靠CPU定时器中断持续更新。NTP同步的对象是系统时钟而硬件时钟默认不会自动跟着改动这导致很多人重启机器后又发现时间不对了。另一个问题是时区。NTP协议传输的永远是UTC标准时间不带时区偏移。服务器上如果用了Asia/Shanghai这类时区chrony在显示本地时间时会自动做偏移换算但实际同步过程始终基于UTC这是设计上的重要原则。所以配置里出现的iburst、poll这些选项和时区没有关系。你可以改动/etc/timezone与/etc/localtime来设置显示时区但千万别去改/etc/chrony/chrony.conf里的服务器地址来“纠正”时差那方向就错了。底层还有一个“时间标准”的问题。新装系统时安装器通常默认RTC使用UTC标准也有系统默认让RTC走本地时间。双系统用户如果发现Windows和Linux时间老差八小时十有八九是两边对RTC的基准理解不一致。Linux把RTC当作UTC处理Windows把RTC当作本地时间处理于是来回切换系统就会导致时间错乱。这个问题和chrony配置无关但如果你要彻底管好时间同步这句提醒值得记下来。2.2 chrony为什么比ntpd好测量模型与修正策略chrony的同步机制和ntpd差异很大。ntpd对时钟频率漂移的修正很保守初始同步可能要花几分钟到十几分钟之后才进入稳定跟踪状态。chrony则用了一套更快的学习算法它能在几十秒内完成粗略同步并通过周期性测量持续修正本机时钟的频率偏差。举个例子如果系统时钟因为主板晶振老化或温度变化每天稳定慢掉0.5秒chrony会记录这个频率误差并做“预补偿”而不只是反复校时。这个特性对无法频繁访问外部时间服务器的离线环境尤其有用。即使断网chrony也能按之前学习到的漂移率继续维持相对准确的时间。这个能力来自设置文件中的driftfile它会把时钟频率偏差保存到指定文件重启后直接加载不需要重新学习。还有一点就是chrony对网络环境的适应能力。默认UDP 123端口与服务器通信时如果某次响应超时或者迟到chrony会根据RTT往返时延加权评估样本质量对抖动大的服务器自动降低权重。这个机制在跨运营商网络的时候价值很明显家里的宽带访问公共时间服务器经常会出现几十毫秒的延迟波动ntpd会把这种波动算进时间样本里导致误差变大chrony的鲁棒性明显好一些。3. 配置前的准备安装、确认与服务管理3.1 安装与系统层面的前置检查大多数现代系统的软件源里都有chrony这个包安装过程很简单。Debian系、Ubuntu、CentOS都能直接安装# Debian / Ubuntu sudo apt update sudo apt install chrony # RHEL / CentOS / Rocky sudo yum install chrony装完之后先确认一下发行版默认的时间同步服务是否冲突。很多系统预装的是systemd-timesyncd它和chrony都通过同一个系统时钟操作两者同时运行会发生竞争。你需要禁用systemd-timesyncd再启用chrony服务sudo systemctl stop systemd-timesyncd sudo systemctl disable systemd-timesyncd sudo systemctl enable --now chronyd如果系统里还留着旧版ntpd也要一并停掉。否则两个NTP守护进程同时修改系统时钟结果不是你修我、就是我修你最后两个都失灵。检查命令也很直观sudo systemctl status chronyd sudo chronyc trackingchronyc tracking能输出当前同步状态。重点看Leap status是否变成NormalStratum是不是已经是合理层级System time那一项代表本机相对参考时间的偏差值。看到这些为正常状态说明chronyd已经在正常工作。3.2 时间服务器选型公共服务器与内网自建时间服务器选型是个值得单独说的环节。公共NTP服务器很多但和你的网络距离、运营商链路、使用策略都有关。我建议至少配置三台以上分散到不同机构或者不同地域避免单一依赖。国内常用的是各高校或研究机构提供的公共NTP地址不要全部写同一家否则上游抖动会直接影响你的同步质量。小规模集群里更常见的做法是自建内网NTP服务器。找一台网络稳定、常年开机的节点让它同步公共服务器然后作为内部其他节点的时间源。其他机器只需指向这台内网服务器省去大量对外请求同时能降低延迟因为局域网内的RTT可能只有几毫秒比公网路径稳得多。这种分层结构在生产环境里属于标准操作。# 内网客户端指向自建服务端的配置示例 server 192.168.10.10 iburst server 192.168.10.20 iburst上面这是客户端配置如果你是那台内网主时间服务器它需要同时完成两件事对外同步公共服务器对内提供服务。外部同步来源写在pool或server里对内提供服务的监听地址默认就是0.0.0.0:123完全不用额外改。关键是配合防火墙规则UDP 123端口允许内网网段访问即可。4. 配置文件逐行拆解每个参数为什么要这样设chrony的配置文件路径通常是/etc/chrony/chrony.conf。不同发行版预装配置差异不小有些默认配置已经能直接用但要得到理想效果建议手工过一遍。我下面贴出一份我常用的配置并逐部分解释参数含义重点说明哪些是生产环境必须考虑的哪些是新手容易忽略的。# /etc/chrony/chrony.conf pool pool.ntp.org iburst server ntp.aliyun.com iburst server ntp1.aliyun.com iburst server time1.cloud.tencent.com iburst driftfile /var/lib/chrony/drift makestep 1 3 rtcsync allow 192.168.0.0/16 local stratum 10 logdir /var/log/chrony log measurements statistics tracking第一块是时间源配置。pool和server的区别在于pool会从域名解析得到一个地址集合chrony会自动管理这些多个服务器而server只针对单台服务器。建议生产环境里至少保留一个pool作为兜底再加上几个指定的server这样无论公共解析怎么变化总会有可用源。iburst参数会让chrony在启动后连续发送八个快速请求包加快首次同步的收敛速度这是默认要点开的选项。driftfile参数保存时钟频率误差路径需要确保进程有写权限。makestep 1 3这个参数特别重要它表示前三次时间测量中如果检测到系统时间与参考时间的偏差超过1秒就立刻以跳跃方式修正系统时钟而不是靠缓慢的 slew 逐步逼近期望值。很多刚接触chrony的人发现启动后时间没变过来原因就是默认配置走了缓慢校准路线偏差好几秒却要用很久才追平。内网环境或者刚开机的机器出现大偏差这个参数能帮你快速恢复正常。rtcsync让chrony定期把系统时间写回硬件时钟确保重启后时间不会回退太多。这台机器如果没有特殊原因保持开启就好。makestep解决的是启动瞬间的突变问题rtcsync解决的是断电重启后的持久化问题两者配合比较完善。allow和local stratum通常只在服务器端配置。allow指定允许哪些网段来请求时间同步比如192.168.0.0/16表示整个私网网段都可以访问。local stratum 10是给这台服务器在无法访问上游外部时间源时使用的兜底策略即使它失去对外连接也依然会以10层身份继续为内网提供服务不会因为源丢失就拒绝响应。这个设计对离线环境非常关键。需要注意的是local stratum的数字大小代表时钟的“信任级别”数字越大优先级越低。所以内网客户端默认会优先选择层级更小的时间源而不会出现同步环路。5. 实操完整配置一台内网时间源服务器5.1 服务器端配置与验证步骤直接照搬你的场景来走一遍。假设你有一台常年运行的服务器IP是192.168.10.10操作系统是Debian系现在要让这台机器成为内网时间服务器。我会从安装到验证逐步说明实际操作。第一步安装完成后直接编辑配置文件。把供应商自带的公共服务器去掉换成你信任的公共NTP源也可以保留系统默认的pool源。重点要加上allow 192.168.0.0/16否则客户端无法访问UDP 123端口。下面是我实际使用的一份服务端配置# 服务端 192.168.10.10 的 chrony.conf pool pool.ntp.org iburst server ntp.aliyun.com iburst server ntp1.aliyun.com iburst driftfile /var/lib/chrony/drift makestep 1 3 rtcsync allow 192.168.0.0/16 local stratum 10 bindaddress 0.0.0.0 port 123第二步重启服务并等待同步。启动后建议等两三分钟再做验证给chrony留出完成初次同步的时间sudo systemctl restart chronyd sleep 120 chronyc tracking这时会输出类似这样的文本Reference ID : 203.107.6.88 (ntp.aliyun.com) Stratum : 2 Ref time (UTC) : Wed May 15 10:11:22 2024 System time : 0.000000031 seconds fast of NTP time Last offset : -0.000008232 seconds RMS offset : 0.000432882 seconds Frequency : 2.087 ppm fast Residual freq : -0.001 ppm Skew : 0.038 ppm Root delay : 0.053022 seconds Root dispersion : 0.003115 seconds重点字段看两个Stratum等于2表示你从第1层公共服务器同步到了时间可信度足够System time显示的偏差越小越好如果这项是分钟级数以上说明配置有问题。Frequency表示本机时钟相对标准时间的漂移率单位是ppm百万分之一。稳定在个位数ppm是正常的如果数值很大或者一直跳动说明硬件时钟质量比较差或者温度影响严重。第三步显式测试本地端口与防火墙规则。用chronyc sources -v可以查看每个时间源的详细状态^*开头的行表示该源已被选中并作为参考源^表示该源可作为备用源。如果全是^?或^x说明同步有问题。查看端口监听状态用sudo ss -ulpn | grep 123看到0.0.0.0:123处于LISTEN并且进程名是chronyd说明服务端正常监听。防火墙方面Debian系默认可能没有额外规则但如果你开启过ufw要记得放行sudo ufw allow 123/udp5.2 客户端配置与联动验证内网其他节点配置就只需一行再加上可选的本地漂移记录路径# 客户端 /etc/chrony/chrony.conf server 192.168.10.10 iburst driftfile /var/lib/chrony/drift makestep 1 3 rtcsync注意客户端的配置里不需要pool也不需要allow它只是一个请求方。iburst依旧建议打开方便客户端启动后快速完成初始同步。客户端完成了配置后同样用chronyc sources -v检查源状态。正常会出现类似^* 192.168.10.10 3 6 377 22 -559us[-1899us] /- 2389us关键看^*标识和偏移量。如果偏移是毫秒级但能稳定收敛可以接受如果一直跳动到几十毫秒甚至几百毫秒先检查服务端的allow配置再检查网络丢包。内网环境下出现毫秒级跳动的常见原因多半是交换机或宿主机CPU软中断处理不及时你还可以尝试把客户端的轮询间隔加大减少同步压力。验证完单台客户端没问题后建议找一台干净机器做端到端的时间偏差对比。在客户端机器上直接跑chronyc tracking观察System time字段是否贴着0附近。另外可以手动对比chronyc -c tracking | awk -F, {print $4}这样输出的就是当前绝对偏差秒数。我通常要求生产环境里偏差不超过20毫秒如果超过这个值多半是同步频率不够或者网络路径问题。6. 同步源选择与架构分层为什么不要全员直连公网6.1 公共NTP源的取舍标准公共NTP源选择其实是门学问。全球有大量开放NTP服务器但不是所有都适合生产使用。我选源的标准有四个你可以直接拿来参考第一来源可靠。使用高校、研究机构或知名云厂商提供的服务稳定性有保证。有一些私人维护的服务器可能某天突然停止服务这会影响你排查问题时的思路。第二距离近。在同一运营商网络内RTT越短越好。实测下来国内云服务器访问几大云厂商的NTP地址往返延迟都在几毫秒到十几毫秒之间效果非常好。面向海外业务的服务器适当选择海外公共NTP源更合适。第三数量适中有冗余。太少容易单点故障过多会导致本地时间源选择算法要花时间挑选、容易受弱源干扰。一般维持三到五个源已经足够。第四尽量不要都指向同一个上游。比如全部指向同一个机构如果对方NTP集群出现问题你的所有源可能同时掉线。分散到两三家以上更安全。6.2 分层设计内网NTP架构的推荐模式生产环境如果节点比较多我不建议每个节点都直接请求公网NTP源。原因很直接大量节点同时在公网请求不仅延迟不可控还容易受链路波动影响也可能被上游限速。我更推荐分层的模式。按规模来排的话可以这样设计几十台规模一台主时间服务器对外同步其他节点全部指向这台。备选方案是加一台冷备主备配置相同客户端配置里把两台都写上。上百到几百台规模两台或三台时间服务器组成同步源池各自对外同步同时定期互相同步一次消除相互之间的微小漂移。客户端把这几台全部写入server列表。跨机房、跨地域场景每个机房至少保留一台本地时间服务器各机房的时间服务器之间再做互相校准。客户端一律只访问本机房的服务器避免跨专线的高延迟。分层架构的好处在于把故障域隔离。如果你只有客户端直连公网一条公网链路的波动会影响一组机器如果有了分层只有最上层的时间服务器受影响底下所有节点不受牵连。而且内网同步延迟低最终精度反而更好。6.3 内网时间源失去外网时怎么兜底这个场景可能不多但必须提前准备好。内网时间服务器如果彻底断外网按默认配置它会因为无法访问外部时间源而拒绝为内网其他节点提供参考时间这会连累整条同步链。解决办法就是前面提到的local stratumlocal stratum 10这个参数的意思是即使这台服务器失去了所有同步源它依然可以作为10层时间源继续为内网节点提供时间。但要注意它提供的时间是基于本机时钟的没有任何上游校准时间会随时间累积漂移。这个设计只是为了兜底不应长期依赖。一旦公网恢复chronyd会自动重新找到上游源并恢复第2层身份无需人工干预。不过这种“无源兜底”状态我建议配合告警。可以用一行简单的脚本检查chronyc tracking | grep -E Reference ID | grep -v N\/A如果输出为空说明Reference ID是N/A当前处于无源状态。配合定时任务或者监控系统就能第一时间发现异常。7. 验证同步效果与故障排查那些年我踩过的坑7.1 用chronyc命令判断同步健康状况配置完成后最核心的验证工具就是chronyc。除了tracking和sources -vchronyc clients也很有用它能查看当前有多少个客户端在向你这台服务器请求同步。如果发现大量外部IP先确认allow范围是否设得太宽。我还习惯用chronyc sourcestats来看每个源的统计样本情况。输出里的RMS offset反映最近测量的整体偏差越小越好Std Dev表示样本标准差如果这个值持续增大说明该源网络抖动大值得排查。还有一条相当实用的经验在客户端做一次模拟并发强制chronyd进行一次立即同步sudo chronyc makestep这个命令能让chronyd立刻执行一次阶梯跳跃适合你在测试时快速看到效果。生产环境一般不需要手动执行除非你确认时间偏差已经大到无法容忍。7.2 常见时间不同步问题排查速查表实际操作中总会出现各种奇奇怪怪的问题我整理了一张高频问题速查表基本覆盖我遇到过的80%场景症状可能原因排查命令 / 方案sources -v全部显示^?或^x防火墙屏蔽UDP 123上游源不可达检查ss监听结果、防火墙规则、网络连通性tracking显示Stratum为10处于无源兜底状态联系不上所有上游确认外网连通性检查pool配置域名能否解析系统时间始终不跳变makestep未合理配置偏差小于slew阈值检查makestep参数必要时手动执行chronyc makestep同步正常但偏差较大网络抖动严重或时间源离得太远换距离更近的源用sourcestats观察标准差重启后时间回退未开启rtcsync或者RTC基准不对开启rtcsync检查RTC时区标准chronyd服务启动失败driftfile路径不可写端口被占用查看journalctl -u chronyd日志修正目录权限这张表里的每一条我都实际碰到过。尤其是重启后时间回退这个问题最容易被人忽视——配置本身没问题服务也正常运行但一断电就现原形。7.3 日志解读与排查思路日志是保底手段。chrony的日志默认配置在/etc/chrony/chrony.conf里通过log指令控制常用的配置是log measurements statistics tracking其中statistics会记录每次时钟调整的统计信息measurements记录与每个源之间的原始测量数据。日志输出到/var/log/chrony目录文件名分别是measurements.log、statistics.log、tracking.log。看一份statistics.log的实际记录时重点关注adj这一列它表示每次调整系统时钟的具体数值。如果多数adj值是正一个大值然后又负一个大值来回摆说明你选的源本身存在严重的抖动或者多个源之间不一致导致chrony反复修正。这种情况应该立即换源硬件时钟本身可能没问题但网络质量决定了最终同步质量。日志里的measurements如果出现大段的Timeout说明UDP 123端口丢包严重。可以先从ping和traceroute下手确认网络路径质量同时检查上游NTP服务器是否有限流。公共NTP源被高频请求时有可能会临时断开响应这是正常现象。8. 生产环境维护建议配置完成只是开始8.1 定期同步校验与告警脚本配置完成后建议用监控系统或者定时任务持续校验同步状态不要等出问题再介入。我自己通常会挂一个简单的指标采集脚本每五分钟执行一次把System time偏差值推进监控系统设一个50毫秒的告警阈值剥离开细节直接看结果。一个非常轻量的做法是直接在cron里加*/5 * * * * /usr/bin/chronyc tracking | /usr/bin/grep -E System time /var/log/chrony-check.log但更推荐的做法是让监控系统直接抓取chronyc的输出。比如在自定义的文本采集器里执行chronyc -c tracking | awk -F, {print system_time_offset $4}这样得到的指标可以关联到每台机器的标签。任何一台机器出现时间偏差监控面板马上会体现出来不用等用户投诉日志时间不对再排查。8.2 更新上游NTP源时的注意事项上游NTP源不是永远一成不变的。有时候你使用的公共池会用新的域名替换旧的有时候发现某个源质量下降需要替换。修改配置时注意两点第一千万别一次性把所有旧源都删掉再换上新的应该先加新源、观察一段时间确认同步稳定后再逐步移除旧源。这样即使新源有问题chrony还能继续使用旧源保持同步。第二更换源之后记得检查driftfile里的频率估计值是否会受到新旧源跨度的冲击。如果是从国内源切换到海外源RTT差异很大tracking里的Frequency数值会出现暂时波动这是正常现象。等几个小时后频率估计会重新收敛不用干预。8.3 和硬件RTC的协同问题前面提到rtcsync会让chronyd把系统时间写回硬件时钟但默认的写入频率其实不高。如果你经常断电重启可以考虑在系统层面额外同步一次硬件时钟sudo hwclock --systohc这条命令手动把系统时间写入RTC。也可以反过来校验RTC和系统时间的偏差sudo hwclock --show如果发现RTC偏差特别大可能主板电池快耗尽了。锂电池一般能撑几年甚至十年但到了一定年限你会看到每次开机时间都回到某个固定年份这是电池电量耗尽的典型信号。趁早换电池不然你配置得再好断电一次就打回原形。9. 一些细节上的补充说明9.1 chrony不监听端口时的排查顺序如果你在客户端访问服务器超时先不要怀疑chrony配置。我碰到过一次情况是云平台安全组把UDP 123给放行了但系统内部firewalld默认区域没放行导致怎么都连不上。排查顺序建议是确认服务端进程监听状态ss -ulpn | grep 123确认系统防火墙规则iptables -L -n -v | grep 123或firewall-cmd --list-ports确认云平台安全组规则如果托管在云上用客户端手动跑一次chronyc sources -v观察错误信息如果跳到第4步才测试很可能浪费很多时间在无关地方。9.2 不推荐把所有节点都设置成同一台源并开启本地服务有些新手图省事会把每台机器都配上local stratum然后互相指向。一旦有两台机器同时开了local stratum而且各自的上游源临时失联就会发生“互相参考”的环路状态时间基准无法收敛。如果你只是想为内网提供时间服务确定合理的层级标注清楚谁是服务器谁是客户端是最稳妥的做法。9.3 关于公网NTP池的使用礼仪很多教程都会推荐pool.ntp.org但如果你有大量服务器不建议所有节点全部指向同一个公共池。公共池的负载均衡机制会自动把请求分散到多个服务器但它并不是无限容量。合理的做法是少数几台服务器访问公共池其余节点访问这几台内网服务器既减轻了公共池的压力也保证自身的同步质量。10. 顺手把监控环境的时区统一问题解决一下最后说一个和chrony配置配套的实际衍生问题。时间同步不仅指UTC还牵扯到每个服务读取时间的展示方式。很多应用默认读取系统本地时间系统时区如果五花八门有的是UTC、有的是Asia/Shanghai那么记录到日志里的时间戳就对不上。生产环境建议所有服务器统一使用UTC展示层单独做时区转换。这条建议听起来简单实际团队协作时会遇到很多阻力因为运维同学习惯看本地时间开发同学习惯看UTC。与其争论不如所有服务器统一UTC日志里强制带时区偏移字段这样任何人在任何地方看都能换算。chrony把底层的“时间基准”修好了上面的时区问题才能有干净的排查空间。如果时间基准不准时区转换再正确也无济于事。这也是我把这篇文章的重点放在同步机制和验证流程上的原因——它虽然基础却决定了整个系统的信息底座。配置chrony这个事看着简单真正实现稳定可靠同步还是有不少门道要摸索。我在这上面趟过的坑单列出来足够再写一篇故障排查实录了。核心原则始终就一条先确认同步源可达、再确认服务运行、最后用chronyc验证偏差值沿着这条链路走大多数问题都能定位到确切环节。