《Linux 时间同步:chrony、NTP 与高精度时间实践》

系统讲解 Linux 时间同步:时间漂移的物理与软件成因、墙钟与单调钟的区别、NTP 分层(stratum)与选源原理、ntpd 与 chrony 的对比选型、chrony.conf 完整配置实战、PTP 高精度同步简介、systemd-timesyncd 与时区管理,以及监控验证与虚拟机、容器场景下的排错实践。

引言

分布式系统里,时间不一致比时间不准更致命:日志时间戳错位会让排查无从下手,Token 与证书校验失败会导致服务大面积 401,数据库主从延迟判断失真、分布式锁与共识算法直接崩溃。Linux 的时钟由硬件晶振驱动,天然存在漂移(drift),必须靠 NTP 之类的协议持续校正。

本文从时间漂移的成因讲起,厘清墙钟(CLOCK_REALTIME)与单调钟(CLOCK_MONOTONIC)的区别,介绍 NTP 的分层(stratum)与选源原理,对比 ntpd 与 chrony 并给出 chrony 的完整配置,再简介 PTP 高精度同步、systemd-timesyncd 与时区管理,最后落到监控验证与虚拟机、容器场景的排错实践。

前置:systemd 服务与单元管理。日志时间线一致性见 systemd-journald 与结构化日志,审计取证对时间的依赖见 Linux 安全加固与基线。


目录


1. 时间为什么重要:漂移、单调钟与墙钟

硬件晶振的频率随温度与老化漂移,普通服务器每天偏差几十到几百毫秒很正常——不校正就会累积成灾难。

漂移的来源分两类:

来源表现影响
晶振频率误差每天数十至数百 ms长期累积,需持续校正
温度与电压变化短期抖动影响同步精度
虚拟化时钟偏移跳变或变慢VM 中尤为明显
NTP 网络抖动毫秒级波动决定同步上限

Linux 有两套时钟,用途完全不同:

时钟系统调用特性用途
墙钟CLOCK_REALTIME可被 NTP 调整、可跳变日志时间戳、证书、Token
单调钟CLOCK_MONOTONIC只增不减、不受 NTP 影响超时、耗时测量、调度
启动钟CLOCK_BOOTTIME含休眠时间休眠感知的计时
# 查看墙钟与单调钟
date
cat /proc/uptime
# 查看当前时间源与同步状态
timedatectl
timedatectl timesync-status

关键原则:测量耗时永远用单调钟,记录时刻才用墙钟。用墙钟算耗时,一旦 NTP 回拨就会得到负数或巨大值。

一句话:墙钟管「几点」,单调钟管「多久」——混用二者是分布式系统里最隐蔽的一类 bug。


2. 时间同步原理:NTP 与 stratum

NTP 通过「客户端与服务器交换四个时间戳」估算网络往返延迟与时钟偏差,再渐进地调整本地时钟,而不是一次性跳变。

NTP 报文的四个时间戳:

T1 客户端发送时刻
T2 服务器接收时刻
T3 服务器发送时刻
T4 客户端接收时刻
偏差 offset = ((T2 - T1) + (T3 - T4)) / 2
延迟 delay  = (T4 - T1) - (T3 - T2)

时钟按「层级(stratum)」组织:stratum 0 是原子钟/GPS 等基准源,stratum 1 是直连基准源的服务器,stratum 2 从 stratum 1 同步,依此类推,层级越大精度越差。

stratum含义典型设备
0基准时钟原子钟、GPS 接收机
1直连基准公共 NTP 池中的一级服务器
2从 stratum 1 同步企业内网 NTP 服务器
3+逐级下传终端主机
16未同步不可用状态

时钟调整有两种方式:

# 一次性跳变(slew vs step)
# step:立即跳到正确时间(差异大时)
# slew:缓慢调整,避免时间倒退(差异小时)
chronyc makestep            # 手动触发一次步进

一句话:NTP 追求「不倒退的平滑校正」——正常运行靠 slew 微调,只有启动时偏差过大才 step 一次,避免时间倒退破坏依赖顺序的逻辑。


3. ntpd 与 chrony:选型对比

chrony 是为「不稳定的网络与虚拟化环境」设计的 NTP 实现,收敛更快、对间歇性联网更友好,已成为现代发行版默认。

维度ntpdchrony
收敛速度慢(数小时)快(数分钟)
时钟调整传统 PLL/FLL更精细的算法
间歇联网差好(适合笔记本/VM)
频率校正需持续运行支持保存 drift 文件
监控接口ntpqchronyc
默认发行版老系统RHEL 7+/Ubuntu 16.04+
资源占用略高更低
# 安装
apt install chrony          # Debian/Ubuntu
yum install chrony          # RHEL/CentOS
# 服务管理
systemctl enable --now chronyd
systemctl status chronyd
# 常用监控
chronyc tracking            # 同步状态
chronyc sources -v          # 时间源
chronyc sourcestats -v      # 源统计

一句话:新部署一律用 chrony——ntpd 已基本退出历史舞台,chrony 在虚拟机、容器、间歇联网场景下的表现全面胜出。


