哎,最近项目是运行在内网环境下的,出现了由于时间不同步导致的bug。一般来讲,几台服务器的时间不一致,会带来很多问题,比如日志时间对不上、分布式服务出现异常,等等。项目上现在有三台服务器,其中只有一台可以临时访问外网,另外两台完全是内网。将来可能会彻底断网。为了解决时间不同步的问题,我整理了下面这个方案。
一、方案目标
让三台服务器的时间保持一致
- 有外网时,能同步公网的标准时间
- 无外网时,在内网里保持同步
二、服务器情况
角色 | IP 地址 | 说明 |
---|---|---|
S1 | 192.168.10.10 | 主服务器,可临时访问外网 |
S2 | 192.168.10.11 | 从服务器,纯内网 |
S3 | 192.168.10.12 | 从服务器,纯内网 |
我们会让 S1 做时间同步的“主机”,S2 和 S3 跟着它同步时间。
三、操作步骤
1. 所有服务器先做这些准备工作
# 关闭系统自带的时间同步服务
sudo systemctl stop systemd-timesyncd
sudo systemctl disable systemd-timesyncd
# 安装 chrony(我们用它来同步时间)
sudo apt update
sudo apt install -y chrony
# 设置时区为中国时间(可根据实际调整)
sudo timedatectl set-timezone Asia/Shanghai
# 同步系统时间到主板时钟
sudo hwclock --systohc
2. 配置主服务器(S1)
我们要让 S1 能自己从外网同步时间,然后把时间提供给内网其它服务器。
编辑配置文件:
sudo nano /etc/chrony/chrony.conf
替换成下面这些内容:
# 公网时间源
server cn.pool.ntp.org iburst
server ntp.aliyun.com iburst
server ntp.tencent.com iburst
# 允许内网访问这个时间服务(根据实际网段调整)
allow 192.168.10.0/24
# 没有外网时,S1 用自己的时间当源
local stratum 10
# 加快第一次同步速度
makestep 1.0 3
# 其他默认配置
driftfile /var/lib/chrony/chrony.drift
rtcsync
logdir /var/log/chrony
保存并退出后,重启服务:
sudo systemctl enable --now chrony
3. 配置内网客户端(S2 和 S3)
让 S2 和 S3 只和 S1 同步时间。
编辑配置文件:
sudo nano /etc/chrony/chrony.conf
内容如下:
# 指向主服务器 S1
server 192.168.10.10 iburst prefer
# 同步时间时快速修正
makestep 1.0 3
# 其他默认配置
driftfile /var/lib/chrony/chrony.drift
rtcsync
logdir /var/log/chrony
保存并退出后,重启服务:
sudo systemctl enable --now chrony
4. 验证同步是否成功
S1 上查看同步源:
chronyc sources -v
如果有外网,它应该会显示外面的时间源。
S2 / S3 上查看同步情况:
chronyc sources -v
你应该能看到 S1 的 IP 地址(192.168.10.10),前面有 ^* 标志,说明它被选作时间源。
还可以查看当前系统时间和参考源偏差:
chronyc tracking
四、原理简单说一下
chrony 是一个时间同步工具,比老的 ntpd 更快更稳定。
- 有外网时,S1 会去公网同步标准时间。
- 没外网时,S1 会用自己主板的时间来继续提供服务,虽然不是很精确,但几台机器之间不会偏太多。
- S2 和 S3 只信任 S1,不和外网同步。
这样三台机器的时间就始终保持一致。
五、优点和注意点
**优点:**有外网就用外网时间,没外网也能内网自给自足。所有服务器时间统一,不容易出错。
注意事项:
如果 S1 防火墙开启了,记得放开 UDP 的 123 端口(NTP 用的)。
bash sudo ufw allow from 192.168.10.0/24 to any port 123 proto udp
这个方案适合内网环境,有更高要求的话可以考虑接 GPS 授时设备。
六、总结
三台服务器,一台临时能访问外网,搭个 chrony 时间服务器。其它服务器跟着它同步。外网断了也不怕,时间不会乱。下次项目中若有类似需求,就可以按照这个方法部署,很快就能搞定。如果有更多服务器,也可以让它们都指向 S1,同样有效。