文章总结: 本文系统介绍了Linux服务器时间同步的最佳实践,重点阐述了chrony作为新一代NTP客户端的优势,包括快速收敛、适合云和容器环境、支持NTS安全协议等。文章还详细说明了时钟源选择策略,推荐优先使用云厂商内网源,并介绍了闰秒涂抹等高级特性,为运维人员提供了从原理到实战的完整指南。 综合评分: 85 文章分类: 技术标准,解决方案
Linux 服务器时间同步(NTP/chrony)最佳实践
点击关注 👉 点击关注 👉
马哥Linux运维
2026年6月7日 14:00 广东
在小说阅读器读本章
去阅读
问题背景
时间同步是 Linux 运维里最容易被忽视、但一翻车就坑死一票业务的基础设施。生产里这些抱怨几乎每周都能听到:
- 业务方反馈”日志时间戳跟实际对不上”,排查事故时复盘会议直接卡在第一步。
- K8s 集群里
kube-apiserver报错x509: certificate has expired or is not yet valid,节点时间漂移几小时,证书根本没过期。 - MySQL 主从复制
Seconds_Behind_Master忽大忽小,磁盘和锁都正常,最后发现从库时间比主库快 5 秒。 - 凌晨跑批任务,crontab 莫名其妙没触发,第二天才发现服务器时间比现实时间慢了 6 小时。
- 同一台机器里
date和hwclock输出的时间差了好几小时,重启后一切又变回来。 - 容器里
date显示的是宿主机时间,但clock_gettime(CLOCK_MONOTONIC)跟宿主机不一致,部分用 monotonic clock 做逻辑的中间件直接行为异常。 - 等保 2.0 测评报告里被写了一条”未配置可信时间源”,要求限期整改。
- 双十一凌晨运维登录堡垒机,被强制下线,提示”登录时间异常”。
这些故障的根因几乎都指向一件事:服务器时间不可信。Linux 服务器的时间其实是一个由”硬件时钟(RTC)+ 内核维护的 system time + NTP 守护进程 + 时区配置 + 闰秒/跳秒策略”共同协作的小系统。任何一个环节没配好,都会出现上述现象。
这篇文章面向初中级运维 / 系统管理员 / DevOps 工程师,从原理到实战,把 chrony 这条主线讲透,覆盖单机、云服务器、容器、K8s 节点、自建 NTP 服务器、内网隔离等场景。看完之后能独立完成时间同步选型、配置、排查和合规落地。
适用读者
- 维护 Linux 服务器集群(物理机、虚拟机、云服务器、容器节点)的运维工程师。
- 排查过”时间跳变、日志错乱、证书校验失败、数据库主从延迟、K8s 节点 NotReady”问题的同学。
- 准备做等保 2.0、PCI-DSS、ISO 27001 等合规加固的工程师。
- 想从 ntpd 迁移到 chrony 或反过来评估的工程师。
- 想自建内网 NTP 服务器、减少对公网依赖的平台工程师。
适用场景
- 物理服务器、VMware 虚拟机、KVM 虚拟机、Hyper-V 虚拟机。
- 阿里云、腾讯云、华为云、AWS、Azure、GCP 等公有云 ECS / VM。
- 私有云、混合云、隔离网络。
- Docker 宿主、K8s node、K3s edge 节点。
- 自建 NTP 服务器(stratum-1 / stratum-2)。
- 金融、政企、医院、制造业等强合规行业。
- 数据库(MySQL、PostgreSQL、Redis、MongoDB)主从复制、分布式一致性场景。
- 分布式存储(HDFS、Ceph、MinIO)集群。
- 消息队列(Kafka、RocketMQ、RabbitMQ)集群。
- 证书体系(PKI、TLS、Kerberos、LDAP)环境。
核心知识点
时间的几个概念
系统时间(System Time / Software Clock)
由 Linux 内核维护的墙上时钟(wall clock),单位是自 1970-01-01 00:00:00 UTC 起的秒数 + 纳秒部分。所有 date、gettimeofday、time()、clock_gettime(CLOCK_REALTIME) 都读这个值。
系统时间由内核 tick 或 tickless 模式维护,本身没有”绝对意义”,完全靠 NTP/chrony 这种用户态守护进程不断校准。系统时间可以”跳变”(slewing 太慢时直接 settimeofday 改掉),但单调时钟不能跳变。
硬件时间(Hardware Clock / RTC)
主板上由电池供电的小芯片保存的时间,机器断电后依然走时。Linux 里通过 /dev/rtc0 访问,可以用 hwclock 命令读写。
- UTC 模式:硬件时间保存为 UTC,开机后操作系统按时区计算本地时间。推荐,跨时区服务器、集群、云服务器都应该用 UTC 模式。
- local 模式:硬件时间保存为本地时间,跨时区会错乱。除非有遗留系统对接 Windows 双系统遗留配置,否则不要用 local 模式。
可以用 timedatectl 查看 RTC in local TZ: no 确认。
单调时钟(CLOCK_MONOTONIC / CLOCK_BOOTTIME)
Linux 内核另一个时钟源,从某个未指定的起点开始单调递增,NTP 不会调整它。应用如果做超时、心跳、限流,应该用 monotonic clock,否则系统时间跳变(NTP 第一次同步时强制 step)会导致逻辑全乱。
clock_gettime(CLOCK_MONOTONIC, &ts) 是关键 API。K8s、etcd、RocksDB、LevelDB、Tokio 运行时、Rust 标准库等都依赖 monotonic clock。
UTC、本地时间、时区
- UTC(Coordinated Universal Time):世界统一时间,NTP 协议传递的就是 UTC。
- 本地时间(Local Time):UTC + 当前时区偏移 + 夏令时调整。
- 时区(Timezone):存放在
/etc/localtime(通常是/usr/share/zoneinfo/<区域>/<城市>的软链),可以用timedatectl set-timezone Asia/Shanghai改。
容器内 /etc/localtime 默认继承宿主,但 Pod spec 可以通过 volumeMounts 单独挂载。
NTP 协议基础
NTP(Network Time Protocol,RFC 5905)是 Linux 时间同步的事实标准协议,使用 UDP 123 端口。chrony 和 ntpd 都遵循这个协议,但实现上有差异。
几个关键术语
- stratum(层):时钟源距离”权威时钟源”的跳数。stratum-0 是原子钟、GPS 接收机这种硬件参考源;stratum-1 是直接连 stratum-0 设备的服务器;stratum-2 是从 stratum-1 同步的服务器,依此类推。stratum 越大误差越大,最大到 stratum-15,stratum-16 表示不可达。
- offset(偏移):本地时钟与上游时钟的时间差,单位一般是毫秒或微秒。
chronyc tracking里的System time就是当前估算的 offset。 - delay(延迟):NTP 请求/响应在网络上的往返时间。
chronyc tracking里的Root delay是到根时钟的总延迟。 - jitter(抖动):多次采样的 offset 方差,反映时钟稳定性。
chronyc tracking里的RMS offset与 jitter 类似。 - reach(可达性):一个 8 bit 的移位寄存器,记录最近 8 次 poll 是否有响应,全部成功是 377(八进制 0o377 = 255),
chronyc sources最后一列就是这个值。 - poll(轮询间隔):多久向源发一次请求,单位是 2 的幂秒。
chronyc sources -v里 Poll 列写的就是2^n里的 n,比如 6 表示 64 秒。 - refid(参考 ID):上游时钟的标识,IP 或 stratum-0 设备名。
- leap(闰秒状态):3 类,正常、插入一秒、删除一秒。2016 年和 2017 年初都出现过闰秒事件。
报文交互
简化流程:
- 客户端发 NTP request 给 server。
- server 在收到包时打上时间戳 T2,立刻发回 NTP response,里面带 T1(客户端发包时间,由客户端写入)、T2、T3(server 准备发包时间)。
- 客户端收到时记录 T4。
- 客户端通过
(T2 - T1) + (T4 - T3)算 round-trip delay,通过((T2 - T1) + (T3 - T4)) / 2算 offset。
这个简化模型假设网络对称,实际 chrony 会用更复杂的卡尔曼滤波估算 offset 和 jitter。
NTP 模式
- client/server 模式:最常用,客户端从服务器拉时间。
- symmetric 模式(mode 1/2):两个 server 互相同步,适合内网有多个 stratum-1 / 2 节点互备。
- broadcast 模式:server 周期性广播,客户端被动接收,适合大子网。
- manycast 模式:客户端发到多播组,最近的 server 应答,适合自动发现。
- pool 模式:
pool.ntp.org背后就是 DNS 轮询 + manycast 自动挑选健康源。
chrony 都支持。
chrony 与 ntpd 的取舍
优势对比
chrony 相对 ntpd 的优势:
- 启动后能更快收敛到正确时间(几秒 vs 几分钟)。
- 适合间歇性网络环境:笔记本、休眠、云服务器、容器节点、Wi-Fi 切换。
- 适合虚拟机和容器,clock skew 估算更准。
- 默认 slewing(微调),减少对应用的时间跳变。
- 配置文件更短,可读性更好。
- 自带 NTS(Network Time Security)支持,ntpd 集成较弱。
chronyc交互式体验好,ntpq略晦涩。
ntpd 相对 chrony 的优势:
- 历史悠久,几乎所有发行版都默认带,老系统更兼容。
- 严格遵循 RFC 5905,对老旧 NTP 设备兼容性更好。
- 文档、案例、调优经验更丰富。
- 第三方审计、安全加固资料多(ntpd 的历史漏洞、monlist 攻击等都有专门 mitigation)。
现状
- RHEL 8 / 9、CentOS Stream 8 / 9、Rocky、AlmaLinux、openEuler 默认就是 chrony。
- Ubuntu 18.04+、Debian 10+、SUSE 15+ 默认 chrony。
- 一些金融、政府、运营商老系统还在用 ntpd,主要是历史原因。
- 云厂商镜像(Aliyun、Tencent Cloud、华为云)默认都装 chrony。
- K8s 节点上,kubelet 不会强依赖 chrony 或 ntpd,但 kube-apiserver、metrics-server、cert-manager 对时间漂移非常敏感。
选择建议
- 新建集群、新建系统:直接 chrony。
- 遗留 ntpd 集群:能升级就升级,升级前在测试集群跑一遍 NTP 同步验证。
- 嵌入式、BusyBox、VyOS:chrony 也有包,ntpd 更紧凑,按需选择。
- 严格合规行业:chrony + NTS 即可,比裸 NTP 安全。
时钟源选择
公有云厂商时钟源
不同云厂商通常提供内网 NTP 入口,延迟低、稳定:
- 阿里云:
ntp.aliyun.com(内网ntp.cloud.aliyuncs.com,旧地址time1.aliyun.com)。 - 腾讯云:
time1.cloud.tencent.com、time2.cloud.tencent.com、time3.cloud.tencent.com、time4.cloud.tencent.com、time5.cloud.tencent.com。 - 华为云:
ntp.myhuaweicloud.com。 - AWS:默认
169.254.169.254提供 Amazon Time Sync Service(基于 atomic clock),EC2 推荐用这个。 - Azure:默认
time.windows.com但建议切到自己的time.nist.gov链路。 - GCP:默认
metadata.google.internal提供 Google 内部 NTP。
云上实例的 chrony 配置里把这些地址放前面,本地时钟源延迟通常 < 5 ms。
公网常见时钟源
pool.ntp.org:全球志愿者 NTP 池,自动轮询,按地域分配节点(0.cn.pool.ntp.org、1.asia.pool.ntp.org等)。time.cloudflare.com:Cloudflare 提供的 NTP,支持 NTS。time.google.com:Google 公共 NTP。time.apple.com:Apple 公共 NTP。
公网源的延迟通常 5-50 ms,受国际出口影响大。金融、政企、涉密网络不建议直接用公网源。
内网自建 NTP 服务器
推荐分层架构:
GPS / 北斗 / 原子钟(stratum-0 设备)
↓
Stratum-1 服务器(内网核心机房,1-2 台做 HA)
↓
Stratum-2 服务器(每个区域机房,2-4 台做 HA)
↓
业务服务器 / 容器节点 / 数据库 / 存储
stratum-1 服务器可以用:
- 树莓派 + GPS 模块 + PPS(精度好,成本低)。
- 商业 NTP 接收机(Meinberg、Symmetricom、Trimble)。
- PTP(IEEE 1588)转 NTP 网关。
- 公有云厂商的内网 NTP(很多银行 / 券商直接用,节省成本)。
闰秒、stepping、slewing
闰秒(Leap Second)
UTC 和 UT1(基于地球自转的时间)有累积差异,IERS 会不定期宣布在 6 月 30 日或 12 月 31 日最后一秒插入或删除 1 秒。最近一次是 2016-12-31,2017-01-01 多了 23:59:60 这一秒。
Linux 处理闰秒的方式:
- 内核标记:内核打上 leap flag,应用读取时间后会看到 23:59:60。
- 步进(step):
chronyc makestep或 ntp 某些版本会直接让时间跳 1 秒。 - 涂抹(smear):Google、Meta(Facebook)、Cloudflare、AWS 都用”闰秒涂抹”,把 1 秒均匀分摊到 24 小时内,绕开 23:59:60 的问题。chrony 可以配置
leapsecmode slew/slew/step/ignore,也可以配smeartime启用涂抹。
Stepping vs Slewing
- slewing:chrony 默认做法,按 0.5 ms/s 或更慢的速度调整 system time(通过
adjtimex),应用感知不到。优点是不会导致时间跳变;缺点是大偏移收敛慢。 - stepping:直接把 system time 改到目标值(通过
settimeofday)。会跳变,数据库、分布式系统、定时任务会出问题。chrony 只在 offset 超过makestep阈值(默认 1 秒)时才 step,或者首次启动时强制 step。 - mktime/clock_gettime 注意事项:应用如果缓存了时间差(如 token TTL、HTTP Expires 头),step 会导致缓存的差值错乱。
chrony 推荐配置:makestep 1.0 3(offset > 1 秒且前 3 次更新才 step),之后再 slewing。生产里可以根据情况改阈值。
chrony 的体系结构
chronyd 是守护进程,负责同步、维护本地时间、调整 RTC。chronyc 是用户态控制工具。
chronyd 启动流程:
- 读取
/etc/chrony.conf(RHEL 系)或/etc/chrony/chrony.conf(Debian 系)。 - 初始化时钟源、refclock、sourcestats、rtsvars。
- 启动后立刻尝试 step 系统时间(如果和上游差距大)。
- 持续轮询上游、估算 offset / delay / jitter、slewing 调整。
chronyd 还会:
- 定期把 system time 同步到 RTC(
rtcsync指令)。 - 提供 NTP server 服务给其他客户端(
allow+local指令)。 - 维护
chrony.measure/tracking/sources/sourcestats等状态。
chrony.conf 常用指令
按功能分组介绍。
上游时钟源
pool pool.ntp.org iburst maxsources 4
server time1.aliyun.com iburst
peer ntp01.internal iburst
refclock SHM 0 offset 0.5 delay 0.2
pool解析为多个 IP,chrony 会从里面挑。server写死一个 IP。peer互相同步(symmetric 模式)。refclock用共享内存或 PPS 设备,适合自建 stratum-1。iburst启动时连续发 8 个包快速收敛。minpoll/maxpoll控制轮询间隔,如minpoll 4 maxpoll 10表示 16 秒到 1024 秒之间浮动。prefer优先选这个源。trust信任这个源。xleave/nts启用 NTS / interleave 模式。
访问控制
allow 192.168.0.0/16
allow 10.0.0.0/8
deny 0.0.0.0/0
同步行为
makestep 1.0 3
rtcsync
leapsecmode slew
smeartime 86400
客户端
local stratum 10
manual
local 表示本机即使没连到上游,也对外宣告自己是 stratum-10,集群内统一时间。manual 配合 chronyc settime 手动校准,但生产里慎用。
日志
log tracking measurements statistics
logdir /var/log/chrony
mailonchange [email protected] 0.5
chronyc 工具
常用子命令:
chronyc tracking:综合状态。chronyc sources -v/chronyc sources:列出源。chronyc sourcestats -v:每个源的统计。chronyc activity:最近 N 次 poll 的情况。chronyc ntpdata:详细 NTP 报文。chronyc waitsync 30 0.01:最多等 30 秒,offset 收敛到 0.01 秒以内。chronyc makestep:强制 step。chronyc tracking -p:显示偏移。chronyc clients:列出连到本机的客户端(仅 server 模式)。chronyc serverstats:server 模式下的请求统计。- `chronyc delete“:移除某个源。
chronyc add server``<addr>:临时加一个源(不写配置文件)。chronyc accheck:检查 NTS 认证。chronyc certif / cacert:NTS 证书管理。chronyc -a makestep(systemd 环境):通过控制 socket 让守护进程 step。
chronyc 还有交互模式,输入 chronyc 回车进 prompt,help 列出所有子命令。
环境准备
硬件
- 至少 1 核 CPU、512 MB 内存、100 MB 磁盘就能跑 chrony。
- 内网 NTP 服务器建议用物理机(不带虚拟化),时钟稳定性最好。树莓派 + GPS 也是经典方案。
- 服务器时钟源需要支持高频中断:现代 x86 服务器一般没问题,老旧 ARM 板卡要注意。
网络
- UDP 123 端口:NTP 协议默认端口。客户端要能出站到上游 server,server 要能监听入站。
- TCP 4460 端口:NTS(Network Time Security)需要。
- 出入站都建议放通。云服务器要注意安全组规则。
- NTP 反射放大攻击:chrony 默认不开
monlist响应,比 ntpd 安全得多,但仍建议用restrict限制源 IP。
操作系统
- RHEL 7 / 8 / 9、CentOS 7 / Stream 8/9、Rocky Linux、AlmaLinux、openEuler 20/22/24、Anolis OS。
- Ubuntu 18.04 / 20.04 / 22.04 / 24.04。
- Debian 10 / 11 / 12。
- SUSE 12 / 15、openSUSE Leap。
- 国产 UOS、麒麟、统信 Deepin。
内核要求:Linux 3.10+ 都没问题,2.6.32 老内核也支持 chrony 3.x / 4.x。
chrony 版本
- chrony 1.30 / 2.x / 3.x:老版本,常见于 CentOS 7、Ubuntu 16。
- chrony 4.x:当前主流,RHEL 9、Ubuntu 22.04 默认。
- chrony 4.2+:开始支持 NTS 加密。
可以用 chronyd -v 或 chronyc --version 查看。
实战步骤
第 1 步:现状摸底
在动手改任何配置之前,先摸清楚当前状态,避免改了反而把生产搞乱。
查看系统时间、时区、RTC
date
date -u
timedatectl
hwclock
hwclock --utc
hwclock --localtime
timedatectl 输出关键字段:
Local time:当前系统时间。Universal time:UTC 时间。RTC time:硬件时间。Time zone:时区。System clock synchronized:是否同步过。NTP service:是否启用了 systemd-timesyncd / chrony / ntpd。RTC in local TZ:硬件时钟是否是 local 模式(应该为 no)。
查看 NTP 服务
systemctl status chronyd
systemctl status ntpd
systemctl status systemd-timesyncd
chronyc tracking
chronyc sources -v
chronyc sourcestats -v
chronyc activity
判断 NTP 是否在工作
chronyc tracking 输出关键字段解读:
Reference ID:上游源标识。Stratum:当前 chronyd 估算的 stratum。System time:当前 system time 与估算真实时间的偏差(带正负号)。Last offset:上一次调整时的 offset。RMS offset:长期 offset 的均方根,反映稳定性。Frequency:本地时钟的频率漂移(ppm)。Residual freq:残差频率。Skew:频率估算的方差。Root delay:到根时钟的总延迟。Root dispersion:到根时钟的总离散度。Update interval:更新间隔。Leap status:闰秒状态(Normal / Insert second / Delete second)。
健康标准:
System time绝对值 < 100 ms(公网)/ < 1 ms(内网)。Last offset绝对值 < 1 秒。RMS offset绝对值 < 1 秒。Frequency在 0 ppm 附近 ± 50 ppm。Leap status是Normal。
chronyc sources -v 输出关键列:
^*:当前选中的源。^+:候选源。^-:备份源。=?:未确认可达性。~:高抖动 / 不稳定。M:异常状态。x:被拒绝。*:手工指定。MS:接收异常。Reach:最后 8 次 poll 的成功次数(八进制)。
健康源:^* 或 ^+,Reach = 377,Last rx 距现在 < 2 个 poll 间隔。
chronyc sourcestats 输出当前 offset、jitter、reach、stability 等长期统计。
查看 NTP 端口
ss -ulnp | grep 123
netstat -ulnp | grep 123
chronyd 监听 0.0.0.0:123 还是 127.0.0.1:123 决定了是否对外提供 NTP 服务。
抓包确认
tcpdump -i any -n udp port 123 -c 20
看是否有 NTP 请求/响应,源/目的 IP 是否符合预期。
收集完这些信息,记到表格里
| 主机名 | 时区 | RTC | chrony 版本 | 上游 | offset | reach | 备注 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| web-01 | Asia/Shanghai | UTC | 4.1 | time1.aliyun.com | +0.3ms | 377 | 健康 |
| db-01 | Asia/Shanghai | UTC | 4.1 | time1.aliyun.com | -2.1s | 0 | 不可达 |
这一步是后面排查和验收的依据,不要省略。
第 2 步:时区配置
查看时区
timedatectl
ls -l /etc/localtime
cat /etc/timezone
修改时区
sudo timedatectl set-timezone Asia/Shanghai
sudo timedatectl set-timezone UTC
sudo timedatectl set-timezone Europe/Berlin
Asia/Shanghai、UTC、Europe/Berlin 等是 IANA 时区数据库标准名,存在 /usr/share/zoneinfo/ 目录里。
RTC 同步模式
sudo timedatectl set-local-rtc 0
set-local-rtc 0 表示硬件时钟存 UTC;1 表示存 local time。生产环境强烈建议 0。
验证
timedatectl
date
date -u
hwclock --show --utc
容器内时区
容器 /etc/localtime 默认继承宿主机。如果要让容器用别的时区:
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
image: my-app:1.0
volumeMounts:
- name: tz-config
mountPath: /etc/localtime
volumes:
- name: tz-config
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
type: File
或者在 Dockerfile 里 ENV TZ=Asia/Shanghai + RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone。但容器镜像里塞时区文件不如直接挂宿主。
应用层时区
JVM 应用:-Duser.timezone=Asia/Shanghai 或 TZ 环境变量。 Python:os.environ['TZ'] + time.tzset()。 Node.js:TZ 环境变量。 MySQL:time_zone 参数 + CONVERT_TZ。
容器内推荐把所有应用统一到 UTC,业务层按需转换。这样跨地域、跨集群、跨云排查日志时不会因为时区搞错。
第 3 步:chrony 安装
RHEL 9 / Rocky 9 / AlmaLinux 9 / CentOS Stream 9
sudo dnf install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
RHEL 8 / CentOS 8 / Rocky 8 / AlmaLinux 8
sudo dnf install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
CentOS 7 / RHEL 7
sudo yum install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
CentOS 7 上默认 chrony 3.4,能用但没 NTS。如需 NTS,需要 chrony 4.0+。
Ubuntu 22.04 / 24.04
sudo apt update
sudo apt install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
Ubuntu 22.04 默认 chrony 4.2+,自带 NTS。
Ubuntu 20.04
sudo apt update
sudo apt install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
Debian 11 / 12
sudo apt update
sudo apt install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
openEuler 20.03 / 22.03
sudo dnf install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
验证安装
chronyd -v
chronyc --version
rpm -q chrony
dpkg -l | grep chrony
第 4 步:上游时钟源选择与配置
按场景给几套配置模板。
模板 1:内网 + 公有云兜底(推荐大部分云服务器用)
# /etc/chrony.conf
# 优先用内网自建 NTP server
server ntp01.internal iburst prefer
server ntp02.internal iburst
# 公有云厂商作为兜底
server ntp.aliyun.com iburst
server time1.cloud.tencent.com iburst
# pool
pool pool.ntp.org iburst maxsources 4
# 启动时如果 offset > 1 秒,连续 3 次更新内允许 step
makestep 1.0 3
# 把系统时间同步到硬件时钟
rtcsync
# 硬件时钟调整间隔
rtcautotrim 30
# 同步到 RTC 的时间
hwclockfile /etc/adjtime
# 允许的客户端网段
allow 192.168.0.0/16
allow 10.0.0.0/8
# 默认拒绝其他来源
deny 0.0.0.0/0
# 拒绝所有 IPv6 来源
deny ::/0
# 日志
log tracking measurements statistics
logdir /var/log/chrony
模板 2:纯内网隔离环境(不连外网)
# /etc/chrony.conf
# 只用内网 NTP server
server ntp01.internal iburst prefer
server ntp02.internal iburst
server ntp03.internal iburst
# 上游不通时,本机仍然能对外提供服务
local stratum 10
makestep 1.0 3
rtcsync
allow 10.0.0.0/8
deny 0.0.0.0/0
deny ::/0
log tracking measurements statistics
logdir /var/log/chrony
模板 3:内网 NTP Server(自建 stratum-1 / 2)
# /etc/chrony.conf
# 这一台是 server 模式,对客户端提供服务
# 自身从上游同步(GPS、北斗、原子钟、或者内网根 server)
server ntp-master01.internal iburst prefer
server ntp-master02.internal iburst
# 允许客户端网段
allow 192.168.0.0/16
allow 10.0.0.0/8
allow 172.16.0.0/12
deny 0.0.0.0/0
deny ::/0
# 自身不睡醒调整 RTC,由其他机器负责
rtcsync
# 上游不可用时,自己作为 fallback
local stratum 10
log tracking measurements statistics
logdir /var/log/chrony
模板 4:NTS(Network Time Security)加密模式
# /etc/chrony.conf
# 需要 chrony 4.2+
server time.cloudflare.com iburst nts
server ntp.nts.sjtu.edu.cn iburst nts prefer
server ntp1.nts.lu iburst nts
makestep 1.0 3
rtcsync
# 限制外网访问,只允许自己出站
deny all
NTS 需要服务端支持,目前 Cloudflare、NIST、Some university 公开 NTP/NTS 节点。生产里更常见的做法是自建 NTS server:
# /etc/chrony.conf
ntsserverkey /etc/chrony/keys/ntp-server.key
ntstrustedcerts /etc/chrony/certs
模板 5:K8s 节点专用
# /etc/chrony.conf
# K8s 节点时间精度要求高(证书、metrics-server、kube-apiserver)
server ntp01.internal iburst prefer
server ntp02.internal iburst
server ntp.aliyun.com iburst
makestep 1.0 3
rtcsync
# 允许 Pod 共享 /dev/ptp 之类的设备
# 不需要 allow,因为 K8s 节点自身就是 client
deny all
# 关闭查询日志
log measurements statistics
logdir /var/log/chrony
模板 6:容器 / 边缘设备
# /etc/chrony.conf
# 适合间歇性网络、Wi-Fi 切换、4G 边缘盒子
pool pool.ntp.org iburst maxsources 4
server time1.aliyun.com iburst
makestep 1 1
rtcsync
# 边缘设备通常没有 RTC 持久化
# 需要时开启 fakehwclock
模板 7:NTP 反射攻击防御
# /etc/chrony.conf
# 限制哪些客户端能查询本机
allow 10.0.0.0/8
deny 0.0.0.0/0
# 不响应 monlist
noclientlog
# 限制每个客户端的查询频率
ratelimit interval 3 burst 8
chronyc clients 可以看当前连到本机的客户端。
第 5 步:重启和验证
修改完 /etc/chrony.conf 之后:
sudo systemctl restart chronyd
sudo systemctl status chronyd
chronyc tracking
chronyc sources -v
chronyc sourcestats -v
chronyc activity
看到 System time 收敛到合理范围(内网 < 1 ms,公网 < 50 ms),chronyc sources 状态列出现 ^*(主源),Reach 达到 377,就说明同步成功了。
chronyc waitsync 60 0.001 可以让 chrony 主动等到 offset < 1 ms:
chronyc waitsync 60 0.001
返回 0 表示成功,非 0 表示超时或异常。
第 6 步:日志和监控
日志
chrony 默认日志比较安静。要看更多细节:
# /etc/chrony.conf
log tracking measurements statistics
logdir /var/log/chrony
常用日志文件:
tracking.log:每个 update interval 的 offset / frequency。measurements.log:原始 poll 测量。statistics.log:长期统计。temp.log:临时错误信息。
日志可以接入 rsyslog、ELK、Loki 等。
监控指标
chrony 自身没有内置 Prometheus exporter,但可以用以下几种方式接入:
chrony_exporter:第三方开源项目,提供chrony_offset_seconds、chrony_frequency_ppm等指标。node_exporter自带的node_timex_*指标。- 自定义脚本,从
chronyc tracking解析。
示例 exporter 指标:
chrony_offset_seconds
chrony_frequency_ppm
chrony_skew_ppm
chrony_root_delay_seconds
chrony_root_dispersion_seconds
chrony_leap_status
chrony_leap_status 0 = Normal、1 = Insert second、2 = Delete second、3 = Not synchronized。
Prometheus 告警规则示例:
groups:
- name: chrony
rules:
- alert: ChronyOffsetTooLarge
expr: abs(chrony_offset_seconds) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "主机 {{ $labels.instance }} 时间偏移过大"
description: "offset = {{ $value }} s"
- alert: ChronyNotSynced
expr: chrony_leap_status == 3
for: 1m
labels:
severity: critical
annotations:
summary: "主机 {{ $labels.instance }} NTP 未同步"
阈值的具体数值需要结合业务基线,不能照搬。
第 7 步:K8s 集群时间同步
K8s 集群对时间同步要求很高:
kube-apiserver颁发的证书有开始/结束时间,节点时间不对证书直接报错。metrics-server拿 kubelet 数据,时间错位会导致 HPA 误判。etcd集群对时间敏感,时间漂移会导致 leader election 异常。kube-scheduler涉及时间戳。- 日志、audit log 顺序依赖时间。
K8s 节点配置推荐
# /etc/chrony.conf
server ntp01.internal iburst prefer
server ntp02.internal iburst
server ntp03.internal iburst
makestep 1.0 3
rtcsync
# 不要 allow,节点自身不向外提供 NTP
deny all
# 日志
log measurements statistics
logdir /var/log/chrony
K8s 节点时间检查
for n in $(kubectl get nodes -o name | cut -d/ -f2); do
echo "== $n =="
kubectl debug node/$n -it --image=busybox -- \
date -u
done
或用 Node Problem Detector(NPD)的时间漂移检测插件。
容器内时间
容器默认共享宿主 system time,不需要额外配置。但有些场景需要单独校准:
- 容器内应用的
time()API 走的是clock_gettime(CLOCK_REALTIME),返回宿主时间。 - 容器内 monotonic clock 是容器进程启动后的单调时间,不是宿主启动时间。
- 如果应用对 monotonic clock 起点有依赖(一般没有),可能会被混淆。
容器 time namespace 是 K8s 1.27+ 的 alpha 特性,可以让 Pod 有独立的时间视图。生产慎用。
物理机云上 K8s
云厂商的 K8s(ACK、TKE、EKS、GKE)会自动用云厂商的 NTP 服务,节点时间通常很准。但建议仍然配内网 NTP server 作为冗余。
第 8 步:故障排查
故障 1:chronyc sources 显示所有源都是 ^? 或 ^x
可能原因:
- 防火墙阻挡 UDP 123。
- 上游 NTP server 不通。
- DNS 解析不到(pool、域名)。
- restrict 配置错误。
排查步骤:
# 1. 测网络
ping ntp.aliyun.com
nc -uv ntp.aliyun.com 123
# 2. 测端口
nmap -sU -p 123 ntp.aliyun.com
# 3. 抓包
tcpdump -i eth0 -n udp port 123 -c 20
# 4. 看 chronyc
chronyc activity
chronyc ntpdata
修复:
- 防火墙放行 UDP 123 出站。
- 改用 IP 地址不用域名。
- 检查上游是不是真的活着。
故障 2:offset 一直跳变(±几秒)
可能原因:
- 源不稳定(公网源丢包率高)。
- 主机 CPU 被打满,poll 间隔超时。
- 虚拟机时间被 hypervisor 干扰。
rtcsync写 RTC 太频繁。
排查:
# 1. 看 CPU
top
vmstat 1 5
# 2. 看 jitter
chronyc sourcestats -v
# 3. 看 reach
chronyc sources -v
# 4. 切到不同源
chronyc delete ntp.aliyun.com
chronyc add server time.google.com iburst
修复:
- 换更稳定的源。
- 加大
maxpoll减少 poll 频率。 - 关掉其他争用 CPU 的进程。
- 检查 KVM / VMware Tools / Hyper-V 集成服务是否在干扰时钟。
故障 3:chronyc tracking 显示 System time 永远 ~0,但 date 偏差大
可能原因:
- chrony 同步的是 internal “kernel time”,但
settimeofday调用被 seccomp 拦了。 - 应用通过自己的方式改了 system time。
排查:
strace -f -e trace=clock_settime,settimeofday,adjtimex -p $(pidof chronyd)
故障 4:机器重启后时间错乱
可能原因:
- 硬件时钟(RTC)漂移严重。
- 操作系统没有把 system time 同步回 RTC。
rtcsync没开。
修复:
# 同步 system time 到 RTC
sudo hwclock --systohc --utc
# 检查 adjtime 文件
cat /etc/adjtime
# 0.000000 1700000000 0.000000
# 1700000000 UTC
# /etc/chrony.conf 里加
rtcsync
故障 5:容器内时间漂移
可能原因:
- 容器没特权但尝试改时间。
- fakehwclock 没启用。
- 容器 runtime 阻止时间调整。
修复:
- 加
CAP_SYS_TIMEcapability。 - 用
bind mount共享宿主 /dev/ptp。 - 启用 fakehwclock。
- K8s 中加
securityContext.capabilities.add: ["SYS_TIME"](生产慎用)。
故障 6:双 NIC 多 IP 节点时间不同步
可能原因:
- chrony 默认从所有接口收 NTP 包,路由表会选一个源 IP 发包。
- 多 IP 节点上策略路由可能阻断。
修复:
# /etc/chrony.conf
bindaddress 192.168.1.10
把 chrony 绑到特定 IP。
故障 7:chronyd 启动失败
排查:
sudo journalctl -u chronyd -n 50
sudo chronyd -f /etc/chrony.conf -d
-d 调试模式打印所有内部状态。
故障 8:reach 一直是 0
可能原因:
server配置错了 IP。- 上游 NTP server 不监听 UDP 123。
- 防火墙双向都关了。
修复:
# 手动测
sudo ntpdate -q ntp.aliyun.com
注:ntpdate 在新系统已经被 chrony / ntpsec 替代,CentOS 7 后基本没有。
第 9 步:风险与回滚
风险 1:改了 chrony.conf 后同步失败
回滚:
# 备份
sudo cp /etc/chrony.conf /etc/chrony.conf.bak.$(date +%Y%m%d)
# 改回旧配置
sudo cp /etc/chrony.conf.bak.20260605 /etc/chrony.conf
# 重启
sudo systemctl restart chronyd
# 验证
chronyc tracking
风险 2:上游源时间不准,导致集群时间整体漂移
现象:所有节点都”看起来同步了”,但都偏 10 秒。
排查:
chronyc tracking
# Reference ID 不是你预期的源
修复:
- 切到可信源。
- 强制 step:
chronyc makestep。
风险 3:强制 step 导致业务故障
风险高的场景:
- 数据库主从:主从可能短暂不一致。
- 分布式系统:lease 过期、心跳失联。
- 证书校验:依赖时间戳的 token / cookie 失效。
应对:
- 用
makestep 1.0 3控制 step 频率。 - 改成 slewing(默认)。
- 业务层用 monotonic clock。
风险 4:chronyd 停服后系统时间缓慢漂移
# 看漂移
sudo systemctl stop chronyd
sleep 60
date
date
# 差几秒就说明硬件时钟漂移
应对:
- 保持 chronyd 持续运行。
- K8s 节点上 chronyd 容器 / systemd unit 不能停。
风险 5:K8s 节点时间漂移导致 cert-manager 续签失败
现象:证书过期、cert-manager Job 报错。
修复:
# 临时强制同步
sudo chronyc makestep
sudo systemctl restart chronyd
长期:
- 配多个上游源。
- 加 Prometheus 告警。
风险 6:UTC 模式 + 多时区管理员误判时间
有些运维习惯看 date 不带 -u,看到北京时间。容器 / 服务器混部时容易混。
建议:
- 服务器统一 UTC,应用按需转换。
- 日志统一 UTC 时间戳。
- 内部约定”我们看 UTC,业务方看本地”。
风险 7:自建 NTP Server 时间源硬件故障
应对:
- 至少 2 台 stratum-1 服务器做主备。
- GPS / 北斗接收机双机热备。
- 监控 stratum-1 偏移量告警。
第 10 步:合规与等保
等保 2.0 中关于时间同步的条款:
- 应当在网络边界、重要网络节点进行安全审计,审计覆盖到每个用户。
- 应对分散在各个设备上的审计数据进行收集集中存储和集中分析。
- 应能对网络行为、主机行为、应用行为等进行时间戳标记,时间源应可信。
实操建议:
- 所有服务器配置 NTP,时间源至少包含 2 个独立源。
- 部署内部 NTP 服务器,连接国家级时间源(北斗 / GPS / 国家授时中心 / 国家时间频率计量中心)。
- 日志带时间戳,统一 UTC。
- 周期性审计:
chronyc tracking截图。chronyc sources -v截图。- 配置文件 diff。
- 自动化检查脚本(下面会给)。
合规检查脚本(Ansible 示例)
# /etc/ansible/playbooks/chrony-check.yml
- name: 检查 NTP 配置
hosts: all
gather_facts: yes
tasks:
- name: 确认 chronyd 在运行
systemd:
name: chronyd
state: started
enabled: yes
register: chrony_status
- name: 收集 chrony tracking
command: chronyc tracking
register: tracking
changed_when: false
- name: 收集 chrony sources
command: chronyc sources -v
register: sources
changed_when: false
- name: 输出报告
debug:
msg: |
主机: {{ inventory_hostname }}
跟踪: {{ tracking.stdout }}
源: {{ sources.stdout }}
合规检查脚本(Bash 示例)
#!/usr/bin/env bash
# /usr/local/bin/chrony-audit.sh
# 检查所有受控主机的 NTP 状态
LOG_DIR=/var/log/chrony-audit
mkdir -p "$LOG_DIR"
REPORT="$LOG_DIR/audit-$(date +%Y%m%d).log"
for host in $(cat /etc/hosts.list); do
echo "=== $host ===" >> "$REPORT"
ssh -o StrictHostKeyChecking=accept-new "$host" \
'chronyc tracking; echo "---"; chronyc sources -v' \
>> "$REPORT" 2>&1
done
# 找 offset > 1 秒的主机
grep -B1 -E "System time.*-?\d+\.\d{6} seconds" "$REPORT" \
| awk '/^=== / {host=$2} /System time/ {
val=$4
if (val+0 > 1.0 || val+0 < -1.0) print host": offset "val" 秒超限"
}'
# 找未同步的主机
grep -B5 "Leap status : Not synchronized" "$REPORT" \
| awk '/^=== / {print $2": 未同步"}'
批量配置管理
用 Ansible / SaltStack / Puppet 批量分发 /etc/chrony.conf:
# ansible: roles/chrony/tasks/main.yml
- name: 安装 chrony
package:
name: chrony
state: present
- name: 分发配置文件
template:
src: chrony.conf.j2
dest: /etc/chrony.conf
owner: root
group: root
mode: '0644'
notify: restart chronyd
- name: 启动并开机自启
service:
name: chronyd
state: started
enabled: yes
Jinja2 模板按环境区分:
# ansible: roles/chrony/templates/chrony.conf.j2
{% if env == 'prod' %}
server ntp01.prod.internal iburst prefer
server ntp02.prod.internal iburst
{% elif env == 'dev' %}
server ntp01.dev.internal iburst
server ntp.aliyun.com iburst
{% endif %}
makestep 1.0 3
rtcsync
allow {{ ntp_allow_net }}
deny 0.0.0.0/0
deny ::/0
log tracking measurements statistics
logdir /var/log/chrony
第 11 步:进阶方向
NTS(Network Time Security)
NTS 是 IETF RFC 8915 定义的 NTP 加密扩展,目标是解决 NTP 流量被篡改、伪造的问题。
chrony 4.2+ 原生支持。配置:
server time.cloudflare.com iburst nts
server ntp.nts.sjtu.edu.cn iburst nts
可以用 chronyc accheck 查看认证状态。
PTP(IEEE 1588 Precision Time Protocol)
金融交易、5G、工业控制场景需要微秒甚至纳秒级时间同步。PTP 适合这些场景。
chrony 4.x 增加了 PTP 支持(refclock PHC),可以把 PTP 主时钟时间同步到系统时间。
GPS / 北斗 + chrony
自建 stratum-1 经典方案:
- GPS 模块:u-blox NEO-M8N、Neo-6M,性价比高。
- 北斗模块:UM220、AT6558R,国内合规友好。
- PPS 信号:从 GPS 出来的高精度秒脉冲,连到树莓派 GPIO。
- chrony 配
refclock PPS /dev/pps0+refclock SHM 0。
# /etc/chrony.conf
refclock PPS /dev/pps0 lock GPS
refclock SHM 0 offset 0.5 delay 0.2 refid GPS
Stratum-1 自建清单
- 树莓派 4B / 5 + GPS 模块 + PPS 天线。
- 恒温晶振(OCXO)板卡,可选。
- chrony 4.x + gpsd。
- 至少 2 台做主备。
- 监控:用 chrony_exporter 抓
chrony_stratum等指标。
时间同步 + 监控告警组合
- Prometheus 抓 chrony_exporter。
- Grafana 看板:offset、reach、stratum、leap status、frequency 趋势。
- Alertmanager 告警:offset > 100 ms、reach = 0、leap status != Normal。
常用命令清单
时间查看
date
date -u
date '+%Y-%m-%d %H:%M:%S.%N'
date -d @1700000000
date -d '2026-06-05 10:00:00 UTC' +%s
hwclock
hwclock --show --utc
hwclock --show --localtime
hwclock --systohc --utc
hwclock --hctosys --utc
timedatectl
timedatectl status
cat /etc/timezone
ls -l /etc/localtime
zdump -v /usr/share/zoneinfo/Asia/Shanghai
chrony 服务
systemctl start chronyd
systemctl stop chronyd
systemctl restart chronyd
systemctl status chronyd
systemctl enable chronyd
systemctl disable chronyd
chronyd -f /etc/chrony.conf -d
chronyd -Q -t 5 'server time.aliyun.com iburst'
journalctl -u chronyd -f
chronyc
chronyc tracking
chronyc sources -v
chronyc sourcestats -v
chronyc activity
chronyc ntpdata
chronyc clients
chronyc serverstats
chronyc waitsync 30 0.001
chronyc makestep
chronyc -a makestep
chronyc delete 192.168.1.10
chronyc add server 10.0.0.1 iburst
chronyc accheck
chronyc tracking -p
chronyc -h ntp01.internal
网络与端口
ss -ulnp | grep 123
netstat -ulnp | grep 123
nc -uv time.aliyun.com 123
nmap -sU -p 123 time.aliyun.com
tcpdump -i eth0 -n udp port 123 -c 20
tcpdump -i eth0 -n udp port 123 -w /tmp/ntp.pcap
调试
strace -f -e trace=clock_settime,settimeofday,adjtimex -p $(pidof chronyd)
gdb -p $(pidof chronyd) --batch -ex 'thread apply all bt' -ex detach
journalctl -u chronyd -p debug
NTP 客户端工具
# ntpdate 已被 chrony 替代,但很多老脚本还在用
ntpdate -q ntp.aliyun.com
sntp -S ntp.aliyun.com
# busybox 内置
busybox ntpd -q -p ntp.aliyun.com
文件路径
/etc/chrony.conf
/etc/chrony/chrony.conf
/etc/chrony.d/*.conf
/etc/chrony.keys
/etc/chrony/ntp.keys
/var/log/chrony/
/var/lib/chrony/
/usr/bin/chronyc
/usr/sbin/chronyd
/usr/share/zoneinfo/
/etc/localtime
/etc/timezone
/etc/adjtime
配置示例汇总
内网 NTP Server(stratum-2 / GPS 接入)
# /etc/chrony.conf
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
# 从上游同步
server ntp-master01.internal iburst prefer
server ntp-master02.internal iburst
# 自定义 NTP Server 监听端口
bindaddress 192.168.100.10
allow 192.168.0.0/16
allow 10.0.0.0/8
allow 172.16.0.0/12
deny 0.0.0.0/0
deny ::/0
# 上游不可用时作为 fallback
local stratum 10
# 限制 monlist 行为,防反射
noclientlog
ratelimit interval 3 burst 8
# 启用 NTS(如果上游支持)
ntsserverkey /etc/chrony/ntpserver.key
ntstrustedcerts /etc/chrony/cacert.pem
# 日志
log tracking measurements statistics
logdir /var/log/chrony
内网 NTP Client(应用服务器)
# /etc/chrony.conf
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
server ntp01.internal iburst prefer
server ntp02.internal iburst
server ntp03.internal iburst
# 不对外提供服务
deny all
# 监控
log measurements statistics
logdir /var/log/chrony
K8s node 客户端
# /etc/chrony.conf
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
server ntp01.internal iburst prefer
server ntp02.internal iburst
server ntp.aliyun.com iburst
# 不对外服务
deny all
# 日志
log measurements statistics
logdir /var/log/chrony
边缘 / 4G 网关
# /etc/chrony.conf
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
# 间歇性网络,用 pool 自动挑
pool pool.ntp.org iburst maxsources 4
server time1.aliyun.com iburst
# 容忍更慢收敛
maxpoll 12
minpoll 6
# 边端不开 server
deny all
物理机自建 stratum-1(GPS + PPS)
# /etc/chrony.conf
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
# GPS + PPS
refclock PPS /dev/pps0 lock GPS prefer
refclock SHM 0 offset 0.5 delay 0.2 refid GPS noselect
refclock SOCK /var/run/chrony.gpsd.sock refid GPS noselect
# 对外服务
bindaddress 192.168.100.10
allow 192.168.0.0/16
allow 10.0.0.0/8
deny 0.0.0.0/0
deny ::/0
# 上游断网兜底
local stratum 1
# 防止反射
noclientlog
ratelimit interval 3 burst 8
# NTS
ntsserverkey /etc/chrony/ntpserver.key
log tracking measurements statistics
logdir /var/log/chrony
NTS 加密模式
# /etc/chrony.conf
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
server time.cloudflare.com iburst nts
server ntp.nts.sjtu.edu.cn iburst nts prefer
server ntp1.nts.lu iburst nts
deny all
log measurements statistics
logdir /var/log/chrony
排查思路
排查表
| 现象 | 检查点 | 命令 | 关键指标 | 结论 |
| --- | --- | --- | --- | --- |
| offset 很大 | 防火墙 | nc -uv time.aliyun.com 123 | 通/不通 | 防火墙挡了 |
| offset 很大 | 上游源 | chronyc sources -v | Reach | 源不可达 |
| offset 跳变 | CPU 抢占 | top, mpstat | %idle | CPU 满 |
| offset 跳变 | hypervisor 干扰 | chronyc sourcestats | jitter | 虚拟化漂移 |
| chronyc 异常 | 日志 | journalctl -u chronyd | error | 配置错误 |
| 容器时间漂移 | 权限 | docker inspect | CapEff | 缺少 SYS_TIME |
| 节点 NotReady | 时间差 | date -u vs kube-apiserver | 证书过期 | 证书时间错位 |
| 日志顺序乱 | NTP 同步状态 | chronyc tracking | System time | 主机时间不统一 |
排查流程
- 看现象:
date不对?hwclock不对?业务报错? - 看服务:
systemctl status chronyd、journalctl -u chronyd。 - 看状态:
chronyc tracking、chronyc sources -v。 - 看网络:
ss -ulnp | grep 123、nc -uv、tcpdump。 - 看 CPU/IO:
top、iostat、vmstat。 - 看时区:
timedatectl、cat /etc/timezone。 - 看 RTC:
hwclock --show --utc。 - 看容器:宿主时间、容器时间对比。
- 定位根因:根据上面信息判断是网络、CPU、配置、硬件、内核哪种。
- 修复:按根因修复。
- 验证:
chronyc waitsync 60 0.001、跨主机date +%s%N。 - 复盘:写事故复盘文档,更新监控。
风险提醒汇总
- 强制
chronyc makestep会让 system time 跳变,可能影响数据库、分布式系统、证书校验、定时任务。 - 改
/etc/chrony.conf之后必须systemctl restart chronyd,否则不生效。 allow 0.0.0.0/0是 NTP 反射攻击温床,必须加restrict或deny 0.0.0.0/0。- 自建 NTP Server 必须有冗余,单点故障会导致整集群时间错乱。
- RTC 模式改成
local会让跨时区机器时间错乱,建议保持 UTC。 pool.ntp.org节点是志愿者维护,质量参差,生产建议用云厂商或自建。- ntpd 历史漏洞(mode 7 monlist、NTP 反射攻击)很多,新系统建议直接 chrony。
- K8s 节点时间漂移会引发
NotReady、x509错误、cert-manager 续签失败等多种问题。 - 应用层应使用 monotonic clock,不要把 CLOCK_REALTIME 当成”时间戳”用。
- 数据库主从复制延迟如果和 offset 跳变同时出现,要先确认时间同步是否正常。
验证方式
同步验证
# 1. 实时 offset
chronyc tracking
# System time 接近 0
# 2. 等待收敛
chronyc waitsync 60 0.001
# 返回 0
# 3. 源健康
chronyc sources -v
# ^* 状态,Reach 377
# 4. 长期稳定
chronyc sourcestats -v
# offset 趋势平,jitter < 1ms
# 5. RTC 同步
hwclock --show --utc
# 接近 system time
跨主机对比
# 在 5 台机器上同时跑
for h in web01 web02 db01 db02 cache01; do
ssh $h "date '+%s.%N'"
done
5 台机器的时间差应该 < 10 ms(内网)/ < 100 ms(公网)。
断网测试
sudo iptables -A OUTPUT -p udp --dport 123 -j DROP
sleep 3600
date
# 1 小时后看漂移
sudo iptables -D OUTPUT -p udp --dport 123 -j DROP
漂移 < 5 秒说明硬件时钟健康。
压力测试
# 跑 stress-ng
stress-ng --cpu 4 --vm 2 --vm-bytes 1G --timeout 600
# 同时看 chronyc
watch -n 1 'chronyc tracking'
应该看到 offset 略有波动但很快收敛。
业务验证
- 数据库主从延迟:
SHOW SLAVE STATUS(MySQL 5.7)/SHOW REPLICA STATUS(MySQL 8.0)里Seconds_Behind_Master接近 0。 - K8s 节点:
kubectl get nodes全是Ready。 - 证书:
openssl x509 -in cert.pem -noout -dates输出与date一致。 - 日志:相邻机器同一时刻的日志时间戳差 < 1 秒。
- 分布式系统心跳:服务间 RPC 心跳正常。
回滚方案
改了 /etc/chrony.conf 出问题
# 1. 备份当前配置
sudo cp /etc/chrony.conf /etc/chrony.conf.broken.$(date +%Y%m%d)
# 2. 恢复备份
sudo cp /etc/chrony.conf.bak.$(date +%Y%m%d) /etc/chrony.conf
# 3. 重启
sudo systemctl restart chronyd
# 4. 验证
chronyc tracking
整台机器时间错乱要回滚
# 1. 停 chrony
sudo systemctl stop chronyd
# 2. 手动设时间(用可信源)
sudo ntpdate ntp.aliyun.com
# 或者
sudo sntp -S time.aliyun.com
# 3. 同步到 RTC
sudo hwclock --systohc --utc
# 4. 启动 chrony
sudo systemctl start chronyd
# 5. 验证
chronyc tracking
date
hwclock
K8s 节点时间错乱
# 1. cordon 节点
kubectl cordon node-01
# 2. 排空
kubectl drain node-01 --ignore-daemonsets
# 3. SSH 登录节点,强制同步
sudo systemctl stop chronyd
sudo ntpdate ntp01.internal
sudo systemctl start chronyd
chronyc tracking
# 4. uncordon
kubectl uncordon node-01
整集群时间错乱
极少见,通常是上游 NTP Server 时间错乱或恶意攻击。
# 1. 切到备用上游
# 修改 /etc/chrony.conf 的 server 指令
sudo sed -i 's/^server .*/server ntp-master01.internal iburst prefer/' /etc/chrony.conf
sudo systemctl restart chronyd
# 2. 强制 step
chronyc makestep
# 3. 监控
chronyc tracking
总结
时间同步看似基础,但实际是 Linux 运维最容易被低估的一块。chrony 是当前最主流的 NTP 客户端/服务器实现,能覆盖从云服务器、容器、K8s 节点到自建 stratum-1 的所有场景。
核心要点:
- 明确时区、UTC、硬件时钟的关系,统一集群时区。
- 选可信上游:内网 + 云厂商 + 公网 pool 三层兜底。
- 用
makestep 1.0 3限制大步 step,其余靠 slewing。 - 启用 NTS 防止 NTP 流量被篡改。
- 至少 2 个独立上游源,监控 reach、offset、stratum。
- 把时间指标接入 Prometheus + Grafana + Alertmanager。
- K8s 节点、自建 NTP server、容器宿主分别给模板。
- 等保 / 行业合规做自动化检查脚本。
- 应用层使用 monotonic clock 而不是 wall clock。
进阶方向:
- NTS 加密、PTP 高精度。
- 自建 stratum-1 + GPS / 北斗。
- chrony_exporter + Prometheus 完整监控。
- 与 CIS Benchmark、SLSA、零信任架构集成。
附录
关键路径
- 配置:
/etc/chrony.conf(RHEL / openEuler / AlmaLinux)、/etc/chrony/chrony.conf(Debian / Ubuntu)。 - 漂移文件:
/var/lib/chrony/drift。 - 日志目录:
/var/log/chrony/。 - 控制 socket:
/var/run/chrony/chronyd.sock。 - 工具:
/usr/bin/chronyc、/usr/sbin/chronyd。 - 时区数据:
/usr/share/zoneinfo/。 - 本地时区:
/etc/localtime。 - 时区名:
/etc/timezone。
关键环境变量
TZ:POSIX 系统设置时区。chronyc_TZ:影响chronyc输出的时区。
关键端口
- UDP 123:NTP。
- TCP 4460:NTS(KE 阶段)。
- TCP 3731:chrony
cmdmonitor(可选,远程 chronyc 接入)。
关键文件
/etc/chrony.keys:对称密钥(NTP authentication)。/etc/adjtime:hwclock 状态。/etc/ntp.conf:ntpd 配置(如果并存)。/etc/systemd/timesyncd.conf:systemd-timesyncd 配置。
关键链接
- chrony 官方:http://chrony.tuxfamily.org/
- chrony GitHub:https://github.com/keplerproject/chrony
- NTP Pool:https://www.pool.ntp.org/
- Cloudflare NTS:https://blog.cloudflare.com/secure-time/
- IETF NTS:https://datatracker.ietf.org/doc/rfc8915/
- IETF NTP:https://datatracker.ietf.org/doc/rfc5905/
版本兼容
- chrony 1.x:老版本,没有 NTS、没有 tsdb。
- chrony 2.x:成熟稳定,CentOS 7 默认。
- chrony 3.x:加入更多 refclock 支持。
- chrony 4.x:NTS、PTP、PHC、Canned config、async transfer。
- 4.2+:NTS KE / NTS EF 完整支持。
具体指令以实际版本为准。
常见错误码
503 No suitable source:所有源都不可达。500 Too many sources:源超过 maxsources。504 Source not found:要删除的源不存在。522 Reachability not yet achieved:reach 还没达到 1。
具体错误以 chronyc 输出为准。
写给初中级读者的最后建议
- 时间同步是基础设施,先把
/etc/chrony.conf写好,再考虑监控。 - 不要照搬网上搜到的 chrony.conf,看清楚每个指令含义再上生产。
- 改配置前先备份,先在测试集群跑一遍。
chronyc tracking是日常排查第一命令,先看这个。- 监控和告警先做,事后复盘才有数据。
- K8s 节点、自建 NTP Server、数据库主库这三种角色优先级最高。
- 出问题不要怕回滚,备份和回滚流程是日常必备。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:马哥Linux运维 点击关注 👉 点击关注 👉《Linux 服务器时间同步(NTP/chrony)最佳实践》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论