4. chrony 配置实战

chrony.conf 的核心是「指定时间源 + 允许谁同步 + 是否本地兜底」,其余都是精度调优。

# /etc/chrony.conf(RHEL 风格)
server ntp1.internal.example.com iburst   # 内网源优先
server ntp2.internal.example.com iburst
pool 2.pool.ntp.org iburst                # 公网兜底
driftfile /var/lib/chrony/drift           # 记录漂移率,加速收敛
makestep 1.0 3                            # 前 3 次偏差>1s 则步进
allow 10.0.0.0/24                         # 允许内网客户端
local stratum 10                          # 上游不可达时本地兜底
rtcsync                                   # 同步系统时间到 RTC
logdir /var/log/chrony
log measurements statistics tracking

关键指令说明:

指令作用
server指定单个时间源
pool指定一组源(自动解析多个 IP)
iburst启动时快速发送一组包,加快收敛
makestep 1.0 3前 3 次同步中偏差 >1s 则步进
driftfile保存频率偏差,加速重启收敛
allow允许哪些网段作为客户端
local stratum N上游不可用时以指定层级对外服务
rtcsync定期把系统时间同步到 RTC
# 修改配置后重载
systemctl restart chronyd
# 验证配置
chronyd -Q 'server ntp1.internal.example.com iburst'
chronyc sources -v
chronyc tracking

一句话:内网一定要有自己的 NTP 服务器 + allow 内网网段——所有主机直连公网 NTP 既不安全也不稳定,还会因出网抖动放大误差。


5. 选源策略与时间层级

时间源要「多点、就近、分层」:至少 3 个源做多数表决,内网分层减轻上游压力,避免所有主机打同一个源。

chronyc sources 输出解读:

