Linux服务器时间同步最佳实践

描述

问题背景

时间同步是 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、数据库主库这三种角色优先级最高。

出问题不要怕回滚,备份和回滚流程是日常必备。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分