chrony的makestep未生效是因为默认禁用跳变,需显式配置且满足偏差超限、已完成初始同步两个条件;常见原因包括未重启服务、启动时网络不可达导致卡在initializing状态。

chrony 的 makestep 为什么没生效?
默认情况下 chrony 不会主动跳变系统时间,即使偏差远超阈值——这是设计使然,防止意外跳变破坏日志、数据库事务等依赖单调时间的场景。只有显式启用 makestep 才可能触发跳变,且需满足两个条件:偏差超过设定阈值,且 chronyd 已完成初始同步(即进入“synchronized”状态)。
常见错误是只在 /etc/chrony.conf 中写了 makestep 1.0 -1,但没重启服务,或 chronyd 启动时网络未就绪、NTP 源不可达,导致始终卡在“initializing”状态,makestep 根本不触发。
-
makestep的第二参数为负数(如-1)表示“对所有启动阶段生效”,但仅对首次同步有效;后续运行中若时间偏差再次超限,仍需手动干预或配合chronyc makestep - 检查状态用
chronyc tracking,确认输出中Leap status是Normal且System time行有数值,才说明已同步 - 若 chronyd 启动时网络未通,可加
makestep 1.0 0(0 表示仅对启动后首次同步生效),再配合network-manager或systemd-networkd的启动顺序控制
timekeeping watchdog expired 错误的真实含义
这不是 chrony 报的错,而是内核在检测到长时间未更新 clock_gettime(CLOCK_MONOTONIC) 或 CLOCK_REALTIME 时触发的 panic 或 warning,常见于虚拟机暂停后恢复、CPU 长时间离线、或系统时间被暴力修改(如直接写 /dev/rtc)导致内核 timekeeper 逻辑失步。此时 chrony 可能还在跑,但内核已拒绝更新时间。
该错误出现后,chronyc tracking 常显示 Leap status: Not synchronised,且 chronyc sources -v 中延迟异常高,因为 chronyd 尝试校正时被内核拦截。
- 不要立刻执行
hwclock --hctosys,这会加剧失步;先用cat /proc/sys/kernel/watchdog_thresh查看当前看门狗阈值(默认 60 秒),再确认是否真有 CPU hang 或 VM pause - 在 KVM/qemu 虚拟机中,需确保启用了
kvm-clock(检查dmesg | grep kvm-clock),并关闭host-passthrough模式下不兼容的 TSC 特性 - 物理机上若频繁触发,检查是否有 BIOS 时间同步功能(如 Intel RAS “Time Sync”)与 chrony 冲突
hwclock 修复的边界在哪?
hwclock 只操作硬件时钟(RTC),它不能替代 chrony 的时间同步逻辑,也不能修复内核 timekeeper 失步。它的作用非常有限:仅在系统启动早期、chronyd 尚未启动前,把 RTC 时间载入系统时钟;或在关机前把系统时间写回 RTC。一旦 chronyd 运行起来,它默认忽略 RTC,完全依赖 NTP 源。
典型误用是发现时间错乱后执行 hwclock --hctosys && systemctl restart chronyd——这可能导致系统时间瞬间倒退或跳跃,触发应用报错,且 chronyd 启动后仍会按自己的逻辑覆盖。
- 若 RTC 本身不准(如电池老化),
hwclock --show显示时间与网络时间差几百秒,应先用hwclock --set --date="2024-06-01 12:00:00"手动校准 RTC,再重启 chronyd - chrony 配置中
rtcsync选项会让 chronyd 定期(默认 11 分钟)把系统时间写回 RTC,比hwclock --systohc更可靠,但前提是系统时间本身已正确 - 某些嵌入式设备无 RTC,
/dev/rtc不存在,此时hwclock直接失败,必须依赖 chrony +makestep或外部授时源
时间跳跃后最易被忽略的三件事
哪怕 chrony 成功跳变了时间,应用层未必感知一致:日志时间戳、数据库事务 ID、TLS 证书有效期验证都可能因时间突变出问题。这些不是 chrony 能管的,得靠运维动作补救。
- 检查
journalctl --since "1 hour ago"是否有大量clock skew detected或time jumped backwards记录,重点排查rsyslog、auditd、postgresql等对时间敏感的服务 - Docker 容器若使用
--privileged或挂载了/dev/rtc,其内部时间可能与宿主不同步,需在容器内也部署 chrony 或使用docker run --time=...(v24.0+) - Kubernetes 集群中,Node 时间偏差超过 1 秒会导致 kubelet 拒绝上报心跳,Pod 状态卡在
Unknown;此时仅修 chrony 不够,还要kubectl drain & uncordon强制刷新节点状态











