服务器集群里时间不一致会导致各种诡异故障,比如分布式事务超时、TLS证书校验失败、日志审计对不上时间线。Chrony是目前主流Linux发行版自带的时间同步服务,比旧版ntpd更轻量、收敛更快,尤其适合云主机和经常休眠的虚拟机。不过很多人配置Chrony时只写了上游服务器地址,忽略了step和slew两种时钟调整方式的差异,结果要么时间长时间不同步,要么同步时对业务造成瞬间冲击。

简单说,step是直接跳变,系统时钟一次性改成正确时间;slew则是通过微调时钟频率,让本地时钟逐渐追赶标准时间,每秒只变动很小的幅度。下面从配置文件和实际场景两条线把这件事讲透。
Chrony与NTP时钟同步基础
NTP协议的核心是客户端向多个时间服务器发送请求,根据往返延迟计算本地时钟与标准时间的偏差,然后修正本地时钟。Chrony通过chronyd守护进程和chronyc命令行工具完成这件事。它支持两种修正策略:step(步进)和slew(渐变)。
step会把系统时钟直接设置为参考时间,瞬时完成同步,偏差多大都能一次纠正。这种方式的优点是快,缺点是时间会出现不连续跳变。如果业务系统正在写数据库、记录日志或者做超时判断,时间突然回退或前进几秒,可能触发重复写入、主键冲突、心跳超时等意外。
slew则温和得多。Chrony不直接改时间,而是计算出一个频率调整值,让本地时钟在一段时间内走得稍快或稍慢,逐步消除偏差。比如本地时钟慢了0.6秒,Chrony可能让时钟每秒多走0.02秒,用30秒把偏差追平。整个过程时间保持单调连续,对业务几乎无感。代价是偏差较大时需要很长时间才能完成同步,而且持续调整期间时钟精度不如step后稳定。
Chrony配置文件中的step与slew参数详解
Chrony的配置文件通常位于/etc/chrony/chrony.conf(部分发行版为/etc/chrony.conf)。和step、slew相关的核心指令主要有以下几个,我们先看一张表格,再逐一说明。
| 参数 | 作用 | 示例 |
|---|---|---|
| makestep threshold limit | 当时间偏差超过threshold秒时,允许在前limit次更新中使用step;超过limit次后只允许slew | makestep 1.0 3 |
| maxslewrate rate | 限制slew的最大速率,单位是ppm(百万分之一),即每秒最多调整的秒数 | maxslewrate 83333 |
| maxupdateskew skew | 允许Chrony更新频率时的最大偏移,单位ppm,防止异常跳变 | maxupdateskew 1000 |
| driftfile path | 保存时钟漂移率文件,下次启动时快速进入稳定slew状态 | driftfile /var/lib/chrony/drift |
| rtcsync | 每11分钟把系统时间同步到硬件时钟RTC,保证重启后时间基本正确 | rtcsync |
makestep是最关键的参数。它的threshold值决定什么时候允许直接跳变。例如默认的makestep 1.0 3表示启动后前三次时钟更新中,如果偏差超过1秒就step;三次之后即使偏差再大也只能slew。很多管理员发现服务器运行几天后时间突然慢了几秒,Chrony却不直接纠正,就是因为已经超过了前三次更新限制,只能slew。如果把threshold设成0,则完全禁用step,全部走slew。
maxslewrate控制slew的速度上限。数值越大,时钟追平得越快,但过快也会让应用感知到时间变化速率异常。默认83333 ppm相当于每秒最多调整83.333毫秒,追平1秒偏差大约需要12秒。如果调成1000 ppm,追平1秒需要1000秒,更加平滑但耗时更长。生产环境一般不建议把maxslewrate调得过高,因为过于急促的频率变化可能导致某些依赖时间戳的程序误判。
driftfile非常重要。即使NTP服务器暂时不可达,Chrony也能根据历史漂移率继续维持较高的时间精度。建议始终配置该文件并确保chronyd用户有写权限。rtcsync则保证系统关机后硬件时钟不会差得太远,避免下次启动时偏差过大只能step。
step与slew如何选择与最佳实践
选择step还是slew,核心取决于业务对时间连续性的敏感程度。如果只是普通Web服务器、日志服务器,时间偶尔跳变几秒影响不大,可以保留较大的step阈值,让系统尽快同步。例如配置文件写makestep 1.0 3,既能快速纠正启动时的大偏差,又能在运行期间避免频繁step。
对于数据库集群、分布式存储、金融交易系统、实时计算平台,时间回退可能造成严重问题。这类场景应当尽量使用slew,只在偏差极小时允许step,甚至完全禁用step。推荐配置可以写成makestep 0.1 1,表示只有偏差在0.1秒以内才允许一次step,否则全部slew。如果系统时间本来就靠人工维持得比较准,可以直接设置makestep 0 0,让Chrony永远slew,同时适当提高maxslewrate到50000左右,保证偏差在可接受时间内追平。
还有一类情况:服务器刚克隆或刚从快照恢复,时间偏差达到几分钟甚至几小时。如果禁用step,slew可能需要几个小时甚至几天才能同步,这显然不可接受。正确做法是先手动执行chronyc makestep命令强制立即step,再让chronyd继续接管后续slew。这个命令可以在启动脚本中加入,但要注意执行时机,避免业务刚开始就受到时间跳变影响。
实际配置中,通用服务器的完整示例可以这样写:
server ntp1.ipipp.com iburst
server ntp2.ipipp.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
这里iburst表示启动后立即发送一组快速请求,加速首次同步。对于时间敏感系统,则把makestep改为0.1 1,再加maxslewrate 50000。无论哪种方案,都建议至少配置两个上游NTP服务器,并优先使用内网时间源或可靠的公共NTP池。
Chrony时间同步故障排查与验证
配置完成后,需要用chronyc命令验证同步状态。chronyc tracking可以查看当前系统时间偏差、最后一次偏移量、更新间隔等。重点关注System time这一项,如果数值在几十毫秒以内说明同步良好;如果一直是几秒甚至更大,说明Chrony没有成功同步,可能还在slew过程中,或者源不可达。
chronyc sources -v能列出所有配置的上游服务器及状态。输出中*表示当前正在使用的源,+表示可接受,?表示不可达、连接失败或认证错误。如果所有源都是?,先检查网络连通性和防火墙,NTP使用UDP 123端口,服务器端和客户端都要放行。再查看journalctl -u chronyd -f日志,通常会明确记录no reachable source或认证失败等错误。
另一个常见问题是ntpd和chronyd同时运行,两者互相干扰,导致时间来回跳变。可以用systemctl status chronyd和systemctl status ntpd确认,只保留其中一个服务。如果时间偏差过大而slew太慢,可以临时执行chronyc makestep,再观察chronyc tracking中的更新间隔是否正常缩短。长期运行时,driftfile文件是否存在、内容是否合理也值得检查。
最后提醒,时间同步不是配置一次就永远不用管。建议定期用chronyc sources检查上游源健康度,并在监控系统中加入时间偏移告警。保持配置简单、理解step和slew的边界,比堆砌一堆参数更有用。
Chrony时间同步NTP stepslew时钟同步修改时间:2026-09-29 00:38:24