问题背景
时间同步是 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 0000 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 多了 2360 这一秒。
Linux 处理闰秒的方式:
内核标记:内核打上 leap flag,应用读取时间后会看到 2360。
步进(step):chronyc makestep 或 ntp 某些版本会直接让时间跳 1 秒。
涂抹(smear):Google、Meta(Facebook)、Cloudflare、AWS 都用"闰秒涂抹",把 1 秒均匀分摊到 24 小时内,绕开 2360 的问题。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 myadmin@example.com 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
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_TIME capability。
用 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 1000 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、数据库主库这三种角色优先级最高。
出问题不要怕回滚,备份和回滚流程是日常必备。
全部0条评论
快来发表一下你的评论吧 !