chronyc sources -v
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* ntp1.internal.example     2   6   377    33    -12us[  -8us] +/-   89us
^+ ntp2.internal.example     2   6   377    35    +15us[ +20us] +/-   95us
^- 203.0.113.10              2   6   377    40   -120us[-115us] +/-   12ms
列含义
M模式(^ 服务器、= 对等、# 本地)
S状态(* 当前最优、+ 参与组合、- 未参与)
Stratum源所在层级
Poll轮询间隔(2 的幂秒)
Reach最近 8 次请求的成功位图(377 为全成功)
LastRx距上次收到响应秒数
Last sample上次测量的偏差

选源与分层策略:

# 企业内网分层示例
# 核心 NTP 服务器(stratum 2):同步公网池
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
allow 10.0.0.0/8
local stratum 10
# 终端主机:只同步内网 NTP
server ntp1.internal.example.com iburst
server ntp2.internal.example.com iburst

一句话:Reach 不是 377 就说明源在丢包——先看 Reach 和 Stratum 判断源是否健康,再看 Last sample 判断精度,最后才谈调优。


6. PTP:高精度时间同步简介

NTP 的精度上限在毫秒级,金融交易、电信、工业控制等场景需要微秒甚至纳秒级,于是有了 PTP(IEEE 1588)。

维度NTPPTP
精度毫秒级亚微秒至纳秒级
传输UDP/IP(通常)二层以太网或 UDP
硬件软件时间戳硬件时间戳(PHC)
拓扑任意主从(需交换机支持)
典型场景通用服务器金融、电信、工业

PTP 依赖网卡的硬件时间戳(PTP Hardware Clock)来消除软件栈抖动:

# 查看网卡是否支持硬件时间戳
ethtool -T eth0
# 查看 PHC 设备
ls /dev/ptp*
# 安装 linuxptp
apt install linuxptp
# 启动 ptp4l(主时钟同步)
ptp4l -i eth0 -m
# 启动 phc2sys(把 PHC 时间同步到系统时钟)
phc2sys -s eth0 -w -m
# /etc/linuxptp/ptp4l.conf(关键项)
[global]
clockClass 248
domainNumber 0
slaveOnly 1          # 本机作为从时钟

一句话:PTP 的精度来自硬件时间戳,不是协议本身——没有支持 PTP 的网卡和交换机,配再多参数也达不到微秒级。


7. systemd-timesyncd 与时区

systemd-timesyncd 是一个轻量 SNTP 客户端,够用但不精确,适合桌面与简单服务器;它只管墙钟,不提供 NTP 服务端能力。

# /etc/systemd/timesyncd.conf
[Time]
NTP=ntp1.internal.example.com ntp2.internal.example.com
FallbackNTP=0.pool.ntp.org 1.pool.ntp.org
RootDistanceMaxSec=5
# 启用与查看
timedatectl set-ntp true
timedatectl status
timedatectl timesync-status
systemctl restart systemd-timesyncd

注意:chrony 与 systemd-timesyncd 会争抢时钟,装了 chrony 就要关掉 timesyncd:

systemctl disable --now systemd-timesyncd

时区管理:

# 查看当前时区
timedatectl
# 列出可用时区
timedatectl list-timezones | grep Asia
# 设置时区
timedatectl set-timezone Asia/Shanghai
# 手动设置时间(不推荐,有 NTP 就别用)
timedatectl set-time "2026-10-04 12:00:00"
# 查看 RTC 与系统时钟
hwclock --show
hwclock --systohc      # 系统时钟写入 RTC
组件角色精度适用
chronyd完整 NTP 客户端+服务端毫秒服务器、内网时间源
ntpd传统 NTP毫秒老系统
systemd-timesyncd轻量 SNTP 客户端十毫秒级桌面、简单场景
ptp4lPTP微秒/纳秒金融、电信

一句话:chrony 与 timesyncd 二选一,绝不能同时开——两个客户端同时调整时钟会互相打架,导致时钟反复抖动。


8. 监控、验证与排错

时间问题的排查顺序:先确认服务在跑,再看有没有源,再看偏差多少,最后看为什么偏差大。

# 1. 服务状态
systemctl status chronyd
chronyc activity
# 2. 同步状态(关键指标)
chronyc tracking
# 3. 源是否可达
chronyc sources -v
chronyc sourcestats -v
# 4. 手动强制同步
chronyc makestep
# 5. 查看最近同步事件
journalctl -u chronyd -n 50

chronyc tracking 关键字段:

字段含义健康值
Reference ID当前时间源标识非 0
Stratum层级1~15
System time与源的时间偏差微秒~毫秒
Last offset上次调整量接近 0
RMS offset偏差均方根小
Frequency本机时钟频率偏差(ppm)稳定
Leap status闰秒状态Normal

常见故障与处理:

# 源不可达(Reach 全 0):查 DNS、UDP 123 防火墙、上游
dig ntp1.internal.example.com
nc -uz ntp1.internal.example.com 123
# 时间差过大拒绝同步:先手动步进一次
chronyc makestep
# Frequency 剧烈波动:多为虚拟机时钟源问题(见下节)

一句话:Reach 全 0 是「够不着」,Stratum 16 是「没同步」——先分清是网络问题还是配置问题,再决定是查防火墙还是改配置。


9. 生产实践:虚拟机与容器

虚拟化环境的时间同步要特别处理:VM 的时钟可能被 hypervisor 干预,容器则共享宿主机时钟——两者策略完全不同。

虚拟机场景:

# KVM/QEMU:使用 kvm-clock 时钟源
cat /sys/devices/system/clocksource/clocksource0/available_clocksource
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
# 应优先使用 kvm-clock / tsc
# VMware:安装 open-vm-tools 并启用时间同步
systemctl status vmtoolsd
vmware-toolbox-cmd timesync status

关键原则:不要在 VM 内同时用 NTP 和宿主机时间同步,二者会互相拉扯:

# VMware 场景:二选一
vmware-toolbox-cmd timesync disable    # 若 VM 内跑 chrony
# 或
systemctl disable --now chronyd        # 若依赖宿主机同步

容器场景:

# 容器默认共享宿主机的时钟命名空间
docker run --rm alpine date
# 因此容器内通常不需要、也不应该跑 NTP
# 若要独立时间命名空间(少见):
docker run --rm --cap-add SYS_TIME --privileged alpine \
  sh -c 'date -s "2026-10-04 12:00:00"'
场景时钟来源建议
物理机RTC + NTPchrony 同步公网/内网
KVM 虚拟机kvm-clock + NTP用 kvm-clock,chrony 微调
VMware宿主 + 可选 NTP二选一,勿双管齐下
容器宿主机不跑 NTP,靠宿主机
K8s 节点宿主机节点同步即可,Pod 无需
# 检查容器与宿主机时间是否一致
docker run --rm --pid=host alpine date
date

一句话:容器不管理时间,虚拟机避免双源——时间同步的职责边界要清晰,越权管理时钟比不同步更危险。


10. 速查表

需求命令
查看同步状态timedatectl / chronyc tracking
查看时间源chronyc sources -v
查看源统计chronyc sourcestats -v
强制步进chronyc makestep
手动指定源测试chronyd -Q 'server ntp.x iburst'
重启服务systemctl restart chronyd
设置时区timedatectl set-timezone Asia/Shanghai
启用 NTPtimedatectl set-ntp true
关闭 timesyncdsystemctl disable --now systemd-timesyncd
查看 RTChwclock --show
系统时间写 RTChwclock --systohc
检查时钟源cat /sys/devices/system/clocksource/clocksource0/current_clocksource
网卡硬件时间戳ethtool -T eth0
PTP 主同步ptp4l -i eth0 -m

一句话记忆:服务器一律 chrony,内网自建时间源并 allow 网段;Reach 看连通、Stratum 看层级、System time 看精度;VM 用 kvm-clock、容器靠宿主机;chrony 与 timesyncd 绝不共存。


延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「linux」更多文章

  1. 《Linux 故障排查工具箱:从 strace 到火焰图》
  2. 《磁盘加密与 LUKS 密钥管理实战》
  3. 《文本处理三剑客:grep、sed、awk 与 jq 实战》