时间同步是 Linux 运维里最容易被忽视、但一翻车就坑死一票业务的基础设施。生产里这些抱怨几乎每周都能听到:
kube-apiserver
x509: certificate has expired or is not yet valid
Seconds_Behind_Master
date
hwclock
clock_gettime(CLOCK_MONOTONIC)
这些故障的根因几乎都指向一件事:服务器时间不可信。Linux 服务器的时间其实是一个由"硬件时钟(RTC)+ 内核维护的 system time + NTP 守护进程 + 时区配置 + 闰秒/跳秒策略"共同协作的小系统。任何一个环节没配好,都会出现上述现象。
这篇文章面向初中级运维 / 系统管理员 / DevOps 工程师,从原理到实战,把 chrony 这条主线讲透,覆盖单机、云服务器、容器、K8s 节点、自建 NTP 服务器、内网隔离等场景。看完之后能独立完成时间同步选型、配置、排查和合规落地。
由 Linux 内核维护的墙上时钟(wall clock),单位是自 1970-01-01 00:00:00 UTC 起的秒数 + 纳秒部分。所有 date、gettimeofday、time()、clock_gettime(CLOCK_REALTIME) 都读这个值。
gettimeofday
time()
clock_gettime(CLOCK_REALTIME)
系统时间由内核 tick 或 tickless 模式维护,本身没有"绝对意义",完全靠 NTP/chrony 这种用户态守护进程不断校准。系统时间可以"跳变"(slewing 太慢时直接 settimeofday 改掉),但单调时钟不能跳变。
主板上由电池供电的小芯片保存的时间,机器断电后依然走时。Linux 里通过 /dev/rtc0 访问,可以用 hwclock 命令读写。
/dev/rtc0
可以用 timedatectl 查看 RTC in local TZ: no 确认。
timedatectl
RTC in local TZ: no
Linux 内核另一个时钟源,从某个未指定的起点开始单调递增,NTP 不会调整它。应用如果做超时、心跳、限流,应该用 monotonic clock,否则系统时间跳变(NTP 第一次同步时强制 step)会导致逻辑全乱。
clock_gettime(CLOCK_MONOTONIC, &ts) 是关键 API。K8s、etcd、RocksDB、LevelDB、Tokio 运行时、Rust 标准库等都依赖 monotonic clock。
clock_gettime(CLOCK_MONOTONIC, &ts)
/etc/localtime
/usr/share/zoneinfo/<区域>/<城市>
timedatectl set-timezone Asia/Shanghai
容器内 /etc/localtime 默认继承宿主,但 Pod spec 可以通过 volumeMounts 单独挂载。
volumeMounts
NTP(Network Time Protocol,RFC 5905)是 Linux 时间同步的事实标准协议,使用 UDP 123 端口。chrony 和 ntpd 都遵循这个协议,但实现上有差异。
chronyc tracking
System time
Root delay
RMS offset
chronyc sources
chronyc sources -v
2^n
简化流程:
(T2 - T1) + (T4 - T3)
((T2 - T1) + (T3 - T4)) / 2
这个简化模型假设网络对称,实际 chrony 会用更复杂的卡尔曼滤波估算 offset 和 jitter。
pool.ntp.org
chrony 都支持。
chrony 相对 ntpd 的优势:
chronyc
ntpq
ntpd 相对 chrony 的优势:
不同云厂商通常提供内网 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
169.254.169.254
time.windows.com
time.nist.gov
metadata.google.internal
云上实例的 chrony 配置里把这些地址放前面,本地时钟源延迟通常 < 5 ms。
0.cn.pool.ntp.org
1.asia.pool.ntp.org
time.cloudflare.com
time.google.com
time.apple.com
公网源的延迟通常 5-50 ms,受国际出口影响大。金融、政企、涉密网络不建议直接用公网源。
推荐分层架构:
GPS / 北斗 / 原子钟(stratum-0 设备) ↓Stratum-1 服务器(内网核心机房,1-2 台做 HA) ↓Stratum-2 服务器(每个区域机房,2-4 台做 HA) ↓业务服务器 / 容器节点 / 数据库 / 存储
stratum-1 服务器可以用:
UTC 和 UT1(基于地球自转的时间)有累积差异,IERS 会不定期宣布在 6 月 30 日或 12 月 31 日最后一秒插入或删除 1 秒。最近一次是 2016-12-31,2017-01-01 多了 23:59:60 这一秒。
Linux 处理闰秒的方式:
chronyc makestep
leapsecmode slew
slew
step
ignore
smeartime
adjtimex
settimeofday
makestep
chrony 推荐配置:makestep 1.0 3(offset > 1 秒且前 3 次更新才 step),之后再 slewing。生产里可以根据情况改阈值。
makestep 1.0 3
chronyd 是守护进程,负责同步、维护本地时间、调整 RTC。chronyc 是用户态控制工具。
chronyd 启动流程:
/etc/chrony.conf
/etc/chrony/chrony.conf
chronyd 还会:
rtcsync
allow
local
chrony.measure
tracking
sources
sourcestats
按功能分组介绍。
pool pool.ntp.org iburst maxsources 4server time1.aliyun.com iburstpeer ntp01.internal iburstrefclock SHM 0 offset 0.5 delay 0.2
pool
server
peer
refclock
iburst
minpoll
maxpoll
minpoll 4 maxpoll 10
prefer
trust
xleave
nts
allow 192.168.0.0/16allow 10.0.0.0/8deny 0.0.0.0/0
makestep 1.0 3rtcsyncleapsecmode slewsmeartime 86400
local stratum 10manual
local 表示本机即使没连到上游,也对外宣告自己是 stratum-10,集群内统一时间。manual 配合 chronyc settime 手动校准,但生产里慎用。
manual
chronyc settime
log tracking measurements statisticslogdir /var/log/chronymailonchange myadmin@example.com 0.5
常用子命令:
chronyc sourcestats -v
chronyc activity
chronyc ntpdata
chronyc waitsync 30 0.01
chronyc tracking -p
chronyc clients
chronyc serverstats
chronyc delete
chronyc add server
<addr>
chronyc accheck
chronyc certif / cacert
chronyc -a makestep
chronyc 还有交互模式,输入 chronyc 回车进 prompt,help 列出所有子命令。
help
monlist
restrict
内核要求:Linux 3.10+ 都没问题,2.6.32 老内核也支持 chrony 3.x / 4.x。
可以用 chronyd -v 或 chronyc --version 查看。
chronyd -v
chronyc --version
在动手改任何配置之前,先摸清楚当前状态,避免改了反而把生产搞乱。
datedate -utimedatectlhwclockhwclock --utchwclock --localtime
timedatectl 输出关键字段:
Local time
Universal time
RTC time
Time zone
System clock synchronized
NTP service
RTC in local TZ
systemctl status chronydsystemctl status ntpdsystemctl status systemd-timesyncdchronyc trackingchronyc sources -vchronyc sourcestats -vchronyc activity
chronyc tracking 输出关键字段解读:
Reference ID
Stratum
Last offset
Frequency
Residual freq
Skew
Root dispersion
Update interval
Leap status
健康标准:
Normal
chronyc sources -v 输出关键列:
^*
^+
^-
=?
~
M
x
*
MS
Reach
健康源:^* 或 ^+,Reach = 377,Last rx 距现在 < 2 个 poll 间隔。
chronyc sourcestats 输出当前 offset、jitter、reach、stability 等长期统计。
chronyc sourcestats
ss -ulnp | grep 123netstat -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 | 不可达 |
这一步是后面排查和验收的依据,不要省略。
timedatectlls -l /etc/localtimecat /etc/timezone
sudo timedatectl set-timezone Asia/Shanghaisudo timedatectl set-timezone UTCsudo timedatectl set-timezone Europe/Berlin
Asia/Shanghai、UTC、Europe/Berlin 等是 IANA 时区数据库标准名,存在 /usr/share/zoneinfo/ 目录里。
Asia/Shanghai
UTC
Europe/Berlin
/usr/share/zoneinfo/
sudo timedatectl set-local-rtc 0
set-local-rtc 0 表示硬件时钟存 UTC;1 表示存 local time。生产环境强烈建议 0。
set-local-rtc 0
1
timedatectldatedate -uhwclock --show --utc
容器 /etc/localtime 默认继承宿主机。如果要让容器用别的时区:
apiVersion:v1kind:Podspec:containers:-name:appimage:my-app:1.0volumeMounts:-name:tz-configmountPath:/etc/localtimevolumes:-name:tz-confighostPath:path:/usr/share/zoneinfo/Asia/Shanghaitype:File
或者在 Dockerfile 里 ENV TZ=Asia/Shanghai + RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone。但容器镜像里塞时区文件不如直接挂宿主。
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。
-Duser.timezone=Asia/Shanghai
TZ
os.environ['TZ']
time.tzset()
time_zone
CONVERT_TZ
容器内推荐把所有应用统一到 UTC,业务层按需转换。这样跨地域、跨集群、跨云排查日志时不会因为时区搞错。
sudo dnf install -y chronysudo systemctl enable --now chronydchronyc tracking
sudo yum install -y chronysudo systemctl enable --now chronydchronyc tracking
CentOS 7 上默认 chrony 3.4,能用但没 NTS。如需 NTS,需要 chrony 4.0+。
sudo apt updatesudo apt install -y chronysudo systemctl enable --now chronydchronyc tracking
Ubuntu 22.04 默认 chrony 4.2+,自带 NTS。
chronyd -vchronyc --versionrpm -q chronydpkg -l | grep chrony
按场景给几套配置模板。
# /etc/chrony.conf# 优先用内网自建 NTP serverserver ntp01.internal iburst preferserver ntp02.internal iburst# 公有云厂商作为兜底server ntp.aliyun.com iburstserver time1.cloud.tencent.com iburst# poolpool pool.ntp.org iburst maxsources 4# 启动时如果 offset > 1 秒,连续 3 次更新内允许 stepmakestep 1.0 3# 把系统时间同步到硬件时钟rtcsync# 硬件时钟调整间隔rtcautotrim 30# 同步到 RTC 的时间hwclockfile /etc/adjtime# 允许的客户端网段allow 192.168.0.0/16allow 10.0.0.0/8# 默认拒绝其他来源deny 0.0.0.0/0# 拒绝所有 IPv6 来源deny ::/0# 日志log tracking measurements statisticslogdir /var/log/chrony
# /etc/chrony.conf# 只用内网 NTP serverserver ntp01.internal iburst preferserver ntp02.internal iburstserver ntp03.internal iburst# 上游不通时,本机仍然能对外提供服务local stratum 10makestep 1.0 3rtcsyncallow 10.0.0.0/8deny 0.0.0.0/0deny ::/0log tracking measurements statisticslogdir /var/log/chrony
# /etc/chrony.conf# 这一台是 server 模式,对客户端提供服务# 自身从上游同步(GPS、北斗、原子钟、或者内网根 server)server ntp-master01.internal iburst preferserver ntp-master02.internal iburst# 允许客户端网段allow 192.168.0.0/16allow 10.0.0.0/8allow 172.16.0.0/12deny 0.0.0.0/0deny ::/0# 自身不睡醒调整 RTC,由其他机器负责rtcsync# 上游不可用时,自己作为 fallbacklocal stratum 10log tracking measurements statisticslogdir /var/log/chrony
# /etc/chrony.conf# 需要 chrony 4.2+server time.cloudflare.com iburst ntsserver ntp.nts.sjtu.edu.cn iburst nts preferserver ntp1.nts.lu iburst ntsmakestep 1.0 3rtcsync# 限制外网访问,只允许自己出站deny all
NTS 需要服务端支持,目前 Cloudflare、NIST、Some university 公开 NTP/NTS 节点。生产里更常见的做法是自建 NTS server:
# /etc/chrony.confntsserverkey /etc/chrony/keys/ntp-server.keyntstrustedcerts /etc/chrony/certs
# /etc/chrony.conf# K8s 节点时间精度要求高(证书、metrics-server、kube-apiserver)server ntp01.internal iburst preferserver ntp02.internal iburstserver ntp.aliyun.com iburstmakestep 1.0 3rtcsync# 允许 Pod 共享 /dev/ptp 之类的设备# 不需要 allow,因为 K8s 节点自身就是 clientdeny all# 关闭查询日志log measurements statisticslogdir /var/log/chrony
# /etc/chrony.conf# 适合间歇性网络、Wi-Fi 切换、4G 边缘盒子pool pool.ntp.org iburst maxsources 4server time1.aliyun.com iburstmakestep 1 1rtcsync# 边缘设备通常没有 RTC 持久化# 需要时开启 fakehwclock
# /etc/chrony.conf# 限制哪些客户端能查询本机allow 10.0.0.0/8deny 0.0.0.0/0# 不响应 monlistnoclientlog# 限制每个客户端的查询频率ratelimit interval 3 burst 8
chronyc clients 可以看当前连到本机的客户端。
修改完 /etc/chrony.conf 之后:
sudo systemctl restart chronydsudo systemctl status chronydchronyc trackingchronyc sources -vchronyc sourcestats -vchronyc 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 表示超时或异常。
chrony 默认日志比较安静。要看更多细节:
# /etc/chrony.conflog tracking measurements statisticslogdir /var/log/chrony
常用日志文件:
tracking.log
measurements.log
statistics.log
temp.log
日志可以接入 rsyslog、ELK、Loki 等。
chrony 自身没有内置 Prometheus exporter,但可以用以下几种方式接入:
chrony_exporter
chrony_offset_seconds
chrony_frequency_ppm
node_exporter
node_timex_*
示例 exporter 指标:
chrony_offset_secondschrony_frequency_ppmchrony_skew_ppmchrony_root_delay_secondschrony_root_dispersion_secondschrony_leap_status
chrony_leap_status 0 = Normal、1 = Insert second、2 = Delete second、3 = Not synchronized。
chrony_leap_status
Prometheus 告警规则示例:
groups:-name:chronyrules:-alert:ChronyOffsetTooLargeexpr:abs(chrony_offset_seconds)>0.1for:5mlabels:severity:warningannotations:summary:"主机 {{ $labels.instance }} 时间偏移过大"description:"offset = {{ $value }} s"-alert:ChronyNotSyncedexpr:chrony_leap_status==3for:1mlabels:severity:criticalannotations:summary:"主机 {{ $labels.instance }} NTP 未同步"
阈值的具体数值需要结合业务基线,不能照搬。
K8s 集群对时间同步要求很高:
metrics-server
etcd
kube-scheduler
# /etc/chrony.confserver ntp01.internal iburst preferserver ntp02.internal iburstserver ntp03.internal iburstmakestep 1.0 3rtcsync# 不要 allow,节点自身不向外提供 NTPdeny all# 日志log measurements statisticslogdir /var/log/chrony
for n in $(kubectl get nodes -o name | cut -d/ -f2); doecho"== $n ==" kubectl debug node/$n -it --image=busybox -- \ date -udone
或用 Node Problem Detector(NPD)的时间漂移检测插件。
容器默认共享宿主 system time,不需要额外配置。但有些场景需要单独校准:
容器 time namespace 是 K8s 1.27+ 的 alpha 特性,可以让 Pod 有独立的时间视图。生产慎用。
云厂商的 K8s(ACK、TKE、EKS、GKE)会自动用云厂商的 NTP 服务,节点时间通常很准。但建议仍然配内网 NTP server 作为冗余。
故障 1:chronyc sources 显示所有源都是 ^? 或 ^x
^?
^x
可能原因:
排查步骤:
# 1. 测网络ping ntp.aliyun.comnc -uv ntp.aliyun.com 123# 2. 测端口nmap -sU -p 123 ntp.aliyun.com# 3. 抓包tcpdump -i eth0 -n udp port 123 -c 20# 4. 看 chronycchronyc activitychronyc ntpdata
修复:
故障 2:offset 一直跳变(±几秒)
排查:
# 1. 看 CPUtopvmstat 1 5# 2. 看 jitterchronyc sourcestats -v# 3. 看 reachchronyc sources -v# 4. 切到不同源chronyc delete ntp.aliyun.comchronyc add server time.google.com iburst
故障 3:chronyc tracking 显示 System time 永远 ~0,但 date 偏差大
strace -f -e trace=clock_settime,settimeofday,adjtimex -p $(pidof chronyd)
故障 4:机器重启后时间错乱
# 同步 system time 到 RTCsudo hwclock --systohc --utc# 检查 adjtime 文件cat /etc/adjtime# 0.000000 1700000000 0.000000# 1700000000 UTC# /etc/chrony.conf 里加rtcsync
故障 5:容器内时间漂移
CAP_SYS_TIME
bind mount
securityContext.capabilities.add: ["SYS_TIME"]
故障 6:双 NIC 多 IP 节点时间不同步
# /etc/chrony.confbindaddress 192.168.1.10
把 chrony 绑到特定 IP。
故障 7:chronyd 启动失败
sudo journalctl -u chronyd -n 50sudo chronyd -f /etc/chrony.conf -d
-d 调试模式打印所有内部状态。
-d
故障 8:reach 一直是 0
# 手动测sudo ntpdate -q ntp.aliyun.com
注:ntpdate 在新系统已经被 chrony / ntpsec 替代,CentOS 7 后基本没有。
ntpdate
回滚:
# 备份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
现象:所有节点都"看起来同步了",但都偏 10 秒。
chronyc tracking# Reference ID 不是你预期的源
风险高的场景:
应对:
# 看漂移sudo systemctl stop chronydsleep 60datedate# 差几秒就说明硬件时钟漂移
现象:证书过期、cert-manager Job 报错。
# 临时强制同步sudo chronyc makestepsudo systemctl restart chronyd
长期:
有些运维习惯看 date 不带 -u,看到北京时间。容器 / 服务器混部时容易混。
-u
建议:
等保 2.0 中关于时间同步的条款:
实操建议:
# /etc/ansible/playbooks/chrony-check.yml-name:检查NTP配置hosts:allgather_facts:yestasks:-name:确认chronyd在运行systemd:name:chronydstate:startedenabled:yesregister:chrony_status-name:收集chronytrackingcommand:chronyctrackingregister:trackingchanged_when:false-name:收集chronysourcescommand:chronycsources-vregister:sourceschanged_when:false-name:输出报告debug:msg:| 主机: {{ inventory_hostname }} 跟踪: {{ tracking.stdout }} 源: {{ sources.stdout }}
#!/usr/bin/env bash# /usr/local/bin/chrony-audit.sh# 检查所有受控主机的 NTP 状态LOG_DIR=/var/log/chrony-auditmkdir -p "$LOG_DIR"REPORT="$LOG_DIR/audit-$(date +%Y%m%d).log"for host in $(cat /etc/hosts.list); doecho"=== $host ===" >> "$REPORT" ssh -o StrictHostKeyChecking=accept-new "$host" \'chronyc tracking; echo "---"; chronyc sources -v' \ >> "$REPORT" 2>&1done# 找 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:安装chronypackage:name:chronystate:present-name:分发配置文件template:src:chrony.conf.j2dest:/etc/chrony.confowner:rootgroup:rootmode:'0644'notify:restartchronyd-name:启动并开机自启service:name:chronydstate:startedenabled:yes
Jinja2 模板按环境区分:
# ansible: roles/chrony/templates/chrony.conf.j2{% if env == 'prod' %}server ntp01.prod.internal iburst preferserver ntp02.prod.internal iburst{% elif env == 'dev' %}server ntp01.dev.internal iburstserver ntp.aliyun.com iburst{% endif %}makestep 1.0 3rtcsyncallow {{ ntp_allow_net }}deny 0.0.0.0/0deny ::/0log tracking measurements statisticslogdir /var/log/chrony
NTS 是 IETF RFC 8915 定义的 NTP 加密扩展,目标是解决 NTP 流量被篡改、伪造的问题。
chrony 4.2+ 原生支持。配置:
server time.cloudflare.com iburst ntsserver ntp.nts.sjtu.edu.cn iburst nts
可以用 chronyc accheck 查看认证状态。
金融交易、5G、工业控制场景需要微秒甚至纳秒级时间同步。PTP 适合这些场景。
chrony 4.x 增加了 PTP 支持(refclock PHC),可以把 PTP 主时钟时间同步到系统时间。
refclock PHC
自建 stratum-1 经典方案:
refclock PPS /dev/pps0
refclock SHM 0
# /etc/chrony.confrefclock PPS /dev/pps0 lock GPSrefclock SHM 0 offset 0.5 delay 0.2 refid GPS
chrony_stratum
datedate -udate '+%Y-%m-%d %H:%M:%S.%N'date -d @1700000000date -d '2026-06-05 10:00:00 UTC' +%shwclockhwclock --show --utchwclock --show --localtimehwclock --systohc --utchwclock --hctosys --utctimedatectltimedatectl statuscat /etc/timezonels -l /etc/localtimezdump -v /usr/share/zoneinfo/Asia/Shanghai
systemctl start chronydsystemctl stop chronydsystemctl restart chronydsystemctl status chronydsystemctl enable chronydsystemctl disable chronydchronyd -f /etc/chrony.conf -dchronyd -Q -t 5 'server time.aliyun.com iburst'journalctl -u chronyd -f
chronyc trackingchronyc sources -vchronyc sourcestats -vchronyc activitychronyc ntpdatachronyc clientschronyc serverstatschronyc waitsync 30 0.001chronyc makestepchronyc -a makestepchronyc delete 192.168.1.10chronyc add server 10.0.0.1 iburstchronyc accheckchronyc tracking -pchronyc -h ntp01.internal
ss -ulnp | grep 123netstat -ulnp | grep 123nc -uv time.aliyun.com 123nmap -sU -p 123 time.aliyun.comtcpdump -i eth0 -n udp port 123 -c 20tcpdump -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 detachjournalctl -u chronyd -p debug
# ntpdate 已被 chrony 替代,但很多老脚本还在用ntpdate -q ntp.aliyun.comsntp -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
# /etc/chrony.confdriftfile /var/lib/chrony/driftmakestep 1.0 3rtcsync# 从上游同步server ntp-master01.internal iburst preferserver ntp-master02.internal iburst# 自定义 NTP Server 监听端口bindaddress 192.168.100.10allow 192.168.0.0/16allow 10.0.0.0/8allow 172.16.0.0/12deny 0.0.0.0/0deny ::/0# 上游不可用时作为 fallbacklocal stratum 10# 限制 monlist 行为,防反射noclientlogratelimit interval 3 burst 8# 启用 NTS(如果上游支持)ntsserverkey /etc/chrony/ntpserver.keyntstrustedcerts /etc/chrony/cacert.pem# 日志log tracking measurements statisticslogdir /var/log/chrony
# /etc/chrony.confdriftfile /var/lib/chrony/driftmakestep 1.0 3rtcsyncserver ntp01.internal iburst preferserver ntp02.internal iburstserver ntp03.internal iburst# 不对外提供服务deny all# 监控log measurements statisticslogdir /var/log/chrony
# /etc/chrony.confdriftfile /var/lib/chrony/driftmakestep 1.0 3rtcsyncserver ntp01.internal iburst preferserver ntp02.internal iburstserver ntp.aliyun.com iburst# 不对外服务deny all# 日志log measurements statisticslogdir /var/log/chrony
# /etc/chrony.confdriftfile /var/lib/chrony/driftmakestep 1.0 3rtcsync# 间歇性网络,用 pool 自动挑pool pool.ntp.org iburst maxsources 4server time1.aliyun.com iburst# 容忍更慢收敛maxpoll 12minpoll 6# 边端不开 serverdeny all
# /etc/chrony.confdriftfile /var/lib/chrony/driftmakestep 1.0 3rtcsync# GPS + PPSrefclock PPS /dev/pps0 lock GPS preferrefclock SHM 0 offset 0.5 delay 0.2 refid GPS noselectrefclock SOCK /var/run/chrony.gpsd.sock refid GPS noselect# 对外服务bindaddress 192.168.100.10allow 192.168.0.0/16allow 10.0.0.0/8deny 0.0.0.0/0deny ::/0# 上游断网兜底local stratum 1# 防止反射noclientlogratelimit interval 3 burst 8# NTSntsserverkey /etc/chrony/ntpserver.keylog tracking measurements statisticslogdir /var/log/chrony
# /etc/chrony.confdriftfile /var/lib/chrony/driftmakestep 1.0 3rtcsyncserver time.cloudflare.com iburst ntsserver ntp.nts.sjtu.edu.cn iburst nts preferserver ntp1.nts.lu iburst ntsdeny alllog measurements statisticslogdir /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 | 主机时间不统一 |
systemctl status chronyd
journalctl -u chronyd
ss -ulnp | grep 123
nc -uv
tcpdump
top
iostat
vmstat
cat /etc/timezone
hwclock --show --utc
date +%s%N
systemctl restart chronyd
allow 0.0.0.0/0
deny 0.0.0.0/0
NotReady
x509
# 1. 实时 offsetchronyc 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 DROPsleep 3600date# 1 小时后看漂移sudo iptables -D OUTPUT -p udp --dport 123 -j DROP
漂移 < 5 秒说明硬件时钟健康。
# 跑 stress-ngstress-ng --cpu 4 --vm 2 --vm-bytes 1G --timeout 600# 同时看 chronycwatch -n 1 'chronyc tracking'
应该看到 offset 略有波动但很快收敛。
SHOW SLAVE STATUS
SHOW REPLICA STATUS
kubectl get nodes
Ready
openssl x509 -in cert.pem -noout -dates
# 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. 停 chronysudo systemctl stop chronyd# 2. 手动设时间(用可信源)sudo ntpdate ntp.aliyun.com# 或者sudo sntp -S time.aliyun.com# 3. 同步到 RTCsudo hwclock --systohc --utc# 4. 启动 chronysudo systemctl start chronyd# 5. 验证chronyc trackingdatehwclock
# 1. cordon 节点kubectl cordon node-01# 2. 排空kubectl drain node-01 --ignore-daemonsets# 3. SSH 登录节点,强制同步sudo systemctl stop chronydsudo ntpdate ntp01.internalsudo systemctl start chronydchronyc tracking# 4. uncordonkubectl uncordon node-01
极少见,通常是上游 NTP Server 时间错乱或恶意攻击。
# 1. 切到备用上游# 修改 /etc/chrony.conf 的 server 指令sudo sed -i 's/^server .*/server ntp-master01.internal iburst prefer/' /etc/chrony.confsudo systemctl restart chronyd# 2. 强制 stepchronyc makestep# 3. 监控chronyc tracking
时间同步看似基础,但实际是 Linux 运维最容易被低估的一块。chrony 是当前最主流的 NTP 客户端/服务器实现,能覆盖从云服务器、容器、K8s 节点到自建 stratum-1 的所有场景。
核心要点:
进阶方向:
/var/lib/chrony/drift
/var/log/chrony/
/var/run/chrony/chronyd.sock
/usr/bin/chronyc
/usr/sbin/chronyd
/etc/timezone
chronyc_TZ
cmdmonitor
/etc/chrony.keys
/etc/adjtime
/etc/ntp.conf
/etc/systemd/timesyncd.conf
具体指令以实际版本为准。
503 No suitable source
500 Too many sources
504 Source not found
522 Reachability not yet achieved
具体错误以 chronyc 输出为准。