首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >CVM 时间不准排查:读懂 chronyc 输出,处理未同步与配置被覆盖

CVM 时间不准排查:读懂 chronyc 输出,处理未同步与配置被覆盖

原创
作者头像
一只特立独行的兔先生
发布于 2026-11-10 18:06:02
发布于 2026-11-10 18:06:02
930
举报

云服务器上日志时间戳对不上、HTTPS 证书提示「尚未生效」、分布式锁和 Token 莫名过期,最后查出来往往是系统时间偏了几秒甚至几分钟。腾讯云 CVM 镜像默认带了时间同步配置,但自建镜像、改过 DNS、重装系统之后,这套配置很容易失效,而且失效时不会有任何告警。

这篇按排查顺序写:先判断是时钟偏差还是时区问题,再看同步服务状态、读 chronyc 输出,然后处理 Reach 为 0、偏差大却追不上、镜像里配置被改回去这三类常见情况。命令以 chrony 为准(TencentOS、CentOS、RHEL 的服务名是 chronyd,Ubuntu、Debian 是 chrony)。

先分清是时钟偏差还是时区

「时间不对」至少有三种完全不同的原因,处理方向也不同:

现象

判断方式

方向

date -u 与标准 UTC 时间差几秒以上

对照可信时间源

时钟偏差,同步没有工作

date -u 正确,date 差整数小时

看 timedatectl 的 Time zone

时区设置问题,与 NTP 无关

单台正常,几台之间互相对不上

逐台看同步源和偏差

各机器的 NTP 配置或状态不一致

先在目标机器上看一眼:

代码语言:bash
复制
date; date -u
timedatectl

timedatectl 的示例输出如下(字段以你机器上的 systemd 版本为准):

代码语言:plaintext
复制
               Local time: Fri 2026-08-21 15:14:24 CST
           Universal time: Fri 2026-08-21 07:14:24 UTC
                 RTC time: Fri 2026-08-21 07:14:24
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

重点看 Time zone、System clock synchronized 和 NTP service。如果只是时区不对,执行 timedatectl set-timezone Asia/Shanghai 即可,不用往下查。容器和宿主机共用同一个内核时钟,容器里时间不对,先去查宿主机;容器里常见的只是时区默认为 UTC。

同步服务有没有在跑

腾讯云文档的建议是:chrony 和 ntpd 二选一,同时装了优先用 chrony,并禁用 ntpd;ntpd 官方已不再维护,Ubuntu 24.04、Debian 12 等较新的发行版软件源里甚至没有 ntp 包。所以先确认到底哪个服务在管时间:

代码语言:bash
复制
systemctl is-active chronyd chrony ntpd systemd-timesyncd 2>/dev/null
systemctl is-enabled chronyd chrony 2>/dev/null

两个服务同时 active 本身就是问题,需要停掉其中一个:

代码语言:bash
复制
sudo systemctl disable --now ntpd

Ubuntu、Debian 上 ntpd 的服务名可能是 ntp,对应改成 sudo systemctl disable --now ntp。

如果 chrony 没装或没启动,装好并设置开机自启:

代码语言:bash
复制
# TencentOS / CentOS / RHEL
sudo yum install -y chrony
sudo systemctl enable --now chronyd

# Ubuntu / Debian
sudo apt install -y chrony
sudo systemctl enable --now chrony

读懂 chronyc sources 和 tracking

服务在跑,不代表在同步。看两条命令:

代码语言:bash
复制
chronyc sources -v
chronyc tracking
chronyc activity

chronyc sources -v 的输出形如下面这样(地址和数值是示意):

代码语言:plaintext
复制
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* time1.tencentyun.com          2   6   377    21   +312us[ +401us] +/-   29ms
^+ time2.tencentyun.com          2   6   377    19   +290us[ +290us] +/-   31ms
^? time3.tencentyun.com          0   6     0     -     +0ns[   +0ns] +/-    0ns

几个关键列,含义取自腾讯云文档对 chronyc 输出的说明:

  • S 列:* 是当前选中的最优源,+ 是按加权合入的备用源,- 是未合入,? 是无法联系的源。
  • Reach:最近 8 次报文的到达情况,八进制 377 表示 8 个包都收到了;0 表示一个都没收到。
  • LastRx:距离上一次收到有效报文过了多久。
  • Poll:轮询间隔的 log2 值,6 即 64 秒。

只要出现一个 ^* 并且 Reach 接近 377,同步链路就是通的。全是 ^? 且 Reach 为 0,进入下一节。

chronyc tracking 关注 System time、Last offset 和 Leap status:

