拓冰建站拓冰建站
首页 / 资讯中心 / 正文

NTP时间同步从入门到实战:配置、排障与自建时间服务器

1. 先说清楚NTP到底解决什么问题很多刚接触Linux的朋友一开始都会觉得时间同步是个“小事”。系统装上能用就行时间差个几分钟似乎也不影响什么。但等你真正维护过几台服务器、跑过数据库主从、看过分布式日志之后就会明白时间不同步的代价有多大。往小了说定时任务可能在错误的时间点触发日志时间错乱让你排查问题时对不上号往大了说Kerberos认证直接失败、数据库主从复制报错、监控告警时间线混乱甚至会因为证书校验时间不合法导致服务完全无法启动。NTPNetwork Time Protocol网络时间协议就是用来解决这个“小事”的标准化方案。它通过网络与时间服务器通信把本地系统时间校准到一个足够精确的水平。对于绝大多数业务场景来说NTP把时间误差控制在几十毫秒甚至几毫秒内已经完全够用。这篇文章我就带你把NTP从原理到落地完整走一遍涵盖安装、配置、校验、排障以及把它配成时间服务器向外提供同步服务的完整过程。适合看这篇文章的人主要是两类。一类是刚接手Linux服务器的运维新手需要用最快的时间把时间同步这个基础服务搞定另一类是已经在用NTP但经常遇到同步失败、时间跳变等问题的进阶使用者想系统搞明白配置文件里那些参数到底意味着什么。不管你是哪类这篇文章都值得读完。2. 原理搞明白配置才不会靠猜2.1 时间同步的核心机制层级与偏移NTP的工作原理听起来不复杂但在动手配置之前我还是建议你先理解两个核心概念时钟层级Stratum和时间偏移Offset。时钟层级描述的是时间服务器的“权威程度”。最顶层是Stratum 0通常是原子钟、GPS授时等硬件设备不直接对外提供服务。Stratum 1直接与Stratum 0相连属于一级时间服务器。Stratum 2与Stratum 1同步以此类推。层级数字越大时间经过的传递越多精度会依次降低但一般情况下从Stratum 2或Stratum 3获取时间已经足够精准。真正在同步过程中起关键作用的是时间偏移的计算。NTP客户端与服务器通信时会记录四个时间戳客户端发出请求的时间T1、服务器收到请求的时间T2、服务器发出响应的时间T3、客户端收到响应的时间T4。通过这四个时间戳可以计算出网络往返延迟Delay和时间偏移Offset。偏移量的计算本质上是把网络延迟折半后的差值修正所以即使网络存在波动也能得到相对准确的校准值。理解了这个机制你就明白为什么NTP不建议频繁大跨度调整时间因为所有的校准都基于网络传输时间的对称性假设。2.2 选ntpd还是chrony先别急着装在Linux生态里时间同步服务主要有两个实现传统的ntpd和较新的chrony。很多人一上来就按照老教程执行apt install ntp其实这个选择值得重新思考。ntpd是CentOS 6时代就广泛使用的老牌服务优点在于配置资料多、兼容性好、行为保守稳定。它的同步策略偏向“缓慢调整”让时间平滑趋近于服务器时间适合对时间连续性要求很高的场景。但它有个明显的短板如果本地时间与服务器时间差距过大通常超过1000秒ntpd会拒绝直接校准需要你先手动做一次大步调整才能进入正常的微调模式。chrony则是后起之秀设计上更现代。它同步速度快即使在网络不稳定的情况下也能较好工作而且对虚拟化环境和频繁挂起恢复的系统比如笔记本电脑支持更好。chrony既可以在几秒内完成初始同步又能在同步稳定后保持极低的时间漂移。在CentOS 8、Ubuntu 20.04及更新版本中chrony已经成为默认的时间同步工具。我给实际部署时的建议是新系统直接用chrony没必要再去折腾老旧的ntpd除非你维护的还是CentOS 6这类老版本系统或者有遗留脚本强依赖ntpd的某些命令行为否则chrony是目前更合适的选择。这篇文章会以ntpd为主做传统讲解因为网上大量教程还是基于ntpd同时也会补充chrony对应的配置方式方便你做对照。3. 安装和配置NTP服务的完整实操3.1 安装前的检查确认时区与时间状态安装之前先花两分钟检查当前系统的时间状态。这一步很多人会跳过但实际踩坑后发现很多“同步失败”的问题其实根源在于时区设置不对。查看当前系统时间状态执行date timedatectl重点看两部分一个是Universal timeUTC和Local time本地时间的差值是否符合你的时区预期另一个是System clock synchronized字段是否为yes。如果时区不对先把时区设置好。比如国内服务器设置上海时区timedatectl set-timezone Asia/Shanghai时区设置完成后再查看一次时间。如果本地时间与实际时间差距很大建议在启动NTP服务前先做一次手动校准设置系统时间到基本准确的状态。原因前面说过ntpd拒绝大跨度调整chrony虽然可以处理但初始差距越大首次同步的时间就越长。3.2 安装ntpd不同发行版的命令差异以主流发行版为例安装ntpd的命令如下。Debian / Ubuntu系apt update apt install -y ntpCentOS / RHEL 7及以前版本yum install -y ntpCentOS / RHEL 8及以后版本如果仍想使用ntpd不推荐但可行需要先安装并启用EPEL源dnf install -y epel-release dnf install -y ntp如果你决定使用系统默认的chronyCentOS 8 / Ubuntu 20.04安装方式也不同。Ubuntu上需要单独安装apt install -y chronyCentOS 8以上的系统一般已经预装chrony无需额外安装直接确认状态即可rpm -qa | grep chrony systemctl status chronyd安装完成后我喜欢马上确认一下版本方便后续排查问题时对照行为差异ntpd --version chronyd --version3.3 ntp.conf配置文件逐个参数解读ntpd的主配置文件是/etc/ntp.conf。这个文件看起来不长但每个参数都是有讲究的。我把一个生产环境可用的最小配置拆开来讲。配置示例# 上游时间服务器配置 server ntp.aliyun.com iburst minpoll 4 maxpoll 6 server ntp1.aliyun.com iburst minpoll 4 maxpoll 6 server cn.pool.ntp.org iburst minpoll 4 maxpoll 6 # 本机作为时间服务器时允许的客户端网段 restrict 127.0.0.1 restrict ::1 restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap # 默认拒绝所有客户端只保留时间查询能力 restrict default nomodify notrap nopeer # 漂移文件记录本地时钟与标准时间的频率偏差 driftfile /var/lib/ntp/drift先看server这行。iburst参数非常关键它表示在服务刚启动时如果无法立即与服务器建立通信会以2秒的间隔连续发送8个请求包而不是按正常轮询间隔等待。这大幅缩短了首次同步的启动时间。minpoll和maxpoll分别是最小和最大轮询间隔单位是2的幂次方秒。minpoll 4代表16秒maxpoll 6代表64秒。默认值是minpoll 664秒和maxpoll 101024秒对于常规场景保持默认或像我这样把最大间隔缩小一点都可以。不建议把轮询间隔设得太短频繁请求会白白占用上游服务器资源。restrict这行的作用可以理解为防火墙规则。restrict default定义了对所有来源IP的默认策略后面追加的参数是允许的动作。modify表示允许修改服务器配置trap表示允许接收控制消息peer表示允许建立对等关系。生产环境下外网客户端只需要查询时间所以把modify、trap、peer全部禁掉只保留查询能力。对于内网网段可以根据需要放开。nomodify表示不能修改配置notrap表示不能接收控制消息nopeer表示不能建立对等关系。注意restrict指令的默认行为是拒绝所有操作包括时间查询所以必须在后续行明确放行允许查询的网段。driftfile参数很多人容易忽略但它实际上很重要。driftfile记录的是本地时钟晶振与真实时间的频率偏差。第一次同步完成后ntpd会把这个偏差值写到文件里下次启动时先读取这个文件本地时钟就能更快进入稳定状态。如果文件不存在ntpd会创建它所以所在目录要保证ntp用户有写权限。3.4 启动服务并验证同步是否生效配置完成后启动服务并设置开机自启systemctl enable ntpd systemctl start ntpd如果是chrony对应的服务名是chronydsystemctl enable chronyd systemctl start chronyd启动完成后验证同步状态这一步容易出问题。我见过不少人直接执行ntpdate查看时间但ntpdate和ntpd是两套东西。ntpdate是一次性手动校准工具ntpd是持续运行的服务两者会抢占123端口不能同时使用。验证ntpd状态最常用的命令是ntpq -p这个命令输出的内容重点看四列。remote列是时间服务器地址st列是层级when列是距离上次查询经过的时间秒poll列是轮询间隔秒reach列是最近8次连接尝试的成功率以八进制表示。offset列则是当前与服务器的时间偏移量单位毫秒。当reach列的值为377八进制即二进制11111111时表示最近8次请求全部成功属于健康状态。offset绝对值越小越好一般稳定在几十毫秒以内就算正常。如果是chrony对应的查询命令是chronyc sources -v以及查看详细跟踪状态chronyc tracking另外通过timedatectl也能快速确认系统是否已进入同步状态timedatectl看System clock synchronized字段是否为yes以及NTP synchronized是否显示。如果systemd-timesyncd也在运行可能与ntpd冲突必要时需要先mask掉systemd-timesyncdsystemctl stop systemd-timesyncd systemctl mask systemd-timesyncd这个坑很隐蔽因为Ubuntu 18.04以上版本默认开启了systemd-timesyncd它与ntpd争抢123端口导致你装了ntpd却始终同步不上。4. 把你的Linux配置成NTP时间服务器4.1 为什么要自建时间服务器很多人觉得既然每台机器都能直接连公网同步时间为什么还要自建一个NTP服务器自建时间服务器最核心的用途是解决内网设备的同步问题。企业内部网络里通常有很多不允许访问公网的设备摄像头、门禁控制器、NAS存储、无外网权限的服务器等。这些设备需要统一、准确的时间但它们无法直接触达公网NTP服务器。另一种常见场景是内网有大量Linux服务器如果每台都直接连公网既浪费带宽也会在公网服务器侧形成大量无意义的请求。更关键的是某些安全要求高的内网环境根本不允许服务器访问外网只能在内网架设统一时间源。把一台能访问公网的Linux服务器配置成NTP服务器让其他内网机器都指向它是最标准也最稳妥的方案。这台服务器既从公网同步时间又对内网提供时间查询服务相当于扮演了时间源的“中间人”角色。4.2 配置内网时间服务器restrict网段开白名单将前面提到的ntp.conf配置稍作修改就可以从“同步客户端”升级为“时间服务器”。核心是两处调整。第一处server行保持与公网时间源同步确保本机时间准确。第二处restrict配置中明确放行内网网段。比如你的内网是192.168.10.0/24网段配置如下# 允许内网客户端查询时间 restrict 192.168.10.0 mask 255.255.255.0 nomodify notrap这里我特意没有加nopeer。如果你需要内网机器之间建立对等关系比如两台NTP服务器互为备份就需要去掉nopeer如果只是纯客户端/服务器模式加上nopeer可以防止内网机器尝试与这台服务器建立对等关系从而减少不必要的状态连接。配置完成后重启服务systemctl restart ntpd但此时还差关键一步防火墙放行UDP 123端口。NTP协议使用UDP协议端口号123这点和常见的TCP协议不同排障时容易漏掉。如果你的系统启用了firewalld或ufw需要添加对应规则。firewalld放行方式firewall-cmd --permanent --add-servicentp firewall-cmd --reloadufw放行方式ufw allow 123/udp4.3 客户端接入配置三种方式对比内网客户端接入时间服务器的配置方式取决于客户端的类型。这里我按三种场景分别说明。Linux客户端使用ntpd或chrony直接把server指向自建服务器server 192.168.10.5 iburstWindows客户端在控制面板的日期和时间设置里选择“Internet时间”标签页把服务器地址改为内网时间服务器的IP点击“立即更新”。这里需要说明的是Windows默认的时间同步间隔是一周如果你希望更频繁地同步需要修改注册表或使用w32tm命令。摄像头、NVR、门禁主机等嵌入式设备一般在设备的网络设置或系统设置里找到“时间同步”或“NTP服务器”选项填入内网NTP服务器地址保存后通常会立即触发一次同步请求。有些设备只允许填一个时间服务器这也无妨自建服务器本身已经足够稳定。关于客户端同步频度NTP协议本身会自动调整同步间隔通常从较短的间隔开始随着同步状态变好逐渐拉长轮询周期。客户端无需刻意设置频繁同步过于频繁的请求反而会对服务器造成不必要的压力。5. 禁止踩的坑与问题排查5.1 时间跳变为什么不要用ntpdate做日常同步我们常用的ntpdate命令作用是把本机时间直接强制设置为服务器时间是一种“跳变式”校准。而ntpd/chrony是“渐进式”校准通过微调每秒的时钟频率让时间平滑接近标准时间不会出现突然跳跃。跳变式校准对大部分场景影响不大但对日志连续性有要求的系统可能产生问题。比如一个Java应用用System.currentTimeMillis()生成了序列号时间突然往回跳几秒可能导致序列号倒挂引起业务逻辑异常。再比如采集系统时间跳变会导致监控曲线出现断层数据看起来像是丢了一段时间。所以我的建议是ntpdate只用于服务启动前的一次性校准日常持续同步交给ntpd或chrony完成。如果你的系统里已经安装了ntpd服务并且正在运行就不要再执行ntpdate命令两者抢同一个端口和同一份时间控制权轻则同步异常重则出现奇怪的时间跳动。5.2 防火墙和SELinux的“暗算”NTP相关的排障我遇到最多的问题可以归结为三类防火墙没放行、SELinux拦截、虚拟化时钟漂移。先说防火墙。在服务器本机上执行ntpq -p能看到连接尝试但offset一直显示为0或连接不上时优先检查防火墙。一种实用的排查方法是使用tcpdump抓包看UDP 123端口是否有双向流量tcpdump -i any udp port 123 -n如果只有请求包没有响应包基本可以确定是服务端防火墙丢弃了响应或者服务端没有正常监听。检查监听状态ss -unlp | grep 123再说SELinux。CentOS/RHEL系统默认开启SELinuxntpd服务受SELinux策略约束。默认策略下ntpd的某些行为会被拦截比如尝试绑定非标准端口、读取非默认路径的driftfile等。如果配置了自定义的driftfile路径且没有配套的SELinux策略服务会启动失败。排查SELinux拦截的最快办法是查看/var/log/audit/audit.log里是否有typeAVC的记录。如果是测试环境想快速确认问题是否与SELinux有关可以临时执行setenforce 0再重启ntpd观察是否恢复正常。但这只是排查手段修复后要记得恢复不能长期关闭SELinux。5.3 虚拟化环境下的时钟漂移KVM、ESXi、Hyper-V等虚拟化平台上的虚拟机时间同步问题的出现概率远高于物理机。原因在于虚拟机的时钟源依赖宿主机而宿主机本身的时钟精度受负载影响明显。如果宿主机负载波动大虚拟机里的时钟就会漂移得厉害。针对虚拟化场景我给几条实操建议。优先在宿主机层面做时间同步宿主机时间准确了虚拟机的时间漂移会小很多。虚拟机内部使用chrony而不是ntpdchrony对不稳定的时钟源容忍度更高校准速度也更快。使用KVM时可以尝试配置半虚拟化时钟virtio-rtc或禁用TSC时钟不稳定特性来减少漂移但这依赖具体虚拟化平台的版本需要查对应文档谨慎操作。如果你发现虚拟机在挂起、快照恢复后时间出现大幅偏差这是正常现象恢复运行后chrony会自动重新校准耐心等待几分钟即可。5.4 排查思路速查表最后把常见问题整理成一张速查表方便你定位问题时对照。症状可能原因快速诊断解决方案ntpq -p 显示连接超时防火墙未放行UDP 123ss -unlp检查监听tcpdump抓包防火墙放行123/udp系统时间与标准时间相差很大初始偏移过大ntpd拒绝校准date查看当前时间timedatectl确认同步状态先手动设置时间到接近标准值再启动服务同步几小时后时间又偏差很多本地时钟晶振偏频或虚拟化时钟漂移chronyc tracking查看系统时钟偏差检查宿主机时间同步确认driftfile正常启动了ntpd但timedatectl显示未同步systemd-timesyncd抢占123端口systemctl status systemd-timesyncdmask掉systemd-timesyncd服务器本机时间准确内网客户端同步不到服务端restrict配置未放行客户端网段服务端执行ntpq -c rv查看访问控制检查restrict规则增加对应网段放行重启后服务未启动未设置开机自启systemctl is-enabled ntpd执行systemctl enable ntpd6. 顺手补充chrony和ntpdate的关键用法6.1 chrony的常用命令与配置文件对比虽然前面已经穿插提到了chrony但这里我还是想完整对比一下两套命令免得你在切换时还要去翻文档。chrony配置文件是/etc/chrony.conf核心参数与ntp.conf非常接近但也有自己的语法特点。一个最小配置pool cn.pool.ntp.org iburst allow 192.168.10.0/24 local stratum 10这里的pool指令与ntp.conf里的server略有不同pool会自动从域名解析出多个服务器地址并在多个地址之间自动选择最优源。allow指令定义允许接入的客户端网段对应ntpd里的restrict。local stratum 10的作用是在无法访问上游时间源时本机仍然以第10层的身份宣告自己是可用时间源避免客户端彻底失去同步源。这个参数要慎用如果本机时间本身不准确又对外宣告自己是时间源会把错误时间传播出去。chrony常用命令有两个。chronyc sources -v是查看同步源的详细状态chonyc tracking是查看系统时钟的实时跟踪信息。tracking输出里最关键的一行是System time它表示系统当前时间与真实时间的误差单位为纳秒。误差合理范围内保持稳定即可不必追求绝对为0。6.2 ntpdate的正确使用姿势ntpdate没有彻底退出历史舞台它在某些一次性脚本里还是有用武之地。比如在集群初始化脚本里先强制校准一次时间再启动ntpd服务。正确用法# 停止ntpd服务如果运行中 systemctl stop ntpd # 执行一次性校准 ntpdate -u ntp.aliyun.com # 校准完成后启动ntpd systemctl start ntpd这里注意-u参数它的作用是使用非特权端口发送请求。如果客户端或服务端有防火墙限制默认的123端口可能被占用加上-u可以避免这个问题。在校准完成后要启动ntpd让后续同步保持持续状态。需要再次提醒的是ntpdate与ntpd不能同时运行否则会产生端口冲突导致时间同步异常。如果你使用的是chrony没有对应的“一次性校准”需求直接依靠chrony的快速同步能力即可它启动后几秒内就能把时间校准到百毫秒级别。7. 我的配置推荐与最后的几点体会7.1 生产环境推荐配置模板给出一个经过验证的生产环境配置模板你可以直接拿去用。Debian / Ubuntu系统使用ntpddriftfile /var/lib/ntp/drift leapfile /usr/share/zoneinfo/leap-seconds.list statistics loopstats peerstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable server ntp.aliyun.com iburst minpoll 4 maxpoll 6 server ntp1.aliyun.com iburst minpoll 4 maxpoll 6 server ntp2.aliyun.com iburst minpoll 4 maxpoll 6 restrict -4 default kod notrap nomodify nopeer noquery restrict -6 default kod notrap nomodify nopeer noquery restrict 127.0.0.1 restrict ::1 restrict 192.168.0.0 mask 255.255.0.0 nomodify notrap nopeerCentOS / RHEL 8以上使用chronypool ntp.aliyun.com iburst pool cn.pool.ntp.org iburst driftfile /var/lib/chrony/drift allow 192.168.0.0/16 local stratum 10这里补充一个关于restrict default中noquery参数的说法。在较老版本的ntpd中默认restrict没有加noquery意味着任何客户端都能向服务器发起查询请求可以获取到服务器当前的时间源列表、连接状态等信息。虽然这些信息不涉及敏感内容但出于最小化暴露的原则建议加上noquery。注意加了noquery不影响客户端正常的时间同步请求只是禁用了监控查询类指令。7.2 同步精度优化4个实用调整项如果你的场景对时间精度要求比较高比如做分布式数据库或者证券交易类系统可以关注以下几个调整项。第一个是选择更近的时间源。内网有时延优势公网服务器的地理位置越近网络抖动越小理论上同步精度越高。在国内使用阿里云NTP或腾讯云NTP通常比使用较远的公网池效果更好。第二个是增加上游服务器数量。建议配置3到5台上游服务器ntpd会通过算法选择最优服务器作为主同步源多台服务器之间还可以交叉验证避免单一时间源异常带来的影响。第三个是正确配置driftfile并保证其可写。driftfile能记录本地时钟的频率偏差服务重启后可以快速恢复到稳定状态。如果driftfile频繁报错需要检查文件权限。还有一点是尽量保持系统负载稳定。高负载导致网络响应延迟抖动增大误差也会随之变大。这听起来像是废话但确实是在物理机上影响NTP精度最直接的因素。7.3 给维护NTP的人几条实在建议文章最后分享几条我在实际维护过程中总结出来的体会不算系统知识但能帮你少走弯路。第一时间同步不是“配好了就完事”的一次性工作。建议在监控系统里加上时间偏移指标对每台服务器定期检查offset值偏移超过阈值就告警。值班时发现20台服务器时间集体偏移几百毫秒多半不是客户端的问题而是上游时间源出状况了。第二修改NTP配置后不要只重启服务就以为万事大吉用ntpq -p或chronyc sources观察十几分钟确认同步稳定了再离开。第三在集群或云环境里搭建新服务器时建议把NTP配置写进初始化脚本或镜像模板里省得每台机器都要手动配一遍也杜绝了“新机器忘了配时间同步”这种低级问题。第四遇到时间异常问题时先看宿主机如果是虚拟机再看服务端最后才查网络排查顺序能节省大量时间。这四条的背后其实都是一件事把时间同步当成基础服务体系的一部分来运营而不只是装个包。我当初第一次排查NTP问题的时候也是被“配了同步源但就是不生效”折腾了很久后来发现就是systemd-timesyncd在抢端口。希望你看了这篇文章能绕过这些坑把时间同步这件事一次做对。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门