ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

NTP与Chrony时间同步实战:从原理到配置与排错

NTP与Chrony时间同步实战:从原理到配置与排错 时间同步这件事平时没人关注可一旦出了问题全是噩梦。日志时间对不上排查起来想骂人、证书校验直接失败、数据库主从报错、定时任务提前或延后执行这些都是我实际见过的情况。不管是搞运维、搭集群还是自己玩软路由、NAS时间同步都是必须打好基础的服务。这篇博文围绕 NTP 和 Chrony 这两个最常用的时间同步方案从原理讲到底层配置再把我这几年的实操排错经验一并写出来希望你们看完能少走弯路。先说结论性建议如果你是 CentOS/RHEL 8 之后的系统直接用 Chrony 就好它在同步速度和抗干扰能力上比传统 NTP 好太多如果你还在维护老旧的 CentOS 6/7 或某些特殊品类设备那就老老实实用 NTP够用且稳。Windows Server 场景下系统自带的 W32Time 服务也能扛起大半边天。我会在下面逐层拆开讲。1. 时间同步到底在解决什么核心问题1.1 无时不在的时间陷阱为什么服务器必须有统一时间我见过很多刚入行的朋友觉得“服务器时间差几分钟无所谓”这个想法其实挺危险的。技术世界里时间是很多机制的底层依赖。比如 HTTPS 证书校验证书的生效时间和失效时间直接被系统时钟影响如果系统时间比真实时间快了半天可能直接触发证书“尚未生效”或“已过期”的错误然后用户访问你的网站就会看到吓人的安全警告。再比如数据库的主从复制很多基于时间戳的增量同步方案在主从时间差异过大时会直接中断或者更隐蔽的是产生逻辑错误的数据覆盖这种问题排查起来极其痛苦日志里面全是莫名其妙的时间跳跃。还有日志分析不管是 ELK 还是 Splunk多台机器的日志汇聚到一起后如果没有统一准确的时间按时间线去还原一次故障过程就完全不可能。你可能看到 A 机器的报错在 B 机器的报错“之前”但实际上它们的先后顺序正好反过来那你排查的方向就完全错了。分布式系统中的分布式锁、缓存过期、消息队列的延迟消息调度也都依赖精确可靠的时钟。在金融交易、电力调度这种领域时间精度甚至要求到毫秒甚至微秒级别。可以说时间同步不是一个“锦上添花”的配置而是一个“地基型”的基础设施。1.2 硬件时钟、系统时钟与时间漂移先把概念理清楚想搞懂时间同步你得先明白计算机里其实有两个时钟一个是硬件时钟另一个是系统时钟。硬件时钟也叫 RTCReal-Time Clock是主板上那块靠电池供电的独立计时芯片就算机器彻底断电它也在走只是精度一般般受温度和环境的影响容易漂移。系统时钟则是操作系统内核维护的软件时钟系统启动的时候从硬件时钟读取一个初始时间之后完全靠内核的定时器机制在维护。问题在于系统时钟使用的晶体振荡器频率不可能绝对精准温度变化、设备老化都会让OS层面的计时出现累积误差这就是常说的“时间漂移”。一台普通服务器一天漂移几秒到几十秒都算正常实测某些品质稍差的硬件在负载较高或机房温度偏高时一天漂个一两分钟也不稀奇。如果一直不做校正时间只会偏离真实世界越来越远。NTP 和 Chrony 这类服务本质上就是定期去对应的“标准时间源”校准系统时钟把漂移纠正回来。另外强调一点同步服务默认调整的是系统时钟硬件时钟往往需要额外配置或由系统定期把系统时间回写到硬件时钟省电模式下更要注意这一点。2. NTP 和 Chrony两大主角的选型对比与工作原理2.1 NTP 的经典时间同步机制分层、协商与滤波NTPNetwork Time Protocol是一个从 1985 年活到现在的老牌协议核心是层级化的时间源结构。顶层的 Stratum 0 是原子钟、GPS/北斗卫星授时模块等真正高精度的物理时钟源它们自己不对外提供 NTP 服务Stratum 1 服务器直接从 Stratum 0 获取时间同时对外提供时间同步服务Stratum 2 从 Stratum 1 同步再给下面层级提供服务以此类推。层级越往下时间精度损耗越多但能扛住的客户端数量也越多。实际项目中Stratum 1 和 Stratum 2 是最常直接用的。客户端的同步过程不止是简单“对一下表”NTP 客户端会连续多次与服务端交换带有发送和接收时间戳的数据包再结合网络往返延迟等数据统计算出时间偏移量和网络延迟然后通过一个类似“筛选聚类合并”的算法从多个候选时间源里挑出最优那个。此外 NTP 还有一个“时钟调解”机制偏差很小时会渐进式调快或调慢本地时钟而不是直接“跳变”这样可以避免因为时间突跳导致应用出现时间回退等异常只有偏差很大时才会选择立刻跳变对齐。这种设计既保精度又保稳定所以 NTP 在业界一直屹立不倒。2.2 Chrony 相比 NTPd 的强势点同步快、抗干扰、适合现代基础设施Chrony 是一个更现代的时间同步实现核心由两个程序组成chronyd 作为后台守护进程chronyc 是它的命令行管理工具。Chrony 与老牌 ntpd 相比几个优势非常突出。第一个是同步速度Chrony 启动后通常在几秒到几十秒内就能完成初步时间校准而传统 ntpd 需要长时间“冷静观察”和多次轮询才敢大幅调时这在服务器频繁重启或时间偏差很大的场景下体验差异极其明显。第二个是抗干扰和稳定性Chrony 对网络延迟抖动、上游时间服务器不稳等情况处理得更好即使网络环境比较差它也能保持相对可靠的时间精度。第三个是对硬件时间戳、精确时间协议 PTP 等新特性支持更好能在高性能网络中达到非常高的精度。再补充一个大家都关心的点Chrony 的配置文件是/etc/chrony.conf管理命令是chronyc比起 ntpd 的ntpq、ntpdate之类的工具命令输出更直观也更容易脚本化。如果你用的是较新版的 Ubuntu、Debian、CentOS/RHEL 8系统默认装的就是 Chrony。从实用出发我没理由不推荐你优先选择 Chrony。下面是两者的速查对比表对比项NTP (ntpd)Chrony初次同步速度较慢常需数分钟到数十分钟校准快通常几秒到几十秒完成初步校准网络抗干扰能力一般高延迟抖动下精度受影响较强适合不稳定网络配置文件/etc/ntp.conf/etc/chrony.conf管理工具ntpq、ntpdate、ntpstatchronyc对 PTP/硬件时间戳支持有限更好支持更多现代特性适用场景CentOS 6/7 等老系统、部分嵌入式设备现代 Linux 发行版首选2.3 上游时间源的选择与“国内常用 NTP 服务器”不管是用 NTP 还是 Chrony都要面对同一个问题上游时间服务器连谁如果公司或数据中心有自己的内网时间源那当然优先配置内网源既快又可控。如果没有就需要使用公网 NTP 服务器。这里我建议国内用户优先选择国内的时间同步地址因为公网跨海链路的延迟和丢包率都可能影响同步质量。比较推荐的国内 NTP 服务器包括中国国家授时中心的ntp.ntsc.ac.cn这是国内最权威的时间源之一主动授时能力很强实测长期稳定性让人放心还有阿里云的ntp.aliyun.com以及ntp1.aliyun.com、ntp2.aliyun.com等腾讯云的ntp.tencentyun.com也很不错。另外对于部分老旧文档里常见的cn.pool.ntp.org它属于全球 NTP Pool 在中国的节点也能用但稳定性相比国内大厂会稍弱一点。做基础场景时我习惯配置两个到三个上游源一主一备避免单一节点故障导致整条链路失效。3. 实操准备CentOS/RHEL 系列下部署 Chrony 服务3.1 环境说明与安装步骤下面我以 CentOS Stream 9 为示例方法论适用于 RHEL 8/9、Rocky Linux、AlmaLinux 等。在动手之前请先确认你是 root 用户或者有 sudo 权限避免后面每一行命令前面都得加个 sudo 显得啰嗦。然后按顺序执行# 安装 chrony 软件包如果系统是精简安装可能没有安装一下很省事 dnf install -y chrony # 设置开机自启并立即启动服务 systemctl enable --now chronyd # 确认服务状态看到 active (running) 就说明起来了 systemctl status chronyd如果是 CentOS 7 或者 Ubuntu 18.04 之前的版本可能默认还没有带 Chrony 或者软件源里不一定有需要自己评估是否额外引入软件源。不过现在这些老版本也陆续走到生命周期的尽头了如果不是特别原因还是建议尽快升级系统。接着看配置文件。默认的/etc/chrony.conf里会有一条或者几条pool指令比如pool 2.centos.pool.ntp.org iburst。iburst这个参数很重要它让 Chrony 在启动时快速发送一组包来完成初始同步正常情况下不需要去掉。我一般会根据自己的场景改写成相对固定的上游地址。用vim编辑vim /etc/chrony.conf把文件中 pool 相关的行替换为下面内容保留你原有注释# 使用国内 NTP 服务器作为时间源 server ntp.ntsc.ac.cn iburst server ntp.aliyun.com iburst server ntp.tencentyun.com iburst改完保存退出后重启一下服务让配置生效systemctl restart chronyd3.2 客户端同步验证chronyc 命令的使用细节服务跑起来以后最要紧的是验证它是不是真的同步上了。优先使用的命令是chronyc tracking输出里面有一个Leap status正常的话是Normal如果显示Not synchronised说明还没同步成功就需要继续排查。接着看Stratum那一项正常情况下如果连的是 Stratum 1 或 2 的上游那自己是 Stratum 2 或 3数字太大会导致精度变差。System time这一行会显示本地系统时钟相对于上游的偏差比如System time: 0.000005123 seconds fast of NTP time越小越好。再来看chronyc sources -v它会把当前配置的上游源状态列出来。重点关注^*开头的行这个星号表示该源是当前正在使用的同步源如果显示^?说明这个源不可达^-或^表示该源虽然可用但被算法判定为候选或备选只有^*是最优选。如果所有源都不是^*说明目前还没有成功完成同步。还有个chronyc sourcestats -v可以查看每个源的统计信息比如延迟、抖动、采样次数等可以用来判断上游质量。最后还建议装一个chronyc makestep的说明默认配置里有一段makestep 1 3含义是如果偏差超过 1 秒且是在系统启动后的前 3 次时钟更新中就直接“跳变”校准时间而不去做平滑微调。这个规则非常实用否则开机时如果偏差很大按照平滑调整可能要等很久才校回来。如果希望手工立即强制校准一次可以执行chronyc makestep执行完再用date命令确认一下当前时间通常就能看到时间瞬间被纠正。另外别忘了timedatectl也能看很多信息比如timedatectl status可以查看系统时钟、硬件时钟以及是否开启了 NTP 自动同步在 systemd 环境下如果NTP synchronized: yes就表示同步正常。4. 场景扩展Windows Server、ESXi 与 Android 设备的时间同步配置4.1 Windows Server 2012 及之后版本的时间同步配置要点很多人觉得只有 Linux 才需要配置 NTP实际上 Windows Server 同样需要尤其是在公司内网做域控或者跑 SQL Server 时。Windows Server 默认使用W32Time服务提供时间同步但如果你直接把它当域控微软官方其实建议只让根域控从外部可靠 NTP 源同步其他成员服务器和客户端再从域控同步时间形成层级结构。以 Windows Server 2012 R2 或更新版本为例想修改外部 NTP 源可以在管理员命令行里执行w32tm /config /manualpeerlist:ntp.ntsc.ac.cn,0x1 ntp.aliyun.com,0x1 /syncfromflags:manual /reliable:yes /update这里的0x1表示使用客户端模式进行同步。执行完以后重启一下时间服务net stop w32time net start w32time然后重新同步并查看状态w32tm /resync w32tm /query /status如果你发现w32tm /query /status里显示的源还是默认的time.windows.com可以再看看注册表确认配置是否生效。Windows 的时间服务有个特性默认轮询间隔比较长有时候手动触发 resync 会提示“数据无效”或“尚未同步”多等片刻再执行一次就好。还有一个隐藏很深的坑如果 Windows 的时间服务一直没有正常同步先确认一下 Windows Time 服务启动类型是“自动”不少优化脚本会把它禁掉如果禁用了需要改回sc config w32time start auto sc start w32time4.2 ESXi 8 设置 NTP虚拟化宿主机的时间校准ESXi 作为虚拟化平台它的时间准确性直接影响到上层所有虚拟机的“初始时间”。如果你宿主机时间就是歪的那虚拟机一开机就会拿到错误时间即便虚拟机里面再装 NTP 服务刚开始那几分钟的日志也可能是错的。在 ESXi 8 里设置 NTP 有两种常见途径一是通过 vSphere Client 图形界面二是通过命令行 esxcli 命令。图形界面路径为进入主机 - 配置 - 系统 - 时间和日期点击“编辑”按钮选择“使用 NTP 服务器”然后填入时间源地址比如ntp.ntsc.ac.cn、ntp.aliyun.comNTP 服务启动策略选择“与主机一起启动和停止”再点击保存。如果修改后没有立即生效可以手动执行“启动”操作把 NTP 服务跑起来。如果通过 SSH 登录到 ESXi 命令行也可以用下面的方式验证esxcli system time get esxcli network ntp set --serverntp.ntsc.ac.cn --serverntp.aliyun.com esxcli system ntp set --enabledtrue esxcli system ntp start不过我建议优先用图形界面毕竟 ESXi 的esxcli system ntp命令在一些版本里行为不完全一致容易踩到参数顺序的坑。还有一点需要特别注意如果 ESXi 所在宿主机硬件时钟本身就有问题或者 BIOS 里的 UTC 设置和实际时区不匹配虚拟机里的时间可能仍然会出现诡异偏差。这时候把虚拟机的VMware Tools时间同步选项打开配合客户机内部的时间服务一起工作效果会更好。4.3 Android 主动校时工具与日常设备时间同步移动端设备的时间同步需求虽然不如服务器那么苛刻但依然存在。Android 手机通常默认通过运营商网络自动同步基站时间但在部分网络环境下或者你拿的是没有插入 SIM 卡的设备、开发者板、电视盒子等特殊 Android 设备系统时间经常出现偏差。这时候就可以使用“安卓主动校时工具”这类应用它们本质上是一个轻量的 SNTP 客户端直接向指定 NTP 服务器发起时间请求并校准本机时间。常见的做法有安装一个简单的 SNTP 校时应用在设置里填入国内 NTP 服务器地址比如ntp.ntsc.ac.cn点击同步即可。部分工具需要 root 权限才能修改系统时间没有 root 的话普通应用权限通常只能通过setTime这种需要android.permission.SET_TIME系统权限的方式实现普通第三方应用拿不到。所以如果你发现校时工具提示“同步失败”或“需要系统权限”其实是很正常的。不需要太纠结这个场景毕竟这不是企业运维的刚需场景但偶尔也能救急——我见过有同事用手机做边缘计算节点没插卡、没连 SIM时间飘了几分钟最后就是靠一个 SNTP 工具手动校准撑过去的。5. 那些年踩过的时钟同步的坑排查思路与实战记录5.1 同步失败常见原因速查表时间同步看似简单实际排起错来一点不比应用故障轻松。下面先给出一份我整理的高频问题速查表方便以后出问题时直接对着查现象可能原因处理思路chronyc sources 显示^?上游服务器不可达网络被防火墙拦截检查本机到 NTP 服务器的 TCP/UDP 123 端口连通性Leap status 一直不是 Normal尚未完成首次同步或上游源质量太差等待时间更新或手工 makestep检查上游服务器配置同步一段时间后漂移又开始变大本地时钟晶体老化或硬件时间源异常更换 CMOS 电池检查是否启用了硬件时间戳功能Windows 时间始终无法同步W32Time 服务被禁用或源配置无效检查服务状态修改注册表源配置手动 resync虚拟机时间频繁跳变宿主机与客户机时间同步机制冲突调整 VMware Tools 时间同步策略保留一个同步源每次重启时间都回到过去硬件时钟没有正常回写或系统与硬件时钟时区不一致执行hwclock -w回写并配置timedatectl set-local-rtc5.2 防火墙与网络层面的大坑UDP 123 端口必须要通NTP 协议使用的是 UDP 123 端口这一点很多人会搞忘。你如果用telnet去测 NTP 服务器的 123 端口大概率显示连接失败那是正常的因为telnet走的是 TCP而 NTP 走的是 UDP。正确测试方式是用nc -u或者直接用chronyc看状态也可以抓包确认。在内网环境里如果服务器上有防火墙firewalld 或 iptables一定要放行 UDP 123 的出方向如果这台机器本身还要当时间服务器那入方向的 UDP 123 也得放行。CentOS/RHEL 上放行端口示例# 若使用 firewalld firewall-cmd --permanent --add-servicentp firewall-cmd --reload # 若使用 iptables老系统 iptables -A INPUT -p udp --dport 123 -j ACCEPT我遇到过不止一次这样的情况内网所有配置看着没问题chronyc sources也显示上游可达但就是一直不同步最后排查才发现是机房物理防火墙在中间拦了非标准端口的 UDP 包。所以在做了软件配置后一定也要确认网络路径上的安全策略。5.3 时间跳变与回跳罪魁祸首不只是 NTP 服务有时候你明明配置好了 Chrony服务器时间却在某个时刻忽然往前跳了几十秒甚至几分钟然后又自己跳回来。这种诡异现象往往不是同步配置的问题而是“多时间源打架”。比如你同时开启了 systemd-timesyncd 和 chronyd两个服务都在抢时间源就会产生频繁的跳变。解决办法是先停用不用的那个服务systemctl disable --now systemd-timesyncd systemctl enable --now chronyd还有一种情况在虚拟机平台上宿主机开启了“客户机时间同步”选项同时虚拟机内部的 NTP 客户端也在工作两者可能因为策略不同产生跳变。实际上、就安全而言云厂商默认的 KVM 虚拟化时间同步一般是通过半虚拟化时钟实现的客户机里面同时又跑 Chrony多数情况下不会冲突但遇到特定版本的内核或较老的操作系统时问题依然可能爆发。最好的做法是内部时间同步交给客户机自带的 NTP/Chrony宿主机层面的时间同步策略则视具体情况关掉。Windows 虚机尤其要注意这个我见过 Hyper-V 上 Windows 虚拟机时间频繁跳变就是因为宿主机时间源与客户机内置源不一致。如果硬件本身出了问题比如主板 RTC 电池没电了重启后系统时间回到 BIOS 出厂时间那你就别指望昂贵的 NTP 服务器能救命了——同步服务只能在系统运行期间校准系统时钟没办法凭空调出一个超出硬件能力的时间基准。遇到这种机器老老实实换 CMOS 电池。5.4 配置时间服务器的延伸内网自建 NTP 源减少公网依赖很多公司出于安全性和稳定性的考虑不愿意让所有服务器直接访问公网 NTP 服务器而是会在内网搭一台 NTP 服务器让其他机器都指向它。Chrony 实现这个配置非常简单。在计划作为内网时间服务器的机器上同样安装好 Chrony并在/etc/chrony.conf中增加允许网段访问的配置默认配置中其实已经有类似的一行被注释掉了# 允许内网 192.168.1.0/24 网段的机器访问本机时间服务 allow 192.168.1.0/24如果希望完全没关系地开放给所有内网客户端也可以写成allow all但建议严格限到具体网段。之后重启 Chronysystemctl restart chronyd在同一内网的其他机器上/etc/chrony.conf里只写上这台内网时间服务器的 IP 即可server 192.168.1.10 iburst这样设置的好处是所有客户端的时间源只有一个或少数几个内网延迟极低时间一致性更好同时减少对公网的依赖网络安全边界也更容易控制。公网服务器被墙、被限速、被 DNS 干扰这类问题内网源一概不用怕。5.5 时间同步地址使用的小经验不要贪多但也不要只留一个关于时间同步地址的数量我见过两种极端一种只配置一个上游服务器挂了就全盘失联另一种配了五六个反而让选择算法消耗更多资源。我的习惯是配置 2 到 3 个上游源既保障冗余又不过度。选源的时候尽量选不同提供方的比如一个国授时、一个阿里云、一个腾讯云防止同一家出现区域性问题时全军覆没。另一条经验是尽量别在配置文件里写仅对 IPv4 或 IPv6 有偏好的地址除非你的网络环境确定只支持其中一种否则最好确认 DNS 解析出来的地址本机可以正常访问。6. 写在最后的实操心得在工作里跟时间同步打交道这么些年最大的体会就是这个基础服务不复杂但必须认真对待。平时它安静地在后台工作你也感受不到它的存在可一旦时间歪了连锁反应能让你排查到凌晨三点。所以在做任何集群、任何日志系统、任何证书校验环境之前先花十分钟把时间同步配置好真的是一笔极划算的“保险”。最后分享一个个人小习惯我每布置完一台 Linux 服务器都会顺手执行一次chronyc tracking看一眼Leap status和System time那行后再离开。这个习惯看似多余但帮我挡掉过不少“配置完过两天又漂了”的尴尬问题。如果你接手的是别人的环境也建议先把当前的timedatectl和chronyc sources输出留个底方便后续对比。时间同步这个方向后续还能往 PTP、精密时间协议的高精度场景继续深入但先把 NTP 和 Chrony 这两个基础吃透你已经能应付绝大多数日常需求了。
返回列表