网络时间协议 (Network Time Protocol, NTP) 是通过 RFC-1305 定义的时间同步协议,该协议基于 UDP 协议,使用端口号为 123;该协议用于在时间服务器和客户端之间同步时间,从而使网络内所有设备的时钟保持一致。
这里简单介绍 NTP 的使用方法。
NTP
对于运行NTP的本地系统,既可以接收来自其他时钟源的同步,又可以作为时钟源同步其他的时钟,并且可以和其他设备互相同步。
时钟层级 Stratum Levels
NTP 时间同步是按照层级分发时间的。
时钟层级定义了到参考时钟的距离,如上图所示。
- stratum-0 也即参考时钟,有极高的精度,提供可靠的 UTC 时间,通常为铯/铷原子钟(Atomic Cesium/Rubidium Clocks)、GPS 授时或者无线电波授时 (如 CDMA),这类的时钟源不会直接为互联网提供服务。
- stratum-1 直接(非通过网络)链接到 stratum-0 提供服务,通常通过 RS-232、IRIG-B 链接,为互联网提供标准时间。
- stratum-2+ 通过网络向上一级请求服务,通常利用 NTP 协议。
通常距离顶层的时钟源越远时钟的精度也就越差。
安装
在 CentOS 中,可以通过如下方式进行安装。
# yum install ntp ntpdate # 安装
# systemctl [enable|start] ntpd # 设置开机启动,或者直接启动
在 Linux 下有两种时钟同步方式,分别为直接同步和平滑同步:
- 通过 ntpdate 直接同步时间。但异常情况时,若机器有个 12 点的定时任务,当前时间认为是 13 点,而实际的标准时间为 11 点,直接使用该命令会造成任务重复执行;因此该命令多用于时钟同步服务的第一次同步时间时使用。
- 通过 ntpd 可以平滑同步时钟,通过每次同步较小的时间的偏移量,慢慢进行调整,也因此会耗费较长的时间,但可以保证一个时间不经历两次。
www.pool.ntp.org 提供了全球的标准时钟同步服务,对于中国可以参考其中的建议 ntp 配置文件,NTP 建议我们为了保障时间的准确性,最少找两个个 NTP Server 。
server 0.asia.pool.ntp.org
server 1.asia.pool.ntp.org
server 2.asia.pool.ntp.org
server 3.asia.pool.ntp.org
它的一般格式都是 number.country.pool.ntp.org ;当然,也可以使用阿里的公共服务。
接下来可以使用如下命令。
工作原理
NTP 授时有以下三种工作模式。
broadcast/multicast
适用于局域网的环境,时间服务器周期性以广播的方式,将时间信息传送给其他网路中的时间服务器,配置简单 (可做到客户端免配置),但是精确度不高,对时间精确度要求不是很高的情况下可以采用。
client/server
最主流的 ntp 授时方式,精度较高,对网络没有特殊要求;同时可以指定多个 ntp server,因而也可避免网络路径失效带来的时钟不能同步。
symmetric
一台服务器可以从远端时间服务器获取时钟,如果需要也可提供时间信息给远端的时间服务器,服务器之间的 peer 关系即为这种工作方式。
接下来,简单介绍下 Client/Server 模式。
如下图所示,Device A 和 Device B 通过网络相连,且都有自己独立的系统时钟,需要通过 NTP 实现各自系统时钟的自动同步。假设在系统时钟同步前,Device A 的时钟设定为 10:00:00am,Device B 的时钟设定为 11:00:00am。
其中 Device B 作为 NTP 时间服务器,即 Device A 将使自己的时钟与 Device B 的时钟同步,另外,假设 NTP 报文在 Device A 和 Device B 之间单向传输所需要的时间为 1 秒。
系统时钟同步的工作过程如下:
- Device A 发送一个 NTP 报文给 Device B,该报文带有它离开 Device A 时的时间戳,该时间戳为 10:00:00am(T1)。
- 当 NTP 报文到达 Device B 时,Device B 会加上自己的时间戳,该时间戳为 11:00:01am(T2)。
- 此 NTP 报文离开 Device B 时,Device B 再加上自己的时间戳,该时间戳为 11:00:02am(T3)。
- 当 Device A 接收到该响应报文时,Device A 的本地时间为 10:00:03am(T4)。
至此,Device A 已经拥有足够的信息来计算两个重要的参数:A)报文的往返时延 Delay=(T4-T1)-(T3-T2)=2s;B) Device A 相对 Device B 的时间差 Offset=((T2-T1)+(T3-T4))/2=1h。这样,Device A 就能够根据这些信息来设定自己的时钟,使之与 Device B 的时钟同步。
NTP 的报文格式
NTP 有两种不同类型的报文,一种是时钟同步报文,另一种是控制报文。控制报文仅用于需要网络管理的场合,它对于时钟同步功能来说并不是必需的,在此只介绍时钟同步报文。
NTP 提供了多种工作模式进行时间同步,包括了:客户端/服务器模式、对等体模式、广播模式、组播模式。
在不能确定服务器或对等体IP地址、网络中需要同步的设备很多等情况下,可以通过广播或组播模式实现时钟同步;客户端/服务器和对等体模式中,设备从指定的服务器或对等体获得时钟同步,增加了时钟的可靠性。
启动 NTP 服务
接下来,看看如何在 Linux 中配置并启动 ntp 服务器。
配置文件
先修改配置文件 /etc/ntp.conf ,只需要加入上面的 NTP Server 和一个 driftfile 就可以了。
# vi /etc/ntp.conf
driftfile /var/lib/ntp/drift
server 0.asia.pool.ntp.org
server 1.asia.pool.ntp.org
server 2.asia.pool.ntp.org
server 3.asia.pool.ntp.org
fudge 127.127.1.0 stratum 0 stratum 这行是时间服务器的层次。设为0则为顶级,如果要向别的NTP服务器更新时间,请不要把它设为0
更新时间
如上,在正式启动 NTP 服务器之前,需要先通过 ntpdate 命令同步系统时间。需要注意的是,此时最好不要启动服务,否则可能由于时间跳变导致服务异常。
# ntpdate 0.asia.pool.ntp.org
# ntpdate 1.asia.pool.ntp.org
需要注意的是,通过 ntpdate 更新时间时,不能开启 NTP 服务,否则会提示端口被占用。
1 Jan 22:35:08 ntpdate[12481]: no servers can be used, exiting
当然,可以通过 cron 定期更新时间,
30 8 * * * root /usr/sbin/ntpdate 192.168.0.1; /sbin/hwclock -w
这样,每天 8:30 Linux 系统就会自动的进行网络时间校准,并写入硬件时钟。
查看状态
首先,通过 ntpstat 查看 NTP 服务的整体状态。
# ntpstat
synchronised to NTP server (202.112.29.82) at stratum 3
time correct to within 44 ms
polling server every 256 s
然后,可以通过 ntpq (NTP query) 来查看当前服务器的状态,到底和那些服务器做时间同步。
# watch ntpq -pn
Every 2.0s: ntpq -p Sat Jul 7 00:41:45 2007
remote refid st t when poll reach delay offset jitter
===========================================================
+193.60.199.75 193.62.22.98 2 u 52 64 377 8.578 10.203 289.032
*mozart.musicbox 192.5.41.41 2 u 54 64 377 19.301 -60.218 292.411
现在我就来解释一下其中各个字段的含义。
remote: 本地机器所连接的远程NTP服务器;
refid: 给远程服务器提供时间同步的服务器,也就是上级服务器;
st: 远程服务器的层级别,级别从1~16,原则上不会与1直接链接;
t: 也就是type,表示该时间服务器的工作模式(local, unicast, multicast or broadcast);
when: 多少秒之前与服务器成功做过时间同步;
poll: 和远程服务器多少秒进行一次同步,开始较小,后面会逐渐增加,可在配置文件中通过minpoll+maxpoll设置;
reach: 成功连接服务器的次数,这是八进值;
delay: 从本地机发送同步要求到服务器的网络延迟 (round trip time);
offset: 本地和服务器之间的时间差别,该值越接近于0,说明和服务器的时间越接近;
jitter: 统计值,统计了offset的分布情况,这个数值的绝对值越小则说明和服务器的时间就越精确;
对于上述输出,有几个问题,第一我们在配置文件中设置与 remote 不同?
因为 NTP 提供的是一个集群,所以每次连接的得到的服务器都有可能是不一样,也就意味着,配置文件中最好指定 hostname 而非 IP 。
第二问题是,那个最前面的 + 和 * 都是什么意思呢?如上,提供了多个服务器同步时间,这些标志就是用来标识服务器的状态。
(space) reject,节点网络不可达,或者 ACL 有限制;
x falsetick 通过算法确定远程服务器不可用;
. excess 不在前10个同步距离较短的节点所以被排除,如果前10个节点故障,该节点可进一步被选中;
- outlyer 远程服务器被clustering algorithm认为是不合格的NTP Server;
+ candidate 将作为辅助的服务器,作为组合算法的一个候选者,当上述的服务器不可用时,该服务器会接管;
* sys.peer 服务器被确认为我们的主NTP Server,系统时间将由这台机器所提供;
o pps.peer 该节点为选中的时钟源,系统时钟以其为参考;
也即是说,输出内容中第一个域标记符号是 * 即可认为系统通过该时间源同步时间。
了解这些之后我们就可以实时监测我们系统的时间同步状况了;注意,部分虚拟机使用的是容器,无独立 kernel,使用的就是宿主机的时间源,所以这时就需要到对应宿主机器排查。
# systemctl start ntpd
$ ps aux | grep ntp
其它
记录下常见的问题。
1. 配置文件中的driftfile是什么?
每个 system clock 的频率都有误差,NTP 会监测我们时钟的误差值并予以调整,但是 NTP 不会立即调整时间,这样会导致时钟跳变,所以采用的是渐进方式,进而导致这是一个冗长的过程。
为此,它会把记录下来的误差先写入 driftfile,这样即使重启之前的计算结果也就不会丢失了。
另外,记录的单为是 PPM (Part Per Million),是指百万分之一秒,也就是微秒,
2. 如何同步硬件时钟?
NTP 一般只会同步 system clock,如果我们也要同步 RTC (hwclock) 的话那么只需要把下面的选项打开就可以了。
# vi /etc/sysconfig/ntpd
SYNC_HWCLOCK=yes
参考
- standard NTP query program ntpq 的实现官网,而且包括了很多相关的资料 The Network Time Protocol (NTP) Distribution 。
- 关于时间的简单介绍,包括了时区、NTP 等 Managing Accurate Date and Time,或者 本地文档 ;其它的一些关于 GPS 相关的信息可以参考 GPS时间同步原理及其应用 ,一篇十分不错的文章。
- Stratum Levels Defined 关于时钟层级的定义;另外一篇关于 ntpq 的介绍可以参考 网络时间的那些事及 ntpq 详解 ,或者参考 本地文档 。
- 实际可以通过 GPS 和 Raspberry Pi 搭建 stratum-1 服务器,可以参考 Building a Stratum 1 NTP Server with a Raspberry Pi ,也可参考 [本地文档](/reference/misc/ntp/Building a Stratum 1 NTP Server with a Raspberry Pi.mht);或者另一篇 The Raspberry Pi as a Stratum-1 NTP Server,也可查看 [本地文档](/reference/misc/ntp/Building a Raspberry-Pi Stratum-1 NTP Server.mht) 。