代码语言:plaintext
复制
Reference ID    : A9FE0050 (169.254.0.80)
Stratum         : 3
System time     : 0.000010930 seconds fast of NTP time
Last offset     : +0.000018760 seconds
RMS offset      : 0.000018760 seconds
Update interval : 2.0 seconds
Leap status     : Normal

Leap status 为 Normal 表示正常同步;从未同步成功时,chrony 会显示 Not synchronised,Reference ID 为全零、Stratum 为 0。Last offset 为正表示本地时钟比服务器快。

chronyc activity 的输出里有一行 sources with unknown address,意思是有时钟源的域名还没解析出地址,这是判断 DNS 问题最快的入口。

Reach 为 0:按解析、路径、端口三层查

1. 域名解析

腾讯云默认的内网时钟源是域名形式:

代码语言:ini
复制
server time1.tencentyun.com iburst
server time2.tencentyun.com iburst
server time3.tencentyun.com iburst
server time4.tencentyun.com iburst
server time5.tencentyun.com iburst

这些域名依赖实例使用的内网 DNS。官方 FAQ 明确写了:改变内网 DNS 会影响依赖内网域名的功能,其中就包括 NTP 时间同步(yum 源和监控上报也一样)。所以自建 DNS、手工改了 /etc/resolv.conf 的机器,要先验证:

代码语言:bash
复制
getent hosts time1.tencentyun.com
cat /etc/resolv.conf

解析不出来就先修 DNS,或者让自建 DNS 把 tencentyun.com 转发回腾讯云内网 DNS;不要直接在 chrony.conf 里换成不可达的公网源。

2. 内网源只对云上实例可用

time1 到 time5.tencentyun.com 这组内网 NTP 仅腾讯云上的实例可用。云下机器、其他云的机器要用外网源,官方文档列出的外网地址是 ntp.tencent.com、ntp1.tencent.com 到 ntp5.tencent.com(旧的 time.cloud.tencent.com 系列仍可用,但建议换新地址)。

3. 抓包看 UDP 123

解析正常还是不通,就直接看包:

代码语言:bash
复制
sudo tcpdump -ni any udp port 123
  • 完全没有出站包:chronyd 没在发,回头查服务状态和解析结果。
  • 有出站、没有回包:路径上被拦了,检查本机防火墙(firewall-cmd、iptables)和安全组出站规则,具体以你的规则配置为准。
  • 回包的源地址和你配置的不一致:NAT 或策略路由改了源地址,见下一小节。

如果这台机器自己要对外提供 NTP 服务,还要在 chrony 里配置 allow,并让安全组放通入站 UDP 123,官方文档对此有明确提示。

4. 外网源被拦截与源地址问题

官方 FAQ 里有两个值得记住的案例:

  • 使用外网 NTP 时出现 no server suitable for synchronization found(ntpdate 一类工具的提示):可能是实例公网 IP 受到 DDoS 攻击,触发了 NTP 反射防护,针对访问腾讯云、源端口为 123 的外网流量被全部拦截,导致同步异常。文档的建议是尽量使用内网 NTP 源。
  • ntpd 报 localhost.localdomain timeout:可能做了 POSTROUTING(源地址转换),文档的处理是把 ntp.conf 里的源 IP 改为 eth0 的 IP。chrony 里对应的是 bindacqaddress 指令(见 man chrony.conf),这一条腾讯云文档没有写,需要自行验证。

偏差很大,但一直追不上

同步状态正常、Reach 也是 377,时间却偏了几十秒甚至更多,常见于实例被挂起恢复、chronyd 长时间停过之后。原因在 makestep。

腾讯云默认配置里是:

代码语言:ini
复制
makestep 1.0 3
rtcsync
leapsectz right/UTC

makestep 1.0 3 的含义是:chronyd 启动后的前 3 次时间调整里,如果偏差超过 1 秒,就直接跳变到正确时间;之后即使偏差再大,也只会通过加快或减慢时钟来平滑追赶,追上需要很长时间。所以服务已经跑了一阵子才出现的大偏差,看上去就是「同步着但时间一直不对」。

这时有两种处理:

代码语言:bash
复制
# 立即步进一次,会造成时间跳变
sudo chronyc makestep
chronyc tracking | grep -E 'System time|Last offset'

如果机器本身时钟不稳定(TencentOS 官方文档针对虚拟机时间经常不准确的场景),可以把配置改成不限次数步进:

代码语言:ini
复制
makestep 1.0 -1

改完 sudo systemctl restart chronyd 生效。两种做法都会让时间发生跳变,官方也提醒生产环境谨慎使用。时间往回跳时,依赖单调递增时间戳的程序(数据库主从、基于时间的 ID 生成、分布式锁租期、定时任务)可能出现异常,建议在业务低峰期、必要时先摘流量再执行。

