内网集群时间同步实战:用Chrony搭建CentOS 7时间服务器(含多节点配置)

在金融交易、医疗记录、分布式数据库等对时间一致性要求极高的企业内网环境中,毫秒甚至微秒级的时间偏差都可能导致数据不一致、交易失败或日志错乱。我曾在一个大型数据分析集群项目中,就曾因为三台计算节点间存在近两秒的时间差,导致基于时间窗口的聚合查询结果完全失真,排查了整整一天才发现是时间同步的“锅”。自那以后,我深刻认识到,一个稳定、精确的内部时间同步架构,不是“锦上添花”,而是保障整个系统可靠运行的“地基”。

传统的ntpd服务在应对现代虚拟化环境、间歇性网络或需要快速收敛的场景时,往往力不从心。而Chrony,作为新一代的网络时间协议实现,以其更快的同步速度、更低的资源消耗和更好的网络适应性,已成为CentOS 7及更高版本系统的默认选择。本文将从一个实战架构师的角度,手把手带你在一台CentOS 7服务器上构建一个local stratum 10级别的内部时间权威源,并指导所有客户端节点通过iburst参数实现快速同步。我们将深入配置细节,涵盖访问控制、防火墙策略、层级验证以及企业级集群中那些容易被忽略的“坑”。

1. Chrony核心优势与内网时间架构设计

在封闭的内网环境中,我们无法直接访问互联网上的公共NTP服务器。因此,标准的做法是挑选一台或几台稳定性好、负载相对较低的服务器作为内部时间服务器,其他所有节点都向它(们)同步时间。这台内部服务器本身,可以配置从少数几台能出公网的机器同步(如果安全策略允许),或者就依靠其自身的硬件时钟,并通过local stratum指令声明为一个可信的参考源。

Chrony相比老旧的ntpd,有几个在企业内网场景下尤为突出的优势:

  • 极快的收敛速度iburst参数配合Chrony的算法,能在服务启动后的几次报文交换内就完成初步同步,这对于快速扩容的集群或重启后需要立即投入服务的节点至关重要。
  • 对网络波动不敏感:内网虽然稳定,但也不排除瞬间的流量高峰或交换机抖动。Chrony能更好地处理临时性的网络延迟和丢包,避免时间出现“跳跃”。
  • 更优的虚拟化支持:虚拟机内的时钟容易漂移,Chrony能更有效地跟踪和补偿这种由虚拟化引入的频率变化。
  • 灵活的服务端控制:通过allow指令可以精确控制哪些网段的客户端能来同步时间,结合防火墙,安全性更高。

一个典型的中小型内网时间架构如下所示:

[互联网公共NTP池] (可选,用于同步出口网关或主时间源)
        |
        v
[内网主时间服务器 (CentOS 7 + Chrony)] <-- local stratum 10
        | (allow 192.168.1.0/24)
        |
        v
[内网客户端集群 (数十至上百台节点)] <-- server <主服务器IP> iburst

在这个架构中,主时间服务器是单点吗?是的,但对于很多场景已经足够。如果对可用性要求极高,你可以部署两台或更多的时间服务器,并让它们互为peer,或者让客户端配置多个server条目实现简单的负载均衡和故障转移。

2. 时间服务器节点部署与深度配置

我们假设主时间服务器的内网IP是172.16.101.188,主机名设为ntp-master。首先,通过SSH登录到这台机器。

2.1 基础环境准备与Chrony安装

通常,CentOS 7 Minimal安装后可能没有预装Chrony。我们先进行安装和基础检查。

# 更新yum缓存,确保能获取到最新软件包信息
sudo yum makecache fast

# 安装chrony
sudo yum install -y chrony

# 安装后,查看关键文件是否就位
rpm -ql chrony | grep -E "(conf$|chronyd$|chronyc$)"

这条命令会列出Chrony的核心文件,你应该能看到/etc/chrony.conf(配置文件)、/usr/sbin/chronyd(守护进程)和/usr/bin/chronyc(控制客户端)。

注意:有些云厂商或定制化的CentOS镜像可能预装了Chrony。你可以通过systemctl status chronydrpm -q chrony来确认。

2.2 关键配置文件 /etc/chrony.conf 详解与定制

接下来是重头戏,配置/etc/chrony.conf。不要直接清空原文件,我们采用覆盖关键配置段的方式。先备份原配置:

sudo cp /etc/chrony.conf /etc/chrony.conf.bak.$(date +%Y%m%d)

现在,用你熟悉的编辑器(如vimnano)打开/etc/chrony.conf。我们将重点关注以下几个核心指令:

# 使用vim编辑配置文件
sudo vim /etc/chrony.conf

你需要修改或确认以下部分。请特别注意allowlocal stratum两行

# 注释掉或删除默认的公共NTP服务器行,因为我们走内网同步。
# server 0.centos.pool.ntp.org iburst
# server 1.centos.pool.ntp.org iburst
# server 2.centos.pool.ntp.org iburst
# server 3.centos.pool.ntp.org iburst

