免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Linux 内网 NTP 时间服务器搭建与 chrony 配置排障

Linux 内网 NTP 时间服务器搭建与 chrony 配置排障 1. 内网为什么会需要一台自建的 NTP 时间服务器凌晨两点被值班电话叫起来说集群里三台机器的日志时间戳差了十几分钟排障时根本拼不出完整的调用链——这种场景我遇到过不止一次。很多人对时间的印象停留在每台机器自己会跟手机一样自动校准但真实的数据中心里Linux 服务器的时间管理是一件需要专门规划的事。这篇内容就是讲清楚 NTP 时间服务器在 Linux 上怎么搭建、怎么配置、怎么验证、怎么排错从单台小机器到几百个节点的集群都适用。不管你是刚接触 Linux 的运维新人还是已经在管一批服务器但时间同步一直靠凑合的老手下面这些步骤基本都能直接照着抄。先把概念说清楚。NTPNetwork Time Protocol是一套用来在网络上传递标准时间的协议默认走 UDP 123 端口它做的事本质上是三件测量本机与上游的时间差、测量网络往返延迟、然后按算法把本机时钟拉到接近上游的水平。而NTP 时间服务器指的是在内网里承担分发时间这个角色的那台或那几台机器——它自己向上游对时然后对下层的服务器、交换机、数据库、业务容器提供对时服务。这套结构存在的意义很直接如果全网几十台机器各自去公网对时一旦出口网络抖动或者上游地址失效各机器会朝着不同方向漂移最后就是日志错位、证书校验失败、主从复制判断异常。1.1 时间漂移带来的真实麻烦大部分人对时间误差的容忍度是差不多就行但服务器环境里差不多的代价可能很贵。我先列几个我实际处理过的例子你对照自己的环境看看有没有踩过。第一类是日志与链路追踪失效。微服务架构下一次请求会横跨七八个服务如果 A 机器比 B 机器慢 8 秒你的日志平台按时间排序出来的调用关系就是反的排查故障时会被彻底带偏。这个问题在单体应用时代不明显一旦上了分布式就变成硬伤。第二类是认证与安全组件报错。很多基于票据的认证机制对时间窗口非常敏感比如 Kerberos 默认允许的时钟偏差是 5 分钟超过这个范围票据直接被判定无效表现就是用户莫名其妙登录不上、集群服务无法互访。TLS 证书校验也会受影响客户端时间比证书生效时间早就会报证书尚未生效。第三类是数据库与中间件的判断逻辑错乱。MySQL 主从复制在部分场景下依赖时间戳判断Kafka 的消息时间戳、Redis 的过期时间、分布式锁的租期计算全都默认各节点时钟基本一致。时间差一大会出现锁还没到期就被判定过期导致并发写冲突或者消息刚发出去就被判定为过期数据这种很难复现的问题。第四类是计费、审计、风控类业务直接出错。这类业务往往有明确的时间窗口要求时间不准意味着账算错了这种问题的修复成本远高于提前把时间同步做好。所以我的观点很明确内网时间同步不是锦上添花而是基础设施的第一层地基。而自己的 NTP 服务器的价值在于你有了一个可控的、稳定的、不依赖外网瞬时状态的内部时间源哪怕公网出口断了内网的对时链条也不会断。1.2 chrony 与 ntpd、systemd-timesyncd 怎么选Linux 上做时间同步现在主要有三个候选我把实际对比列出来方案典型发行版默认收敛速度虚拟化表现适用场景chronyRHEL 8/CentOS 8/SUSE快秒级到分钟级好专为不规律唤醒优化推荐首选服务端客户端都合适ntpdCentOS 7 及更早慢可能几十分钟一般虚拟机频繁唤醒时容易积累偏差老系统兼容systemd-timesyncdUbuntu 18.04 默认中等一般只做简单客户端功能很薄结论很清楚今天要在 Linux 上搭 NTP 时间服务器直接选 chrony。原因不是新而是它解决了一个老 ntpd 解决不好的问题——虚拟机和容器环境下系统不会一直连续运行可能被暂停、被迁移、被快照恢复ntpd 的算法假设时钟是连续走的一旦睡眠后唤醒它需要很长时间才能重新收敛甚至长期保持一个固定偏差chrony 在这方面做了针对性优化几分钟内就能把偏差压到毫秒级。还有一个现实原因chrony 同时具备服务端和客户端能力配置文件语法简洁命令行工具chronyc的信息密度比ntpq高排错时能少查很多文档。至于 systemd-timesyncd它只适合我这台机器随便对一下时就行的场景它不支持作为服务端为其他机器提供时间功能上是个阉割版所以搭建时间服务器时第一件事就是把 Ubuntu 上默认的它关掉——这个坑后面单独讲。1.3 Stratum 层级到底意味着什么理解Stratum层级这个概念对排查问题非常关键。NTP 是分层结构的Stratum 0是参考时钟本身比如原子钟、GPS 授时接收机它们不直接跑 NTP 协议。Stratum 1是直接连接 Stratum 0 的服务器属于国家级或大型机构的时间源。Stratum 2从 Stratum 1 取时间Stratum 3 从 Stratum 2 取依此类推最大到 1516 就表示不可用。你在内网自建的那台服务器正常情况下会显示为 Stratum 3 或 Stratum 4。这个数字大小本身不影响精度——决定精度的是网络延迟和上游质量不是层级数字。但层级有两个实际用途一是排查时看到 Stratum 突然变成 16说明同步丢失了二是配置里那个local stratum 10参数意思是当所有上游都不可达时本机把自己的层级设为 10 继续对外提供时间保证客户端不至于完全断供。这个参数用得好是保险用得不好是隐患后面会详细说。2. 动手前的准备环境盘点与上游时间源挑选直接上手改配置文件是最容易翻车的做法。我在正式动手前一定会做三件事确认系统版本和虚拟化平台、挑好上游时间源并测试连通性、清理掉会互相打架的服务。这三步花十分钟能省掉后面两小时的排查。2.1 系统版本、虚拟化平台与时钟源确认先看系统因为配置文件的路径在不同发行版上是不一样的这是新手最容易卡住的地方cat /etc/os-release uname -r两条命令分别看发行版和内核版本。记住这个差异RHEL/CentOS/Rocky/AlmaLinux 的配置在/etc/chrony.confDebian/Ubuntu 的配置在/etc/chrony/chrony.conf。别问我为什么不一样反正历史上就这么分的写文档和做自动化的时候必须区分。接着看虚拟化平台因为它决定了你的时钟源策略systemd-detect-virt cat /sys/devices/system/clocksource/clocksource0/available_clocksource cat /sys/devices/system/clocksource/clocksource0/current_clocksourcesystemd-detect-virt会告诉你是 kvm、vmware、microsoftHyper-V还是 none。后面两条是看可用的时钟源和当前时钟源。经验值是这样的KVM 环境下优先用kvm-clock它在半虚拟化下提供更稳定的时钟比默认的tsc或hpet抗漂移能力强得多。VMware 环境下装好open-vm-tools它带的时间同步功能会配合宿主机工作但注意不要和 chrony 抢着改时间一般建议让 chrony 主导vmware-toolbox-cmd 的时间同步关掉。物理机就用默认的tsc一般没问题高精度场景可以考虑acpi_pm以外的选项但绝大多数业务没必要折腾。提示容器内的机器不要试图在容器里跑 chrony 改时间容器共享宿主机内核时钟容器内改时间会失败或者只影响自己命名空间。正确做法是在宿主机上同步时间。顺便把时区也确认一下因为它和 NTP 是两件完全不同的事timedatectl这条命令的输出里有Local time、Universal time、RTC time、Time zone以及System clock synchronized和NTP service两个状态位。NTP 同步的永远是 UTC 时间时区只是显示层的换算。我见过有人因为服务器显示时间差 8 小时就以为 NTP 坏了其实是时区设成了 UTC 而他期待的是东八区。改时区用timedatectl set-timezone Asia/Shanghai和 NTP 一点关系都没有。2.2 上游时间源的选择与连通性自测自建的服务器自己也得有老师。上游时间源的选择原则就三条网络延迟低、长期稳定、最好不止一个。常见的做法是选两到四个上游组成一个小的候选池。选择时有几个考虑点如果这台机器在内网且能访问公网可以用公共时间源如果内网有隔离要求就用单位已有的上级时间服务器或者带授时功能的设备。配置多个上游的好处是 chrony 会自动做筛选剔除掉延迟大或者行为异常的那个避免单点。配置前一定要先测连通性别改完配置再发现根本不通。最直接的测试方式是用chronyc自带的探测或者临时用ntpdate -q老工具很多新系统已经不预装只是用来测# 临时安装测试工具CentOS 系 yum install -y ntpdate ntpdate -q 上游地址-q表示只查询不设置时间输出会告诉你是哪个层级、偏差多少秒。如果这个命令能出结果说明 UDP 123 的出方向是通的。这一点极其重要——很多人只记得在防火墙上放行入方向的 123 端口给客户端用却忘了服务器自己也要能出方向访问上游的 123 端口结果就是服务端起来了客户端也能连上它但它自己永远同步不上层级一直是 16。这个坑我踩过也见过太多人在群里问为什么我的服务器状态是初始化。2.3 端口、防火墙与冲突服务的清理防火墙这块原则是按需放行、限定来源# firewalldRHEL 系 firewall-cmd --permanent --add-servicentp firewall-cmd --reload firewall-cmd --list-services # 或者更精细地只放行某个网段 firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.10.0/24 port port123 protocoludp acceptUbuntu 上用 ufw 的话是ufw allow from 192.168.10.0/24 to any port 123 proto udp。如果用的是云主机还要记得在云平台的安全组里放行这一层很多人会漏掉表现为本机防火墙都关了还是不通。关于 SELinuxchrony 本身有现成的策略一般不需要额外处理用getenforce看下状态即可。如果确实遇到权限拒绝可以用ausearch -m avc -ts recent找具体的拒绝记录再针对性处理不要一上来就setenforce 0。最后是清理冲突服务这一步必须做# Ubuntu/Debian 上关掉 systemd-timesyncd systemctl disable --now systemd-timesyncd # 老系统上如果装了 ntpd 也要关掉 systemctl disable --now ntpd 2/dev/null || true为什么必须关因为chronyd 和 systemd-timesyncd 会争抢同一个时钟调整接口两个进程同时往两个方向拧时钟结果就是时间反复横跳你在chronyc tracking里会看到偏移量一直在正负之间跳怎么都收敛不了。这个现象很有迷惑性看起来像上游有问题实际上是本地两个服务在打架。3. 服务端配置chrony.conf 逐行拆解准备工作做完进入正题。这一章我会把配置文件拆到每一行讲清楚每个参数为什么这么写而不是给你一份复制粘贴就能用的配置了事——因为网络环境千差万别理解了参数才能自己调。3.1 安装与配置文件位置差异安装本身没难度# RHEL/CentOS/Rocky/AlmaLinux yum install -y chrony # 或者新版本 dnf install -y chrony # Debian/Ubuntu apt update apt install -y chrony装完之后先别急着改强烈建议先备份原配置cp /etc/chrony.conf /etc/chrony.conf.bak.$(date %F) # Ubuntu 上是 cp /etc/chrony/chrony.conf /etc/chrony/chrony.conf.bak.$(date %F)备份这个动作看起来像仪式感但当你改了一堆参数发现同步不上、想回滚的时候有个带日期的备份文件能救你一命。我个人的习惯是每次改动前都备份文件名带上日期和改动原因半年后回头看能快速回忆起来当时为什么改。配置文件的注释以#开头语法是指令 参数。下面这份是我在多个内网环境里沉淀下来的服务端配置模板逐行解释放在后面# 上游时间源多个以备冗余 server ntp1.example.internal iburst minpoll 4 maxpoll 6 server ntp2.example.internal iburst minpoll 4 maxpoll 6 # 公网备用内网完全隔离时删掉 server ntp.aliyun.com iburst # 记录晶振频率偏差加快重启后的收敛 driftfile /var/lib/chrony/drift # 允许对时的网段 allow 192.168.10.0/24 allow 10.20.0.0/16 # 前 3 次校准时偏差超过 1 秒直接步进 makestep 1.0 3 # 定期把系统时间写入硬件时钟 rtcsync # 上游全部不可用时以 stratum 10 继续对内提供服务 local stratum 10 # 关闭客户端功能只做服务端可选 # port 0 # 日志目录 logdir /var/log/chrony3.2 关键指令一行一行讲透server与pool的区别。server指定一个具体的主机名或 IPpool指定一个域名池chrony 会解析出多个地址并自动轮换。内网自建时间源通常用server更可控如果你的上游是公共的池化域名用pool更方便。但要注意一个坑不要在同一份配置里同时用很多个pool也不要既用pool又重复列出池里的地址否则同一台机器被走了两次chrony 的算法会误判。我一般控制上游总数在 3 到 4 个。iburst这个参数值得单独说。默认情况下 chrony 启动后要等一段时间才会发出第一个探测包然后逐步收敛整个过程可能好几分钟。加上iburst后启动瞬间它会以 2 秒间隔连发 8 个包让初次同步在几秒内完成。对于需要快速恢复的服务器这个参数几乎必加。minpoll和maxpoll是轮询间隔单位是指数实际间隔是 2 的 n 次方秒参数值实际间隔适用场景416 秒内网低延迟收敛快负载略高6默认最小值64 秒通用折中8256 秒稳定环境降低开销10默认最大值1024 秒约 17 分钟极稳定环境抗抖动要求不高内网环境网络抖动能压到亚毫秒级别所以我把 poll 区间设在 4 到 6让服务器能快速跟踪上游变化。如果是跨机房或者跨运营商的链路抖动量级大把 maxpoll 放小反而会让算法被噪声带偏这时候更合理的做法是保持默认的 6 到 10靠长时间平均来抵消抖动。driftfile记录的是本机晶振相对于标准频率的偏差。有了这个文件chronyd 重启后不用从头慢慢摸索能直接带着上次的频率修正量起步收敛时间能缩短一个量级。注意这个文件所在目录必须对 chronyd 进程可写否则启动会报错。makestep 1.0 3是两个参数阈值和次数。含义是在启动后的前 3 次时钟更新中如果偏差超过 1 秒就直接步进瞬间跳过去之后只做 slew缓慢平滑调整。为什么要区分因为瞬间跳变会导致应用侧感知到时间倒流或跳跃对数据库、消息队列这类有时间依赖的服务不友好而 slew 的调整速率非常慢chrony 默认大约每秒 0.5 毫秒也就是说 5 秒的偏差要慢慢纠将近 3 小时。所以合理的策略是开机初期允许步进快速把大偏差抹平运行期只允许平滑调整避免影响业务。注意如果一台机器已经运行很久、时间偏差又很大直接重启服务触发步进可能会影响业务。这种时候更稳的做法是先在维护窗口内用chronyc makestep手动步进一次或者用date -s手动设置后立刻启动 chronyd。allow是权限边界没写allow时 chrony 默认只响应本机查询。这里的网段一定要写成客户端实际的来源网段别图省事写0.0.0.0/0全放开那样一旦这台机器暴露在更大网络上就会变成一个公开的时间服务既浪费带宽也有安全风险。多个网段就写多行。local stratum 10是个双刃剑。它的作用是当所有上游都失联时本机仍然以一个较高的层级号继续对外服务这样客户端不会彻底失去时间源。但它有个前提——本机时钟本身得靠得住。如果这台机器的时钟漂得厉害你又开了这个选项那它就会把错误的时间分发给整个内网比断供更糟糕。所以我的做法是只在物理机上开或者在有硬件时间源、有冗余上游的情况下开纯虚拟机且没有可靠上游的宁愿让它报错也不要开。rtcsync让系统按固定周期把系统时间写回硬件时钟RTC。这样机器断电重启后BIOS 里的时间不会差得太离谱能给 chronyd 一个更好的起点。port 0这个指令是把 NTP 服务端口关掉让这台机器只做客户端不做服务端。如果你的机器不需要对别人提供服务加上它等于关掉了一个不必要的监听端口安全上更干净。3.3 启动、自启与首次同步的验收动作配置改完启动服务systemctl enable --now chronyd systemctl status chronyd看到active (running)只是第一步真正的验收要看同步状态。等 30 秒到 1 分钟让iburst完成初次探测然后执行chronyc sources -v输出里有一个关键列是行首的符号含义如下符号含义^*当前选中的同步源一切正常^可用的备选源被纳入候选^-被合并算法排除的源^?不可达或尚未完成探测^x被判定为错误时钟的源看到^*才叫成功。如果全是^?说明探测包没出去或者没回来回去检查上游地址和出方向防火墙。如果一直有源但选不出来看chronyc tracking里的层级和偏移。再执行chronyc tracking这是我排错时看得最多的一条命令chronyc tracking几个字段的解读Reference ID是当前同步的上游标识Stratum是你的层级System time是本机相对上游的偏移量这个是核心指标正常应该在毫秒级甚至微秒级Last offset是上一次更新的偏移RMS offset是历史偏移的均方根反映稳定性Frequency是晶振频率偏差单位 ppmUpdate interval是当前轮询间隔Leap status显示Normal就对了。最后确认监听状态ss -lunp | grep 123应该能看到 chronyd 监听在 UDP 123 上。到这里服务端就算搭好了。4. 客户端接入从单台手工到批量下发服务端好了接下来是让它真正产生价值——把客户端接上来。这一步在小规模环境里手工做没问题几十台以上就必须走自动化否则一定会漏机器。4.1 Linux 客户端的两种接法客户端有两套常见的实现chrony 和 systemd-timesyncd。如果你的机器上装的是 chrony配置和服务端几乎一样只是不需要allow、local这些服务端指令server 192.168.10.10 iburst driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync改完systemctl restart chronyd再用chronyc sources -v和chronyc tracking验收标准和服务端一样。如果机器上是 systemd-timesyncdUbuntu 默认就是配置走的是另一套# /etc/systemd/timesyncd.conf [Time] NTP192.168.10.10 FallbackNTP192.168.10.11然后执行systemctl restart systemd-timesyncd timedatectl看System clock synchronized: yes和NTP service: active两行。timesyncd 的缺点是信息不透明你只能看到同步了没有看不到偏差具体是多少。所以我个人的偏好是只要有条件客户端也统一换成 chrony理由是排错的时候能看到偏移量、能看到当前用的是哪个源省下来的时间远超安装成本。管理异构系统的痛苦一半来自不同实现的行为差异。这里还有个容易忽略的细节客户端和服务端必须在 UDP 123 上双向通畅。客户端出方向要能到服务端的 123服务端回包的路径也要通。云环境下如果客户端在另一个安全组记得两个方向都配。4.2 Windows 客户端接入实操内网里总会有几台 Windows 服务器它们同样可以对接 Linux 上的 chrony因为 NTP 是标准协议跨平台没问题。操作在管理员权限的命令行里执行w32tm /config /manualpeerlist:192.168.10.10,0x8 /syncfromflags:manual /update net stop w32time net start w32time w32tm /resync w32tm /query /status0x8这个标志位表示使用客户端模式对于普通客户端来说是最合适的。执行完w32tm /query /status后关注几项Source应该显示你的内网服务器地址Stratum应该是一个合理的数字Last Successful Sync Time应该是刚刚。Windows 的时间服务有个特点它默认的校时行为比较保守偏差很大时可能慢慢磨。如果遇到死活同步不上的情况可以先用w32tm /query /configuration确认配置生效了再用w32tm /stripchart /computer:192.168.10.10 /samples:5直接看和服务器的时间差。这条命令很好用能立刻判定是网络不通还是别的问题。4.3 大规模批量下发与硬件时钟落盘到了几十台以上的规模手工改配置就是灾难必须上自动化。用 Ansible 的话一份最小化的模板加一个任务就够# playbook: sync-ntp.yml - hosts: all become: yes vars: ntp_server: 192.168.10.10 tasks: - name: 部署 chrony 客户端配置 template: src: templates/chrony-client.conf.j2 dest: /etc/chrony.conf owner: root group: root mode: 0644 notify: restart chronyd - name: 确保 systemd-timesyncd 关闭 systemd: name: systemd-timesyncd state: stopped enabled: no ignore_errors: yes - name: 启动并设置开机自启 systemd: name: chronyd state: started enabled: yes handlers: - name: restart chronyd systemd: name: chronyd state: restarted模板文件里就一行有效的server {{ ntp_server }} iburst。这里有个实操要点Ubuntu 和 RHEL 的配置路径不同写模板时要按发行版分支处理否则会出现任务显示成功但配置根本没生效的情况。我一般用 Ansible 的when: ansible_os_family Debian做判断。另外别忘了批量验收。跑完自动化后可以用一条临时命令扫描所有机器当前偏移量for h in $(cat hosts.txt); do echo -n $h: ssh -o ConnectTimeout3 $h chronyc -c tracking | awk -F, {print \$5} donechronyc -c tracking是 CSV 格式输出第 5 个字段就是本机相对上游的偏移秒数这个格式在 chrony 3.2 及以上可用。把结果汇总一下超过阈值的机器单独处理比挨个登录快得多。关于硬件时钟落盘现代系统上rtcsync会周期性把系统时间写回 RTC一般不用手工干预。但如果你需要立即固化一次比如马上要断电维护可以执行hwclock --systohc。反过来的命令是hwclock --hctosys从硬件时钟读回系统这个一般在开机脚本里由系统自动完成手动执行要谨慎因为硬件时钟可能不准。5. 排查实录对不上时的定位顺序这一章是我最想写的部分因为前面所有配置都顺利的话你根本不会来搜排查。真正的价值在于出问题的时候知道先看哪里。5.1 先分清是没同步还是同步了但不准这是两个完全不同的问题处理路径也不一样所以第一步是分类。判断方法执行chronyc sources -v。如果行首全是^?那是根本没连上方向往网络和上游地址查。如果有^*说明同步关系建立了但chronyc tracking里的System time偏移量始终很大比如几百毫秒甚至几秒那是同步了但收敛不了方向往时钟源、虚拟化、参数配置查。我见过最典型的误判是机器显示^*已选中用户就认为没问题了结果业务侧的日志还是错乱。原因是他看的是同步状态没看偏移量。^*只代表我找到了可信的老师不代表我已经学会并且和老师完全一致。这个区别一定要记住。5.2 五类高频故障的现场处置故障一服务端起来了但自己层级一直是 16。排查顺序先看chronyc sources -v是不是全^?再测出方向连通性。八成是出方向 UDP 123 没放行。用ntpdate -q或者直接nc -u -z -v 上游IP 123测。另外注意 DNS 问题如果你在配置里写的是域名而服务器的 DNS 不好使解析失败也会导致全^?。这种情况直接换成 IP 最稳。故障二客户端连上了但偏移量一直在几百毫秒上下晃。这种情况多半是上游配置太多且质量参差。chrony 在多个源之间做筛选如果某个源网络抖动严重它会频繁重选导致估计值抖动。解决方法是精简候选源到 3 个以内并且优先选延迟低的。可以用chronyc sourcestats -v看每个源的统计信息重点关注Std Dev标准差这一列标准差大的源直接干掉。故障三虚拟机时间越跑越偏重启后好一阵又不行。虚拟机的时钟依赖宿主机如果宿主机负载高或者启用了 CPU 频率调节虚拟机时钟会跟着漂。处理方式有三层确认时钟源是kvm-clockKVM 环境确保open-vm-tools或对应的集成组件已安装且时间同步不会和 chrony 打架把 poll 间隔设小一点让 chrony 更频繁地纠偏。还有一个很多人不知道的点——虚拟机的 CPU 被长时间偷走steal time 高会导致时钟走慢这时候要在宿主机层面解决资源争抢光调 chrony 治不了根。故障四配置改完重启服务还是老样子。先确认你改的是当前生效的那个配置文件。Debian 系上是/etc/chrony/chrony.conf很多人在/etc/chrony.conf里改了半天实际读的是前者。确认方法systemctl cat chronyd看服务定义里引用了哪个路径或者ps -ef | grep chronyd看启动参数。这个坑我至少踩过两次每次都浪费半小时。故障五客户端和服务端时间差了十几分钟完全同步不上。时间偏差过大时chrony 出于安全考虑会拒绝同步防止被恶意源一下子把时钟带飞。这时候需要手动干预。可以先在客户端停掉服务手动把时间调到接近值再启动systemctl stop chronyd date -s $(date -d 2026-01-01 10:00:00) systemctl start chronyd或者用chronyc makestep强制步进一次。注意在生产环境上手动改时间要极其谨慎最好在维护窗口内做改完立刻确认业务侧没有异常。5.3 常见现象速查表把上面这些整理成一张表出问题的时候可以直接对着找现象最可能的原因处置动作全部源显示^?出方向 123 未放行 / DNS 失败测连通性配置改 IP源显示^*但偏移大上游质量差 / poll 设置不当精简上游调整 pollStratum 显示 16完全未同步回到全部^?的排查路径重启后短暂失步drift 文件丢失或不可写检查/var/lib/chrony/drift权限偏移量正负反复跳多个时间服务在打架关闭 timesyncd 或 ntpd虚拟机持续漂移时钟源不合适 / steal time 高切 kvm-clock查宿主机负载客户端偶尔全断上游单点故障增加冗余上游考虑local stratum配置改了不生效改错了配置文件路径用systemctl cat确认路径提示排查时养成先看状态、再看偏移、最后看日志的顺序。journalctl -u chronyd -n 100 --no-pager能看到 chronyd 的启动和运行日志很多参数错误会在启动时直接报出来比瞎猜快得多。6. 长期运维监控、限速与安全边界搭起来只是开始一套时间同步体系如果没人盯着早晚会悄悄出问题。这一章讲的是让它长期稳定运行该做的事。6.1 用一条命令做偏移量监控告警时间偏移是个缓慢变化的量出问题往往没有明显症状所以必须做监控。最简单的方式是写个脚本定时采集偏移量超过阈值就告警#!/bin/bash # check_ntp_offset.sh THRESHOLD0.1 # 单位秒超过 100 毫秒告警 OFFSET$(chronyc -c tracking 2/dev/null | awk -F, {print $5}) if [ -z $OFFSET ]; then echo CRITICAL: chronyc 无输出服务可能异常 exit 2 fi ABS$(awk -v o$OFFSET BEGIN{print (o0)?-o:o}) if awk -v a$ABS -v t$THRESHOLD BEGIN{exit !(at)}; then echo WARNING: 时间偏移 ${OFFSET} 秒超过阈值 ${THRESHOLD} 秒 exit 1 fi echo OK: 时间偏移 ${OFFSET} 秒 exit 0这个脚本丢给 Zabbix、Prometheus 的 textfile collector 或者任何能执行脚本的监控系统都行。阈值定多少合适我的经验是普通业务机器 100 毫秒足够对时间敏感的集群比如跑分布式数据库的可以压到 10 毫秒以内。不要定得太死比如 1 毫秒那样会天天告警最后没人看告警才是最大的风险。除了偏移量还值得监控两个指标chronyc tracking里的Stratum是否正常突然变大说明上游丢了以及chronyc activity里在线客户端的数量是否有异常下降说明可能有网络分区。6.2 ratelimit 与访问控制如果这台服务器同时对大量客户端提供服务要防止它被滥用。NTP 协议有个经典的安全问题是放大攻击——攻击者伪造源地址向服务器发一个很小的请求服务器回一个更大的响应把攻击流量导向受害者。虽然内网风险低但作为规范实践建议加上限速ratelimit interval 3 burst 8 leak 2含义是大致限制同一个客户端在短时间内的高频请求。具体数值要根据客户端规模调整客户端多的时候设太严会导致正常校时被拒所以上线前先观察chronyc serverstats的输出看实际请求频率。访问控制方面回到那个原则allow只写需要的网段。如果内网做了分区时间服务器应该部署在能被各区域访问到的位置而不是让防火墙开一堆穿墙规则。另外如果环境里有加密要求chrony 4.0 以上支持 NTSNetwork Time Security可以对时间同步链路做认证加密配置上需要在服务端和客户端共享密钥复杂度比普通配置高一截建议在确实有合规要求时再上。还有一个实用的加固点是密钥认证。传统的对称密钥方式在 chrony 里通过keyfile配置keyfile /etc/chrony.keys密钥文件里写10 SHA1 HEX:你的十六进制密钥然后服务端和客户端在server或allow相关配置里引用这个 key 编号。这种方式能防止客户端连到伪造的时间源但密钥管理本身是个负担规模大了不好维护所以实际中用得不多知道有这条路就行。6.3 迁移、冗余与几个我踩过的坑最后分享几个实际运维里攒下来的经验都是文档里不会写的。关于冗余。只搭一台时间服务器就是单点它一挂全网时间开始漂。规模稍大的环境建议至少两台客户端配置里把两台都写上chrony 会自动选优。但要注意两台服务端最好从不同的上游取时间或者至少错开一部分上游否则上游挂了它们一起挂冗余等于没有。关于迁移。换时间服务器地址是件麻烦事因为客户端配置散落在各处。我的做法是给时间服务器配一个内网域名比如ntp.corp.internal所有客户端都写域名而不是 IP。换机器时只改 DNS 解析客户端完全不用动。这一个习惯能省掉无数次批量改配置的痛苦。关于容器和 Kubernetes。节点上的时间同步和容器里的时间不是一回事。容器共享宿主机时钟所以只需要保证每个节点的时间准确。但要注意某些容器镜像里预装了 ntp 相关组件可能会尝试在容器内改时间这种要么删掉组件要么在启动脚本里禁掉。关于时间跳变。我再强调一次运行期的时钟跳变对业务是有害的。有一次一台机器重启后makestep触发了步进把时间往前跳了 2 秒结果基于时间戳做幂等判断的服务出现了重复处理。后来的做法是所有对时间跳变敏感的服务都要能在代码层面容忍一定范围的时间回退不能假设时间单调递增。这是架构层面的防御比调 NTP 参数更根本。关于验证周期。我给自己定的规矩是新机器上线时必须验证时间同步状态每季度抽查一批机器的偏移量每次网络或防火墙变更后重新确认 123 端口的双向连通性。这三条坚持下来时间相关的问题基本就绝迹了。说到底NTP 这套东西技术上不复杂真正难的是把它当成一件需要持续照看的基础设施而不是配一次就忘的开关。我在多个环境里反复部署过这套方案最后沉淀下来的核心就几句话服务端选 chrony、上游至少三个且要测通、allow严格限制网段、makestep控制好步进窗口、客户端统一实现以便排查、偏移量一定要有监控。把这几点做到位内网时间这件事就可以从你的待办清单里划掉了。
返回列表