NTP 时间同步故障排查实战指南

一、故障背景

时间同步是分布式系统的基石。在运维实践中,NTP(Network Time Protocol)时间不同步会导致:

  • 数据库主从复制失败
  • 证书验证失效
  • 日志时间戳混乱
  • 分布式事务一致性破坏
  • Kerberos 认证失败

本文基于 Chrony/NTPd 实战经验,系统梳理时间同步故障的排查方法论。

二、故障现象识别

2.1 典型症状

1
2
3
4
5
6
7
8
9
# 检查系统时间与 NTP 服务器时间差
date && ntpq -p

# Chrony 用户检查同步状态
chronyc tracking
chronyc sources -v

# NTPd 用户检查对等体状态
ntpq -pn

告警阈值参考:

  • 偏移量 > 100ms:警告
  • 偏移量 > 1s:严重
  • 偏移量 > 128ms 且持续:Kerberos 可能失效

2.2 快速诊断命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 一键检查时间同步健康度
check_ntp_health() {
echo "=== 系统时间 ==="
date
echo ""
echo "=== Chrony 状态 ==="
chronyc tracking 2>/dev/null || echo "Chrony 未运行"
echo ""
echo "=== 时间源状态 ==="
chronyc sources -v 2>/dev/null || ntpq -pn 2>/dev/null || echo "无可用时间源"
echo ""
echo "=== 时间偏移 ==="
chronyc offset 2>/dev/null || echo "无法获取偏移量"
}

三、故障排查流程

3.1 第一步:确认服务状态

1
2
3
4
5
6
7
8
9
10
# 检查 Chrony 服务
systemctl status chronyd
journalctl -u chronyd -n 50 --no-pager

# 检查 NTPd 服务
systemctl status ntp
journalctl -u ntp -n 50 --no-pager

# 检查端口监听
ss -ulnp | grep -E '123|chrony'

常见问题:

  • 服务未启动:systemctl start chronyd
  • 配置错误:检查 /etc/chrony/chrony.conf/etc/ntp.conf
  • 端口冲突:123 端口被其他进程占用

3.2 第二步:检查网络连通性

1
2
3
4
5
6
7
8
9
10
11
# 测试 NTP 服务器可达性
ping -c 3 ntp.aliyun.com
ping -c 3 time.cloudflare.com

# 测试 NTP 端口连通性
nc -zv -u ntp.aliyun.com 123
nc -zv -u time.cloudflare.com 123

# 检查防火墙规则
iptables -L -n | grep 123
firewall-cmd --list-all | grep 123

防火墙放行命令:

1
2
3
4
5
6
7
8
9
# Ubuntu/Debian
ufw allow out 123/udp

# CentOS/RHEL
firewall-cmd --permanent --add-port=123/udp
firewall-cmd --reload

# iptables
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT

3.3 第三步:分析时间源质量

1
2
3
4
5
6
7
8
# Chrony 查看时间源详情
chronyc sources -v

# 输出解读:
# ^ = 服务器,= = 对等体,* = 当前同步源,+ = 候选源
# MS = 模式 (6=客户端,3=服务器)
# Reach = 可达性寄存器 (377=最近 8 次都成功)
# LastRx = 上次收到响应的时间

时间源质量问题:

  • Reach 值低:网络不稳定或服务器不可达
  • LastRx 过大:超过 64 秒未收到响应
  • Stratum 过高:时间源层级过深,精度下降

3.4 第四步:检查系统时钟源

1
2
3
4
5
6
7
8
9
10
# 查看当前时钟源
cat /sys/devices/system/clocksource/clocksource0/current_clocksource

# 查看可用时钟源
cat /sys/devices/system/clocksource/clocksource0/available_clocksource

# 虚拟机推荐时钟源
# KVM: kvm-clock
# VMware: vmx-tsc
# Xen: xen

时钟源切换:

1
2
3
4
5
6
7
# 临时切换
echo kvm-clock > /sys/devices/system/clocksource/clocksource0/current_clocksource

# 永久切换 (GRUB 配置)
# 编辑 /etc/default/grub,添加:
# GRUB_CMDLINE_LINUX="clocksource=kvm-clock"
# 然后 update-grub && reboot

3.5 第五步:排查硬件时钟问题

1
2
3
4
5
6
7
8
9
10
11
# 查看硬件时钟
hwclock --show

# 同步硬件时钟到系统时钟
hwclock --hctosys

# 同步系统时钟到硬件时钟
hwclock --systohc

# 检查 RTC 状态
cat /proc/driver/rtc

常见问题:

  • 主板电池耗尽:硬件时钟掉电后重置
  • 虚拟化环境:宿主机时间漂移影响虚拟机
  • BIOS 设置:检查 RTC 是否启用

四、典型故障案例

4.1 案例一:虚拟机时间漂移

现象: KVM 虚拟机时间逐渐变慢,每天漂移数分钟

