NTP内网时间同步方案chronyc

sheng-hu-lnQ_qxiD5bA-unsplash.jpg

需求

内网(断网、无互联网)的几台服务器老是时间提前,一开始延时几秒后面慢慢变的几分钟,影响数据。

找管理员也是效果不理想,管理员那边是通过交换机的时间,然后母鸡通过vmtools强制推送到客户端上,交换机的时间也是人为设定的,也出现时间提前的情况。

内网内无NTP服务器

架构

  • 光闸(网闸)摆渡互联网时间接口(垃圾光闸不支持TCP、UDP转发)
  • 内网通脚本定时同步并搭建NTP服务,供其他服务器使用

互联网

  • NTP Service
  • 协议:
    • UDP
  • 端口:
    • 123
  • 软件
    • chrony
  • NTP公共服务器
    • ntp.tencent.com
    • ntp.aliyun.com

NTP - docker

1
2
3
4
5
6
7
8
9
10
11
12
13
docker run -e TZ=Asia/Shanghai -d --restart=always \
-p 123:123/udp \
--name ntp \
--env NTP_SERVERS=ntp.tencent.com,ntp.aliyun.com \
--env LOG_LEVEL=0 \
-v /etc/timezone:/etc/timezone:ro \
-v /etc/localtime:/etc/localtime:ro \
--log-opt max-size=10m \
--log-opt max-file=1 \
cturra/ntp:latest

# 检查 ntp 服务器的时间源
docker exec ntp chronyc sources

自建chrony NTP Service

在安装 Chrony 之前,需要在服务器中设置正确的时区。可以使用以下命令进行设置:

1
timedatectl set-timezone Asia/Kolkata

现在,使用以下命令验证您当前的时区:

1
timedatectl

应该得到以下输出:

1
2
3
4
5
6
7
8
9
[root@localhost home]# timedatectl
Local time: 一 2024-05-13 14:44:32 CST
Universal time: 一 2024-05-13 06:44:32 UTC
RTC time: 一 2024-05-13 06:44:51
Time zone: Asia/Shanghai (CST, +0800)
NTP enabled: yes
NTP synchronized: no
RTC in local TZ: no
DST active: n/a

安装 Chrony 服务器

默认情况下,从 Centos 7.x 开始的最小发行版中都已经预装并开启了 Chrony,如果你的系统没有安装,可以用下面命令进行安装

1
yum -y install chrony

安装 Chrony 后,启动 Chrony 服务并使其在系统重启时启动:

1
2
3
4
5
6
# 开启服务
systemctl start chronyd
# 设置自动开机
systemctl enable chronyd
# 查看状态
systemctl status chronyd

配置 Chrony 服务器

Chronys 的主要配置文件位于 /etc/chrony.conf。需要对其进行编辑并更改时间服务器。

1
vi /etc/chrony.conf

注释掉默认池并添加离您的位置最近的 NTP 服务器列表。

主要修改

server

allow

local stratum 10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server ntp.tencent.com iburst
server ntp.aliyun.com iburst
#server ntp.myinspurcloud.com iburst
#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
# 内网无法联网使用,只开启本身其他全注释
# server 192.168.79. iburst

# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift

# Allow the system clock to be stepped in the first three updates
# if its offset is larger than 1 second.
makestep 1.0 3

# Enable kernel synchronization of the real-time clock (RTC).
rtcsync

# Enable hardware timestamping on all interfaces that support it.
#hwtimestamp *

# Increase the minimum number of selectable sources required to adjust
# the system clock.
#minsources 2

# Allow NTP client access from local network.
#allow 192.168.0.0/16
# 允许全部访问
allow all
# Serve time even if not synchronized to a time source.
# 即使未与server时间源同步,也提供时间。
local stratum 10

# Specify file containing keys for NTP authentication.
#keyfile /etc/chrony.keys

# Specify directory for log files.
logdir /var/log/chrony

# Select which information is logged.
#log measurements statistics tracking
#bindcmdaddress 0.0.0.0
#bindcmdaddress ::
#bindcmdaddress /var/run/chrony/chronyd.sock

开启服务

1
2
3
4
5
6
7
8
9
10
# 完成后保存并关闭文件,然后使用以下命令设置 NTP 同步:
timedatectl set-ntp true
# 接下来,重新启动 Chrony 服务以应用更改:
systemctl restart chronyd
# 使用以下命令检查的 NTP 服务器是否正常工作:
chronyc sources -v
# 查看时间信息
date
# 查看详细的时间信息
timedatectl

配置防火墙

需要允许 NTP 服务通过防火墙。可以使用以下命令允许它:

1
firewall-cmd --permanent --add-port=123/udp

接下来,重新加载防火墙服务以应用更改:

1
firewall-cmd --reload

Windows配置命令

1
2
3
4
5
6
7
8
# 自建
w32tm /config /syncfromflags:manual /manualpeerlist:"10.26.8.61"
# 互联网
w32tm /config /syncfromflags:manual /manualpeerlist:"ntp.tencent.com"
# 配置更新
w32tm /config /update
# 同步
w32tm /resync

时间API

搭建在互联网的Chrony那台服务器上,因为有装openresty就直接用了

1
2
3
4
5
6
7
8
# 北京时间
# 2024-05-13 15:08:10
location /time {
default_type 'text/plain';
content_by_lua_block {
ngx.print(os.date("!%Y-%m-%d %H:%M:%S", os.time() + 8 * 3600))
}
}

内网脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
# Get the time from your API
TIME=$(curl -s http://172.12.34.56:12000/time | tr -d '\n')

# Check if time is empty or not
if [ -z "$TIME" ]
then
echo "Failed to fetch time from API!"
exit 1
else
echo "Fetched time from API: $TIME"
fi

# Set the system time
echo "Setting system time..."
sudo date -s "$TIME"
echo "Done!"

配置一下cron,每隔几分钟自动执行一次

1
*/5 * * * * /bin/bash /home/updatesystemtime.sh

最后

如此可以达到内网时间同步情况,但还是依赖于互联网(光闸摆渡)条件,如果完全离线的话需要定期手动调整时间,不然时间误差会在1分钟左右。

参考