ARTICLE DETAIL

资讯详情

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

深度解析Linux NTP时间同步:原理、配置与生产环境排障

深度解析Linux NTP时间同步:原理、配置与生产环境排障 你有没有遇到过这种情况凌晨两点被电话叫醒说线上系统登录不上了数据也对不齐。等你火急火燎地爬上服务器一看发现几台机器的时间差了七八分钟HTTPS证书验证失败、数据库事务时间戳乱套、定时任务全部错乱。最后定位到问题就是时间同步服务挂了。时间这个东西平时没人注意一出问题就是连锁反应。在Linux系统里NTPNetwork Time Protocol就是负责把服务器时间校准的核心方案。这篇文章我就结合自己多年的运维经验完整聊聊Linux下如何安装配置NTP、如何让客户端对接、以及那些真正部署时才会踩到的坑希望能帮你把时间这个“隐形地基”打牢。1. 先说清楚服务器时间不同步到底有多坑1.1 一个凌晨两点的故障现场有一年我值班接到告警说某个对账系统的数据大面积对不上。我登上去一看应用日志里两个服务之间的时间戳差了整整六分钟消息队列里的消息顺序看起来都是乱的数据库主从复制的延迟监控也报了异常。折腾了快一个小时最后用一条命令找到了元凶date -R三台应用服务器时间分别差了4分钟、6分钟、2分钟。当时的NTP服务早就停了而且停止时间已经超过一个月。系统的时钟漂移在虚拟机上尤其严重一个月能跑偏几分钟甚至十几分钟。那次故障之后我把部门所有服务器的NTP检查做成了巡检脚本并给所有内网机器统一对接了公司的NTP服务器。从那以后这类问题基本绝迹。1.2 时间同步失效会引发哪些连锁反应很多人觉得时间不对不就是日志难看点吗实际上远不止如此。我把实际工作中遇到的影响列出来你感受一下受影响对象典型故障表现严重程度HTTPS/TLS 证书校验证书有效期判断失败浏览器或服务端直接拒绝连接高Kerberos 认证票据有效期校验失败域认证批量报错默认容差只有5分钟高分布式数据库/消息队列事务时间戳乱序、消息先后关系错乱、主从同步异常高定时任务cron任务错峰执行、重复执行、甚至不执行中日志审计与排障多台机器日志时间线对不上排障根本无从下手中监控告警监控数据时间轴错乱误报漏报频发中音视频/安防设备海康等摄像机录像时间错乱回放取证困难中如果你的环境里有海康威视之类的IP摄像机它们的录像时间也是依赖NTP做对时的。摄像头时间错乱回放关键时间点的录像时你根本不知道哪段对应哪个时刻这在安防场景里是非常要命的问题。1.3 NTP是怎么把时间校准的NTP的核心思路并不复杂网络里有多个“时间源”时间源本身也有层级划分专业说法叫 stratum阶层。第0层是最顶层的原子钟、GPS时钟等直接对外提供时间。第1层直接连接第0层第2层连接第1层以此类推。数字越小时间越接近权威源。客户端会向多个时间源发起请求NTP算法不光是简单取平均值它会把网络延迟delay、抖动jitter等因素考虑进去综合判断出一个最可信的时间值。同步过程是渐进式的。正常情况下NTP守护进程会小步微调本地时钟不会让时间一下跳变太多避免对应用产生冲击。你可以把NTP理解成你在一间大教室里向几个你觉得比较靠谱的同学问现在几点然后你综合他们的答案判断出最可能准确的时间并主动调自己的表。这么一说应该很好理解。2. 搭建一个可用的NTP服务器2.1 环境准备和安装方式我先明确一下本文的主环境。目前企业里存量较多的系统有两类一类是CentOS 7、AlmaLinux 8/9、Rocky Linux 8/9 这类 RHEL 系另一类就是 Ubuntu 20.04/22.04、Debian 11/12 等 Debian 系。我下面以 RHEL 系为主来演示Ubuntu 的安装命令会一并给出差别不大。先检查系统里是否已经装了NTPrpm -qa | grep ntp # 或者 dpkg -l | grep ntpRHEL 系直接用 yum 安装yum install -y ntpUbuntu/Debian 系用 apt 安装apt update apt install -y ntp安装完成后确认一下路径which ntpd which ntpdate which ntpq这三个命令对应 NTP 的守护进程、手动同步命令、查询状态命令后面全都会用到。2.2 手写一份生产可用的 ntp.confNTP 的核心配置文件是/etc/ntp.conf。安装完成后的默认配置其实已经能跑但要用于生产环境我建议像我一样老老实实重写一遍把每个关键参数都搞清楚。先备份原始文件cp /etc/ntp.conf /etc/ntp.conf.bak然后编辑配置。下面是一份我常用的基础配置适用于内网NTP服务器# 用于记录时钟漂移率ntpd 会周期性把漂移值写入这个文件 driftfile /var/lib/ntp/drift # 默认拒绝所有客户端的修改、通知、查询 restrict default nomodify notrap nopeer noquery # 允许本机自由使用完整 NTP 服务 restrict 127.0.0.1 restrict ::1 # 允许内网网段访问本NTP服务器 restrict 192.168.10.0 mask 255.255.255.0 nomodify notrap # 配置上级时间源 server ntp.aliyun.com iburst server cn.pool.ntp.org iburst server ntp.ntsc.ac.cn iburst # 当所有外部时间源都不可用时使用本地时钟兜底 server 127.127.1.0 fudge 127.127.1.0 stratum 10这是一份非常典型的配置。逐行解释几个关键点driftfile很关键它用来记录本地时钟与真实时间的偏差率。ntpd 启动后会读取它重启后能快速恢复到之前的校准状态不用重新从头测量。restrict是访问控制。nomodify表示禁止客户端修改服务器时间配置notrap禁止远程登录nopeer禁止建立对等关系noquery禁止查询状态。默认拒绝、指定网段放行是最稳妥的做法。server一行配置一个上级时间源。iburst参数非常推荐加上它的作用是如果服务器刚启动会在一开始连续发送多个请求包快速完成初同步而不需要等漫长的 64 秒轮询周期。127.127.1.0是本地时钟的“虚拟时间源”fudge是给它指定一个伪层级。这行配置的实际意义就是兜底当所有互联网时间源都连不通时这台服务器至少还能给内网其他机器提供一个相对稳定的时间参考。注意stratum 10要设置得比较大这样正常情况下客户端会优先选择你配置的权威上级源而不是本地时钟。2.3 启动服务、设置开机自启并完成首次同步配置文件写好后启动服务并加入开机自启systemctl start ntpd systemctl enable ntpd systemctl status ntpdRHEL 系里重启 ntpdsystemctl restart ntpdUbuntu 里也可能是systemctl restart ntp看准你自己的服务名。刚启动时时间不会瞬间同步完成。你可以先手动强制做一次同步这样比干等快得多。手动同步的步骤是systemctl stop ntpd ntpdate -u 0.cn.pool.ntp.org systemctl start ntpd为什么要先停掉 ntpd因为 ntpd 和 ntpdate 默认都监听 123 UDP 端口同时跑会报socket in use。这个坑我在后面专门讲。过几分钟后用ntpq -p查看同步状态ntpq -p我随便给一个健康状态的输出样例remote refid st t when poll reach delay offset jitter *ntp.aliyun.com 193.123.178.131 2 u 32 64 377 30.821 1.251 3.245 cn.pool.ntp.org 218.75.204.146 3 u 16 64 377 26.330 -0.923 2.156最左边第一列如果显示的是*表示当前正在使用这个时间源作为同步参考显示表示这个源可用可以作为候选。reach显示为377八进制代表最近 8 次轮询全部成功这也是一个非常重要的健康指标。offset表示本地时间与时间源的偏差单位是毫秒数字越小越好一般个位数毫秒都算正常。3. 客户端接入让所有机器时间对齐3.1 先用 ntpdate 做一次临时同步当你只想临时把某台机器的时间校准一次不想装守护进程长期同步可以直接用 ntpdatentpdate -u 192.168.10.10-u参数意思是使用非特权端口发送请求可以绕过一些防火墙策略实测在多数场景下更不容易被拦截。我需要特别提醒ntpdate是直接把本地时间“跳变”到目标时间。如果时间差很小比如几百毫秒影响不大但如果你一台机器因为故障停了很久时间偏了几个小时那一跳变就会出问题正在运行的业务可能因为时间突然倒流而出现异常数据库日志尤其明显。所以生产环境里我一般只在确认服务停止、业务影响可控时才手动使用 ntpdate。3.2 客户端持续同步的标准配置客户端不建议只做一次性同步正确做法是让每个客户端配置成 NTP 服务的对端持续保持时间一致。客户端的配置更简单。比如内网有台 NTP 服务器IP 是192.168.10.10那么客户端的/etc/ntp.conf可以这么写driftfile /var/lib/ntp/drift restrict default nomodify notrap nopeer noquery restrict 127.0.0.1 restrict ::1 server 192.168.10.10 iburst然后启动服务systemctl start ntpd systemctl enable ntpd如果客户端服务器是 Windows也有对应的配置方式在管理员命令行里执行w32tm /config /manualpeerlist:192.168.10.10 /syncfromflags:manual /reliable:yes /update net stop w32time net start w32time w32tm /resyncWindows 自带的 W32Time 服务就是 NTP 的一个实现很多老系统比如 Windows Server 2008 也是这种方式开启 NTP 同步。Linux 客户端和 Windows 服务器之间互相对时只要走的标准 NTP 协议一般都能正常互通。3.3 别忘记时区和硬件时钟搞定NTP之后还有两个极容易被忽略的点时区和硬件时钟。时区不对的话即使UTC时间准了你date看到的本地时间也可能是错的。统一设置时区用一条命令timedatectl set-timezone Asia/Shanghai然后确认状态timedatectl status输出里重点看Local time、Universal time、RTC time这三项。硬件时钟也需要处理。服务器存在两个时钟一个是系统内核维护的软件时钟另一个是主板上电池供电的硬件时钟RTC。ntpd 同步的是软件时钟但系统重启时会读取硬件时钟来初始化软件时钟。如果硬件时钟和软件时钟偏差很大重启后时间又会跳回去。所以我每配置完一台服务器都会做一次硬件时钟校准hwclock --systohc这条命令是把当前系统时间写入硬件时钟。反过来如果确认硬件时钟是准的可以用hwclock --hctosys把硬件时间写回系统。RHEL 系里默认硬件时钟使用UTCWindows 默认使用本地时间如果你是在同一台机器上装双系统这块配置尤其要小心否则两个系统之间的时间会一直互相打架。4. 踩坑实录NTP部署中的常见问题4.1 socket in use 到底是谁占用了端口新手刚实操最容易遇到的报错ntpdate[12345]: sendto(192.168.10.10): Network is unreachable ntpdate[12345]: sendto(192.168.10.10): Connection refused或者是ntpq: read: Connection refused还有一种更经典的ntpdate[12345]: the NTP socket is in use, exitingthe NTP socket is in use的根因就是ntpd 服务还开着占用了 123/UDP 端口你又去执行 ntpdate自然抢不到端口。解决思路也很简单systemctl stop ntpd ntpdate -u 192.168.10.10 systemctl start ntpd如果想省事配置好 ntpdate 后直接用systemctl restart ntpd等它慢慢对齐也行只是速度不如手动同步快。4.2 服务器同步不上的头号原因时间源连不通这是最常见的同步失败原因没有之一。排查步骤我建议按顺序来第一步测试网络连通性。NTP走的是 UDP 123 端口ping 通不代表 UDP 通但可以先看基本链路ping -c 4 ntp.aliyun.com第二步检查 UDP 123 是否通。用nc测 UDP 端口比较直观nc -uvz ntp.aliyun.com 123如果返回succeeded说明端口可达。没有nc的话可以用telnet但 UDP 的 telnet 测试结果不如 nc 直观。第三步看防火墙。RHEL 系常见的是 firewalld放行 NTP 用firewall-cmd --permanent --add-servicentp firewall-cmd --reloadUbuntu 的 ufw 则用ufw allow 123/udp第四步用 tcpdump 抓包确认有没有响应。这条是终极大法能直接看到 NTP 请求和回应tcpdump -i eth0 udp port 123 -n如果在网络上确实有 NTP 请求发出却等不到任何回包那基本就可以判定是中间链路的问题要么是防火墙拦了要么是上层路由做了 NAT 策略。4.3 虚拟机环境时间漂移特别快怎么办虚拟机环境下时间漂移快是常态我见过最夸张的一台 KVM 虚拟机一个月时间跑偏了十几分钟。原因在于虚拟机的软件时钟依赖宿主机提供的虚拟时钟信号宿主机的调度、负载波动、暂停恢复都会造成时钟不稳定漂移率比物理机高得多。针对虚拟机我有几个建议第一宿主机自身的时间必须稳定。宿主机时间都不准虚拟机再怎么同步也是白搭。物理机尽量配置 GPS、北斗授时设备或者至少对齐到靠前的公共时间源。第二给虚拟机装好对应的增强工具。VMware 虚拟机装 open-vm-toolsKVM/QEMU 虚拟机装 qemu-guest-agent这些工具会配合虚拟化层做时间补偿能显著减少漂移。第三修改内核时钟源。某些情况下把系统时钟源强制指定为 TSC 会有改善。可以在/etc/default/grub的GRUB_CMDLINE_LINUX里追加clocksourcetsc notsc然后重新生成 grub 配置grub2-mkconfig -o /boot/grub2/grub.cfg需要注意不是所有硬件都适合 TSC旧 CPU 上 TSC 可能不稳定所以这个操作建议先在测试机验证。4.4 用 ntpq -p 判断同步是否健康部署完之后不要只是看一眼状态是 active 就完事了。多花一分钟用ntpq -p读懂输出能帮你提前排除掉很多隐患。我整理了一个速查表字段含义健康标准remote时间源地址对应你配置的源refid上游参考ID应为权威源或上游IPststratum 层级数值越小越权威t连接类型u 表示单播when距上次请求秒数小于 poll 即可poll轮询间隔秒数默认 64 或 1024reach最近8次探测的命中率377 最理想delay网络往返延迟越小越好国内源一般几十毫秒offset本地时间与源的偏差个位数毫秒理想超过100ms要警惕jitter时间偏差的抖动越小越稳定特别说一下reach它是八进制显示。如果你看到的是1、3、7、17这种说明刚刚加入轮询不久还在积累历史数据如果长时间都是0说明请求基本全失败了。稳定状态下reach377是最健康的表现。另外ntpq -p输出的第一列可能是*、、-、空格*表示当前选中的同步源表示候选源可以被选中-表示被排除的源空格表示该源还没有被充分评估看到*存在并且 offset 不大说明同步状态是健康的。5. 进阶心得时间同步不只是装个软件5.1 内网时间同步架构怎么设计小规模环境比如只有三五台服务器全部直连公网时间源是没问题的。但规模一上来比如有几十上百台机器就不建议所有机器都直连公网了。原因有几个公网时间源会限制单个IP的请求频率机器多了容易被限流。大量客户端直连公网一旦外网链路抖动你会看到全网服务器时间同步状态都不健康排查面太广。在某些隔离内网环境里服务器根本出不了外网必须内网自建时间服务器。我建议的标准架构是这样的第一层是外部权威时间源可以是公网的ntp.aliyun.com、cn.pool.ntp.org也可以是企业自建的 GPS/北斗授时设备。第二层是内网 NTP 服务器通常一台或两台这台机器可以访问外网时间源同时监听内网网卡对外提供时间服务。配置里注意restrict要明确放行内网网段比如我前面写的restrict 192.168.10.0 mask 255.255.255.0 nomodify notrap。第三层才是大量的业务服务器和终端设备它们只向内网 NTP 服务器同步不接触外网。这样架构清晰故障面小安全策略也好做。如果公司规模再大、对时间精度要求更高还可以做冗余搭两台内网NTP服务器客户端同时指向这两个源server 192.168.10.10 iburst和server 192.168.10.11 iburst各写一行。NTP客户端会自动挑选最合适的源来同步一台挂了另一台顶上。5.2 多时间源冗余与选源细节配置多个时间源时有几个细节值得注意时间源不要配太多三四条比较合适。配太多反而会让客户端花费大量时间在测量候选源上。更重要的是不要全部配置同一个上游服务商的源那样等于没有冗余。我的习惯是至少保证两个不同服务商的时间源再留一条本地时钟兜底。如果你内网里已经有基于 GPS 或北斗的授时设备优先级应该是最高的。在server配置里NTP 没有严格的优先级顺序概念它靠的是 stratum 层级和算法筛选。所以fudge 127.127.1.0 stratum 10这行才会设定一个很大的层级目的就是让本地时钟优先级最低只有全部外部源都挂了它才会被选中。5.3 新系统要不要换成 chrony聊到时间同步很多用惯了 CentOS 7 的朋友会有疑问现在新的操作系统版本好像默认装的是 chrony不是 ntpd那到底用哪个我用下来的感受是这样的chrony 是现代操作系统的时间同步守护进程RHEL 8/9、Ubuntu 20.04 以上的版本默认都使用 chrony。它在网络抖动大、系统频繁挂起恢复重新校准等场景下表现明显更好启动后的初同步速度也更快。如果你是在新版本系统上从零搭建我建议直接用 chrony不用再特意安装传统 NTP 套件。chrony 的配置文件是/etc/chrony.conf说白了也是配置server和allow核心思路和 NTP 完全一样只是命令变成了chronyc sources -v。日常语法不复杂网上资料也多。但如果是老系统存量环境或者客户端设备只支持 NTP 协议、不支持 chrony 的同步协议交互那沿用 ntpd 也没有问题。对我来说新机房、新系统用 chrony旧机房、存量系统保持不变是最稳妥的策略。5.4 分享几个看家小技巧最后分享几个我自己一直在用的小技巧算是长期运维攒下来的习惯。定期巡检脚本不能少。不要以为配好同步就高枕无忧。我写过一段最简单的巡检每天检查一次所有服务器的时间偏移量超过一定阈值就告警逻辑很简单#!/bin/bash TIMEOFFSET$(ntpq -p | awk NR2 $1* {print $9}) if [ -n $TIMEOFFSET ]; then ABSOFFSET$(echo $TIMEOFFSET | awk {print ($10)?-$1:$1}) if [ $(echo $ABSOFFSET 100 | bc) -eq 1 ]; then echo NTP offset over threshold: ${TIMEOFFSET}ms fi fi用 Ansible 批量下发 NTP 配置也很方便。给所有机器推送一份写好时间源的/etc/ntp.conf然后执行systemctl restart ntpd几分钟内全机房的时间就整整齐齐了比一台台登上去手工改高效得多。还有一个小提醒内核时钟跳变对大业务的影响常被忽略。默认情况下 ntpd 采用渐进微调但如果时间偏差超过了一个阈值它会直接跳变这个阈值在 Linux 下默认是128毫秒。某些实时性很敏感的应用即使几十毫秒的跳变也可能造成异常。如果你的业务对时间特别敏感可以考虑通过内核参数sysctl kernel.timer_slack_ns等去调整但更推荐的做法是让系统始终保持健康同步避免出现大幅偏差后的强制跳变。再说一个排查小技巧当你怀疑某台机器时间不准但 NTP 状态又显示正常时不要只看date一定要看timedatectl里System clock synchronized: yes和NTP synchronized: yes这两个字段两个都显示正常的机器才能认为时间确实处于受控状态。以上这些都是我在一次次凌晨故障和日常巡检里攒出来的实操经验。时间同步看起来是一件小事但真要做好、做稳值得投入的精力并不少。多一层配置多一次巡检可能就避免了一次深夜被叫醒的翻车事故。
返回列表