# 如果此服务器有出网权限,并需要从外部同步,可以保留或添加一到两个稳定的外部源。
# 例如阿里云NTP服务器(可选):
# server ntp1.aliyun.com iburst minpoll 4 maxpoll 10

# 关键配置:允许同步的客户端网段。这里允许整个172.16.101.0/24网段。
# 请务必根据你的实际内网规划修改!限制得越精确越安全。
allow 172.16.101.0/24

# 另一个关键配置:即使本机未能与上游源同步,也以本地时钟作为时间源提供服务。
# stratum 10 表示这是一个较低层级的、但可用的参考源。这确保了内网时间服务的连续性。
local stratum 10

# 系统时钟漂移记录文件。Chrony用它来持续补偿本机时钟的固有误差。
driftfile /var/lib/chrony/drift

# 时间调整策略:如果系统时钟偏差超过1秒,前3次更新将采用“步进”方式立即纠正。
# 之后采用“微调”方式平滑纠正。这避免了服务刚启动时因时间差过大导致的长时间等待。
makestep 1.0 3

# 启用内核级别的RTC(实时时钟)同步,将系统时间回写到硬件时钟。
rtcsync

# 日志目录
logdir /var/log/chrony

为了更清晰地对比关键参数的作用,我整理了下面这个表格:

配置指令示例值核心作用企业级配置要点
allowallow 172.16.101.0/24定义允许同步时间的客户端网络范围。安全基石。务必按需分配,禁止使用allow all。可配置多条。
local stratumlocal stratum 10当无外部同步源时,声明本地时钟为备用源。确保内网时间服务不中断。Stratum值通常设为10。
serverserver ntp1.aliyun.com iburst指定上游时间源。内网主服务器可选配。iburst加速初始同步。
makestepmakestep 1.0 3控制时间校正方式。1.0是触发步进的阈值(秒),3是步进模式生效的前几次更新。
rtcsyncrtcsync系统时间同步到硬件时钟。长期运行服务器的关键配置,减少重启后时间偏差。

2.3 防火墙与SELinux策略调整

CentOS 7默认的防火墙是firewalld,Chrony服务端需要开放NTP协议使用的UDP 123端口。

# 查看当前防火墙区域和规则
sudo firewall-cmd --list-all

# 永久开放NTP服务(firewalld预定义了ntp服务,对应udp 123端口)
sudo firewall-cmd --permanent --add-service=ntp
# 重新加载防火墙配置
sudo firewall-cmd --reload
# 再次确认ntp服务已在允许列表中
sudo firewall-cmd --list-services

如果系统启用了SELinux(默认是Enforcing模式),NTP端口通信通常没有问题,因为Chrony的RPM包已经设置了正确的SELinux上下文。但如果你遇到客户端无法同步的问题,可以临时将SELinux设为Permissive模式测试是否是SELinux导致的:

# 临时设置为宽容模式(重启后失效)
sudo setenforce 0
# 永久修改需要编辑 /etc/selinux/config,将SELINUX=enforcing改为SELINUX=permissive,然后重启。

提示:生产环境不建议长期关闭SELinux。如果确认是SELinux问题,应调查并添加正确的策略模块,而非直接禁用。

2.4 启动服务并验证服务端状态

配置完成后,启动Chrony守护进程并设置开机自启。

# 启动chronyd服务
sudo systemctl start chronyd
# 设置开机自动启动
sudo systemctl enable chronyd
# 检查服务运行状态,确保是active (running)
sudo systemctl status chronyd

现在,我们来验证服务端自身是否已准备好。使用chronyc命令行工具:

# 查看时间同步源状态。“^*”表示当前正在使用的同步源。
chronyc sources -v

对于配置了local stratum 10且未指定外部server的主节点,你可能会看到类似以下的输出,源标识为#,表示使用的是本地时钟:

MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#* LOCAL(0)                10   6   377    22    +0ns[   +0ns] +/-    0ns

这完全正常,它表明本机现在就是一个Stratum 10的时间源。同时,检查服务是否在监听正确的端口:

# 查看chronyd进程监听的端口,应包含UDP 123
sudo ss -tunlp | grep chronyd

输出中应该能看到*:123,表示正在所有接口上监听NTP请求。

3. 客户端节点配置与快速同步

现在,我们转向客户端节点(假设IP为172.16.101.189)。客户端的配置要简单得多,核心思想是指定主时间服务器并启用快速同步。

3.1 客户端基础安装与配置

同样,先确保Chrony已安装:

sudo yum install -y chrony

编辑客户端的/etc/chrony.conf文件:

sudo vim /etc/chrony.conf

将文件顶部的server配置指向我们的主服务器,并启用iburst。同样,注释掉或删除默认的公共服务器行。

# 指定内网主时间服务器,iburst参数用于快速初始同步
server 172.16.101.188 iburst

# 以下为客户端推荐保留的配置
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony

iburst参数是客户端快速同步的关键。它指示客户端在启动后,立即发送一组数据包(通常是4-8个)给服务器,从而在几秒内就能获得一个较好的时间估计,大大缩短了首次同步所需的时间。

3.2 启动客户端服务并验证同步状态

