Linux NTP 介绍

2017-02-28 linux

网络时间协议 (Network Time Protocol, NTP) 是通过 RFC-1305 定义的时间同步协议,该协议基于 UDP 协议,使用端口号为 123;该协议用于在时间服务器和客户端之间同步时间,从而使网络内所有设备的时钟保持一致。

这里简单介绍 NTP 的使用方法。

NTP

对于运行NTP的本地系统,既可以接收来自其他时钟源的同步,又可以作为时钟源同步其他的时钟,并且可以和其他设备互相同步。

时钟层级 Stratum Levels

NTP 时间同步是按照层级分发时间的。

ntp stratum levels

时钟层级定义了到参考时钟的距离,如上图所示。

  • 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 alibaba basic service

接下来可以使用如下命令。

工作原理

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 秒。

how ntp works

系统时钟同步的工作过程如下:

  1. Device A 发送一个 NTP 报文给 Device B,该报文带有它离开 Device A 时的时间戳,该时间戳为 10:00:00am(T1)。
  2. 当 NTP 报文到达 Device B 时,Device B 会加上自己的时间戳,该时间戳为 11:00:01am(T2)。
  3. 此 NTP 报文离开 Device B 时,Device B 再加上自己的时间戳,该时间戳为 11:00:02am(T3)。
  4. 当 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 packets format

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

参考