重装或用自定义镜像后配置被改回去

这类问题的典型表现是:机器上手工配好了 NTP,用它制作自定义镜像,新实例起来后 NTP 配置又变回了默认值,或者新实例时间与正常时间不一致。

官方 Cloud-Init 文档的说明是:实例首次启动时,Cloud-Init 会根据 vendor_data.json 中的 NTP Server 信息设置实例的 NTP 服务器配置,并拉起 NTP 服务。想保留镜像里自己配置的 NTP,需要在制作自定义镜像之前,删掉 /etc/cloud/cloud.cfg 里的 - ntp 这一行。

代码语言:bash
复制
# 先确认 ntp 相关行在哪里,并备份
sudo grep -n 'ntp' /etc/cloud/cloud.cfg
sudo cp /etc/cloud/cloud.cfg /etc/cloud/cloud.cfg.bak

# 删除 - ntp 行
sudo sed -i '/^[[:space:]]*-[[:space:]]*ntp[[:space:]]*$/d' /etc/cloud/cloud.cfg
sudo grep -n 'ntp' /etc/cloud/cloud.cfg

# 制作镜像前确认同步服务开机自启
sudo systemctl is-enabled chronyd

另一个相反的情况:镜像里压根没开 NTP,新实例时间就是和正常时间不一致。官方 FAQ 的建议是先按「Linux 实例:配置 NTP 服务」配好,再重新创建自定义镜像。两种情况的判断依据其实是同一个:新实例首次启动后,/etc/chrony.conf(Ubuntu、Debian 是 /etc/chrony/chrony.conf)里的 server 行是谁写的,以及服务是否设置了开机自启。

把检查固化成巡检

时间偏差属于「出事前没有任何征兆」的问题,建议放进巡检或定时任务里。下面的脚本在未同步或偏差超过阈值(默认 0.5 秒)时返回非 0:

代码语言:bash
复制
#!/usr/bin/env bash
# 用法:./chk_time.sh [阈值秒数]
THRESHOLD=${1:-0.5}
out=$(chronyc tracking) || { echo "chronyc 执行失败"; exit 3; }
leap=$(echo "$out" | awk -F': ' '/^Leap status/ {print $2}')
offset=$(echo "$out" | awk '/^System time/ {print $4}')

if [ "$leap" != "Normal" ]; then
  echo "leap status: ${leap:-unknown}"
  exit 2
fi
awk -v o="$offset" -v t="$THRESHOLD" 'BEGIN { exit (o + 0 > t + 0) ? 1 : 0 }' \
  || { echo "offset ${offset}s exceeds ${THRESHOLD}s"; exit 1; }
echo "ok, offset ${offset}s"

System time 一行里的数值是绝对值,快慢用后面的 fast 或 slow 表示,脚本只比较大小即可。

排查清单

  1. timedatectl 先分清时区问题和时钟偏差,时区问题用 timedatectl set-timezone 解决。
  2. systemctl is-active chronyd chrony ntpd systemd-timesyncd:只留一个同步服务,优先 chrony,并设置开机自启。
  3. chronyc sources -v:有 ^* 且 Reach 接近 377 才算同步成功;全是 ^?、Reach 为 0 往下查。
  4. chronyc activity 出现 unknown address,或 getent hosts time1.tencentyun.com 解析失败:查 DNS,改过内网 DNS 会影响 NTP。
  5. 解析正常仍不通:tcpdump -ni any udp port 123 看有无出站和回包,再查本机防火墙和安全组;云下机器改用外网源。
  6. 同步正常但偏差大:理解 makestep 1.0 3 只管前 3 次调整,必要时 chronyc makestep 手动步进,评估业务影响后再决定是否改成 makestep 1.0 -1。
  7. 自定义镜像或重装后配置被改:制作镜像前删除 /etc/cloud/cloud.cfg 里的 - ntp,并确认镜像里已启用同步服务。
  8. 验证标准:chronyc tracking 的 Leap status 为 Normal、System time 在预期范围内,timedatectl 显示 System clock synchronized: yes。

参考文档

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 先分清是时钟偏差还是时区
  • 同步服务有没有在跑
  • 读懂 chronyc sources 和 tracking
  • Reach 为 0:按解析、路径、端口三层查
    • 1. 域名解析
    • 2. 内网源只对云上实例可用
    • 3. 抓包看 UDP 123
    • 4. 外网源被拦截与源地址问题
  • 偏差很大,但一直追不上
  • 重装或用自定义镜像后配置被改回去
  • 把检查固化成巡检
  • 排查清单
  • 参考文档
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档