原因: 未使用 KVM 专用时钟源,依赖 TSC 导致漂移

解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 检查当前时钟源
cat /sys/devices/system/clocksource/clocksource0/current_clocksource

# 2. 切换为 kvm-clock
echo kvm-clock > /sys/devices/system/clocksource/clocksource0/current_clocksource

# 3. 永久生效 (宿主机和虚拟机)
# 虚拟机 GRUB 添加:clocksource=kvm-clock
# 宿主机 QEMU 启动参数添加:-cpu host,kvmclock=on

# 4. 安装 qemu-guest-agent 增强时间同步
apt install qemu-guest-agent
systemctl enable qemu-guest-agent

4.2 案例二:防火墙阻断 NTP 流量

现象: Chrony 显示所有时间源 Reach=0,无法同步

排查:

1
2
3
4
5
6
7
8
# 1. 检查 Chrony 日志
journalctl -u chronyd -f | grep -i "no response"

# 2. 测试 UDP 123 端口
nc -zv -u ntp.aliyun.com 123

# 3. 检查 iptables 规则
iptables -L OUTPUT -n -v | grep 123

解决:

1
2
3
4
5
# 放行出站 NTP 流量
iptables -A OUTPUT -p udp --dport 123 -d 0.0.0.0/0 -j ACCEPT

# 或使用 UFW
ufw allow out 123/udp comment "NTP time sync"

4.3 案例三:时间跳变导致服务异常

现象: NTP 同步时时间突然跳变 5 分钟,导致数据库连接断开

原因: 初始偏移量过大,Chrony 使用步进模式而非渐进模式

解决:

1
2
3
4
5
6
7
8
9
10
11
# 1. 修改 Chrony 配置,限制单次调整幅度
# /etc/chrony/chrony.conf
maxupdateskew 100.0
makestep 1.0 3

# 2. 对于超大偏移,手动分步调整
chronyc -a 'step @$(date +%s)' # 先步进到大致时间
chronyc -a 'maxrate 100' # 限制后续调整速率

# 3. 重启服务
systemctl restart chronyd

4.4 案例四:多网卡环境时间源绑定错误

现象: 服务器有多个网卡,NTP 请求从错误网卡发出被防火墙拦截

解决:

1
2
3
4
5
6
7
8
9
10
11
# 1. 指定绑定的网络接口
# /etc/chrony/chrony.conf
bindaddress 192.168.1.100
bindcmdaddress 127.0.0.1

# 2. 或指定特定路由
ip route add ntp.aliyun.com via 192.168.1.1 dev eth0

# 3. 验证请求源地址
chronyc -n sources | head -5
tcpdump -i eth0 -n udp port 123 -c 10

五、最佳实践建议

5.1 时间源选择策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 推荐配置(Chrony)
# /etc/chrony/chrony.conf

# 国内用户优先使用国内源
server ntp.aliyun.com iburst
server ntp.tencent.com iburst
server ntp.ntsc.ac.cn iburst

# 国际备用源
server time.cloudflare.com iburst
server pool.ntp.org iburst

# 本地硬件时钟作为 fallback
rtcsync

# 保持至少 3 个时间源
minsources 3

5.2 监控告警配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Prometheus 告警规则
# /etc/prometheus/rules/ntp_alerts.yml

groups:
- name: ntp_alerts
rules:
- alert: NtpOffsetHigh
expr: abs(node_ntp_offset_seconds) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "NTP 时间偏移过高"
description: "服务器 {{ $labels.instance }} NTP 偏移 {{ $value }}s"

- alert: NtpNoSync
expr: node_ntp_sync == 0
for: 10m
labels:
severity: critical
annotations:
summary: "NTP 未同步"
description: "服务器 {{ $labels.instance }}{{ $value | humanizeDuration }} 未同步"

5.3 定期健康检查脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
# /usr/local/bin/ntp_health_check.sh

OFFSET=$(chronyc offset | awk '{print $2}')
OFFSET_ABS=${OFFSET#-} # 取绝对值

if (( $(echo "$OFFSET_ABS > 0.1" | bc -l) )); then
echo "CRITICAL: NTP offset ${OFFSET}s exceeds threshold"
exit 2
elif (( $(echo "$OFFSET_ABS > 0.05" | bc -l) )); then
echo "WARNING: NTP offset ${OFFSET}s approaching threshold"
exit 1
else
echo "OK: NTP offset ${OFFSET}s within normal range"
exit 0
fi

六、总结

时间同步故障排查核心要点:

  1. 先服务后网络:确认 NTP 服务运行正常,再排查网络连通性
  2. 先本地后远程:检查本地时钟源配置,再验证远程时间源
  3. 先软件后硬件:排除配置问题,再考虑硬件时钟故障
  4. 监控先行:部署 NTP 偏移监控,故障发生前预警

记住:时间同步是基础设施中的基础设施,值得投入精力做好监控和维护。


参考文档: