结论: 服务器时间不同步先别急着手工改时间,先用 timedatectl status 与 chronyc tracking 判断偏差量与同步状态:偏差小于 1 秒通常让 chrony 自动缓步追平;偏差很大或 chronyd 起不来,再依次排查 UDP 123 出站、NTP 服务器可达性、服务冲突与硬件时钟。修完必须 hwclock --systohc 写回硬件时钟。
引言:时间不对,是最容易被误诊的故障
服务器时间不同步的表现形式极具迷惑性:浏览器提示"您的连接不是私密连接"看起来像证书问题,定时任务没执行看起来像 cron 坏了,主从复制中断看起来像数据库故障,日志时间对不上让人完全无法复盘。而它们的根因可能只是系统时钟偏了三分钟。
时间之所以重要,是因为它是一批安全机制的隐含前提:TLS 证书校验依赖当前时间落在 notBefore 与 notAfter 之间;Kerberos 默认只容忍 5 分钟偏差;etcd、ZooKeeper、Consul 这类分布式组件用心跳超时判断节点存活;数据库主从与 binlog 也依赖时间戳排序。一旦时间错乱,这些组件会以各不相同的症状同时报错。
本文讲的是故障排查,即"已经出问题了怎么定位并修复";如果你想从零搭建一套时间同步体系,可以参考配置向的文章。
第一步:确认时间偏差到底有多大
结论: 用 date 与 timedatectl status 看系统时间,用 hwclock -r 看硬件时钟,用 chronyc tracking 看与上游的最后偏差量;三者对比即可判断是"时区搞错了"还是"时钟真的漂移了"。
时区错和时间错是两件完全不同的事:前者表现为时间整整差 8 小时(或若干整数小时),后者表现为偏差几分钟到几小时不等,且会持续增长。
# 系统当前时间与 UTC 对照
date
date -u
timedatectl status
# 硬件时钟(RTC)读取,与系统时间对比
hwclock -r
hwclock --compare # 对比系统与硬件时钟差值
# chrony 的同步详情:核心命令
chronyc tracking
chronyc sources -v
chronyc sourcestats -v
# 若使用 ntpd(较少见)
ntpq -p
ntpstattimedatectl status 的输出里要重点看三行:System clock synchronized: yes/no(是否已同步)、NTP service: active/inactive(同步服务是否启用)、Time zone(时区)。三者都为正常才算真的没问题。
chronyc tracking 里最关键的是 Last offset(最后一次与上游的偏差)与 Leap status(闰秒状态,正常为 Normal)。若 Last offset 持续大于 1 秒且 System clock synchronized 为 no,说明同步链路断了。
第二步:chronyd / ntpd 服务起不来怎么排查
结论: 服务起不来先 systemctl status 看退出码,再用 journalctl -u chronyd 看具体报错;最常见的三类原因是与 systemd-timesyncd 端口冲突、配置文件 server 行不可达、以及容器/云镜像里 chrony 根本没装。
截至 2026 年,主流发行版的时间同步栈已经收敛:Ubuntu 24.04 LTS 默认使用 systemd-timesyncd,RHEL 9 / Rocky 9 / AlmaLinux 9 / openEuler 默认使用 chrony,ntpd 只在个别老系统上还活着。三者同时运行会争抢 UDP 123 端口,导致后启动的那个 bind 失败。
# 看服务状态与最近日志
systemctl status chronyd --no-pager -l
journalctl -u chronyd -b --no-pager | tail -40
# 确认是否有多个时间服务在抢 123 端口
systemctl status systemd-timesyncd --no-pager
ss -lunp | grep ':123'
# 冲突处置:保留 chrony,停掉 timesyncd
systemctl disable --now systemd-timesyncd
systemctl enable --now chronyd
# 未安装时安装(按发行版选择)
apt install -y chrony # Debian / Ubuntu
dnf install -y chrony # RHEL / Rocky / Alma / openEuler
# 手工测试:让 chronyd 前台跑一次并输出,能看到真实报错
chronyd -Q -t 5 'server pool.ntp.org iburst'若 chronyd 报 Could not bind socket : Address already in use,就是端口冲突;若报 No suitable source for synchronization,则是上游不可达或 UDP 123 被挡,进入下一步。
还要说明一点:ntpdate 已经废弃。它在 RHEL 8 之后被移除,Debian/Ubuntu 也将其标记为 deprecated,因为它采用"一步跳变"校准,会打断正在运行的服务。需要立即校准时用 chrony 的 chronyc makestep 或 chronyd -q:
# 允许 chrony 做一次大步跳变(默认只在偏差 > 1 秒的前 3 次更新中自动跳变)
chronyc makestep
# 或前台一次性校准后退出(类似老 ntpdate 的用法)
chronyd -q 'server ntp.aliyun.com iburst'第三步:UDP 123 出站被挡是最常见的"起不来"原因
结论: NTP 使用 UDP 123 端口, outbound 方向必须放通;云服务器尤其要检查安全组/ACL 的出站规则,因为很多厂商默认只放通常见的 TCP 出站。
这是最容易被忽略的一环:服务器本身能上网、ping 也通,但 NTP 就是同步不了,因为 UDP 123 被安全组静默丢弃了(UDP 丢包不会有明确报错,只会表现为"等不到回应")。
# 1. 先确认 DNS 能解析 NTP 服务器域名
getent hosts ntp.aliyun.com
# 2. 测试 UDP 123 连通性(chronyd 自带工具最准)
chronyd -Q -t 5 'server ntp.aliyun.com iburst'
# 3. 用 nc 探测 UDP(注意 UDP 无回显,超时不代表一定不通,需结合 chronyc 判断)
nc -vzu ntp.aliyun.com 123
nc -vzu 203.107.6.88 123
# 4. 抓包确认是否有出无回
tcpdump -ni any udp port 123 -c 20
# 5. 本机防火墙出站是否拦截
iptables -S OUTPUT | grep 123
firewall-cmd --list-all如果确认是安全组问题,需要在云控制台的出站规则中放行 UDP 123(目标可以是指定 NTP 服务器 IP,也可以是 0.0.0.0/0)。同时确认内网 DNS 能解析 NTP 域名,否则会出现"端口通但找不到服务器"的情况。
常用 NTP 服务器对照表
| 提供方 | 服务器地址 | 适用场景 | 说明 |
|---|---|---|---|
| 阿里云 | ntp.aliyun.com、ntp1~ntp7.aliyun.com | 阿里云 ECS、国内服务器 | 内网延迟低,国内首选;截至 2026 年免费开放 |
| 腾讯云 | time1~time5.cloud.tencent.com | 腾讯云 CVM、轻量 | 与阿里云类似,优先选同厂商 |
| 华为云 | ntp.huaweicloud.com | 华为云 ECS | 同上 |
| 微软 | time.windows.com | Windows Server 默认 | Windows 自带的默认源,Linux 也可用 |
| Apple | time.apple.com | 通用备用 | 全球可用,国内延迟略高 |
| NTP Pool 项目 | pool.ntp.org、cn.pool.ntp.org | 通用/海外服务器 | 志愿者池,建议配 iburst 加速首次同步 |
| 国家授时中心 | ntp.ntsc.ac.cn | 需要权威授时的场景 | 中国科学院国家授时中心提供 |
配置示例(/etc/chrony.conf,RHEL 系路径;Debian/Ubuntu 为 /etc/chrony/chrony.conf):
# 注释掉默认的 pool 行,改用国内源并加 iburst 加速首次同步
pool ntp.aliyun.com iburst
pool cn.pool.ntp.org iburst
# 允许 chrony 在前 3 次更新中做时间跳变(偏差大时必开)
makestep 1.0 3
# 把同步后的系统时间写回硬件时钟(chrony 默认每 11 分钟一次)
rtcsync
# 修改后重启服务并验证
systemctl restart chronyd
chronyc sources -v第四步:容器时区不一致
结论: 容器默认使用 UTC 时区,与宿主机的 Asia/Shanghai 不一致,表现为应用日志时间与宿主机差 8 小时、定时任务在错误时刻触发。修法是把宿主机的 /etc/localtime 与 /etc/timezone 挂进容器,或设置 TZ 环境变量。
注意区分两件事:容器的时间值默认与宿主机共享内核时钟,不会独立漂移;容器的时区则是独立的,来自镜像内的 /etc/localtime。所以"容器时间和宿主机差 8 小时"几乎总是时区问题,而不是同步问题。
# 宿主机设置时区
timedatectl set-timezone Asia/Shanghai
timedatectl status | grep 'Time zone'
# 容器内查看时区
docker exec <容器名> date
docker exec <容器名> cat /etc/timezone 2>/dev/null || echo "无 timezone 文件"
# 方式一:挂载宿主机时区文件(推荐,最稳妥)
docker run -d --name web \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
nginx:1.26
# 方式二:环境变量(需基础镜像含 tzdata)
docker run -d --name app -e TZ=Asia/Shanghai myapp:1.0# docker-compose.yml 写法
services:
app:
image: myapp:1.0
environment:
- TZ=Asia/Shanghai
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:roKubernetes 环境下,Pod 同样继承节点时钟,时区通过挂载 hostPath 或 downward 方式解决;更推荐的做法是在镜像构建阶段就 RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime,一劳永逸。
第五步:时间偏差会引发哪些连锁故障
结论: 时间偏差的影响远不止"显示不对",它会直接击穿证书校验、身份认证、定时任务和分布式一致性四类机制。
- TLS/SSL 证书校验失败:时间早于
notBefore会报certificate is not yet valid,晚于notAfter会报certificate has expired。这是"证书没到期却提示过期"的头号原因。 - Kerberos / AD 域认证失败:默认容忍 5 分钟偏差,超限时报
Clock skew too great。 - 定时任务误触发或漏触发:cron 按系统时间执行,时间错乱会导致备份在非业务低峰执行,或整点任务被跳过。
- 分布式集群异常:etcd、ZooKeeper、Consul 依靠心跳判活,节点间时间差过大会导致频繁 Leader 选举甚至脑裂。
- 日志时间线错乱:多台服务器时间不一致时,跨机器排查一次请求的耗时链路会完全无法对齐。
快速验证证书与时间的关系:
# 查看证书有效期与当前时间的相对关系
openssl x509 -in /etc/nginx/ssl/server.crt -noout -dates
date -u
# 直接对站点做一次带时间校验的握手测试
openssl s_client -connect example.com:443 -servername example.com &1 \
| grep -E 'Verify return code|notBefore|notAfter'
# 看日志时间是否与实际相符(对比 tail 出来的时间与 date)
tail -5 /var/log/nginx/access.log; date排查命令速查表
| 目的 | 命令 | 关键观察点 |
|---|---|---|
| 看整体状态 | timedatectl status | System clock synchronized: yes、NTP service: active |
| 看偏差量 | chronyc tracking | Last offset、Leap status: Normal |
| 看上游源 | chronyc sources -v | 行首为 ^* 表示当前正在使用的源;? 表示不可达 |
| 手工跳变校准 | chronyc makestep | 偏差大时立即追平,可能影响运行中的服务 |
| 前台一次性测试 | chronyd -Q -t 5 'server ntp.aliyun.com iburst' | 输出 offset 即为成功 |
| 改时区 | timedatectl set-timezone Asia/Shanghai | 与 date 对照,应正好差 8 小时 |
| 写回硬件时钟 | hwclock --systohc | 修完必做,否则重启后回到错误时间 |
| 硬件时钟读回 | hwclock --hctosys | RTC 正确而系统时间错时使用 |
| 容器时区 | docker exec <容器> date | 与宿主机 date 对比是否差 8 小时 |
| Windows 侧 | w32tm /query /status、w32tm /resync | Source 与 Last Successful Sync Time |
企业QQ咨询