启动并启用客户端chronyd服务:

sudo systemctl start chronyd
sudo systemctl enable chronyd

稍等几秒钟,让iburst发挥作用,然后检查同步状态:

# 查看同步源详情
chronyc sources -v

理想的输出结果中,你应该看到主服务器的IP地址,并且在最左侧的MS列下有一个^*的标记。例如:

MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 172.16.101.188          11   6   377    45   -123us[-456us] +/-   12ms

这里^*表示“当前已同步的服务器”,Stratum是11,这正好比我们主服务器的local stratum 10高一层,符合NTP层级关系,说明同步链路是正常的。

你还可以使用tracking命令查看更详细的同步质量信息:

chronyc tracking

输出会包含参考时钟ID、系统时间偏移量(System time)、频率偏差(Frequency)等关键指标。一个健康同步的状态,其System time的偏移量应该在毫秒甚至微秒级别。

4. 高级运维、排错与集群化考量

基础的主从同步搭建完成后,我们还需要关注一些高级主题,以确保时间服务在企业环境中的长期稳定。

4.1 监控与日志分析

Chrony的日志默认位于/var/log/chrony/目录下。通过日志可以了解同步过程中的警告或错误。

# 查看最近的日志
sudo tail -f /var/log/chrony/chrony.log

对于监控,除了定期手动执行chronyc sources -vchronyc tracking,你可以将这些命令的输出集成到Zabbix、Prometheus等监控系统中。一个简单的思路是编写一个脚本,解析chronyc tracking中的Last offsetRMS offset,将其作为监控指标。

4.2 常见问题排错指南

即使配置正确,有时也会遇到同步失败的情况。下面是一个简单的排错流程:

  1. 检查网络连通性:在客户端使用pingnc(或telnet)测试到主服务器UDP 123端口的连通性。

    ping -c 3 172.16.101.188
    # 测试UDP 123端口(注意:某些nc版本参数不同)
    nc -uzv 172.16.101.188 123
    
  2. 检查防火墙规则:确认主服务器的防火墙确实放行了UDP 123端口。在客户端,也可以临时关闭防火墙测试。

  3. 检查服务端allow配置:确认客户端的IP地址确实在服务端/etc/chrony.confallow指令定义的网段内。

  4. 检查SELinux:如前所述,临时将SELinux设为Permissive模式测试。

  5. 查看详细错误信息:检查客户端和服务端的/var/log/messagesjournalctl -u chronyd,寻找与chrony相关的错误日志。

  6. 强制时间步进:如果客户端时间偏差非常大(比如几分钟以上),Chrony默认的平滑调整可能需要很久。此时可以手动触发步进调整:

    # 在客户端执行,立即步进同步时间
    sudo chronyc makestep
    

4.3 构建高可用时间源集群

对于核心生产环境,依赖单台时间服务器存在风险。我们可以构建一个简单的高可用方案:

  • 方案一:多服务器并列。部署2-3台时间服务器,都配置相同的local stratum 10allow规则。在所有客户端的/etc/chrony.conf中,配置多个server条目。

    server 172.16.101.188 iburst
    server 172.16.101.189 iburst
    server 172.16.101.190 iburst
    

    Chrony客户端会自动评估多个源的质量并选择最优的进行同步。

  • 方案二:主从+备援。设置一台主服务器(可能连接外部源),另一台作为备用。备用服务器配置主服务器为上游(server 172.16.101.188 iburst),并配置local stratum 11(注意层级要比主服务器高)。这样当主服务器失效时,备用服务器可以降级为本地源继续提供服务。客户端同时配置两台服务器。

  • 方案三:使用硬件时间源。对于金融、通信等对时间有极端要求的场景,可以考虑为时间服务器配备GPS接收器或原子钟作为硬件参考时钟,这将提供最高精度和可靠性的时间源。

4.4 时间一致性巡检脚本

最后,分享一个我经常在集群中使用的简易巡检脚本,它可以批量检查所有节点的时间同步状态和偏移量:

#!/bin/bash
# check_ntp_status.sh
# 将需要检查的客户端IP列表写入文件,如 host.list

SERVER_IP="172.16.101.188"
HOST_LIST="./host.list"

echo "=== Chrony集群时间同步状态巡检 ==="
echo "基准服务器: $SERVER_IP"
echo ""

for host in $(cat $HOST_LIST); do
    echo "--- 节点: $host ---"
    # 通过SSH执行命令,请确保已配置密钥免密登录
    ssh -o ConnectTimeout=5 $host "
        echo -n '服务状态: '; systemctl is-active chronyd;
        echo -n '同步源: '; chronyc sources -v 2>/dev/null | grep '^\^\*' | awk '{print \$2}';
        echo -n '时间偏移: '; chronyc tracking 2>/dev/null | grep 'System time' | awk '{print \$4, \$5}';
        echo -n '本地时间: '; date '+%Y-%m-%d %H:%M:%S';
    " 2>/dev/null || echo "连接或执行失败"
    echo ""
done

运行这个脚本,你可以快速掌握整个集群的时间同步健康状况。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