DB-유

Time Synchronization with chrony

· linux, ntp, chrony, centos

The worst clock bug I ever chased was a certificate reported as "not yet valid" on a VM whose clock had wandered off. Drifting clocks cause odd problems: TLS failures, rejected Kerberos tickets, replication timestamps going backwards, logs you can't line up across hosts. VMs are the worst, since the clock is at the hypervisor's mercy.

CentOS 7 ships chrony instead of the old ntpd. It syncs faster after boot, copes better with flaky networks, and needs a few lines of config. I set it up as a client on CentOS 7 and Ubuntu 18.04, then optionally as an internal time server so every host doesn't go out to the Internet.

Install

On CentOS 7 it's usually there already:

sudo yum -y install chrony
sudo systemctl enable chronyd
sudo systemctl start chronyd

Ubuntu 18.04 defaults to systemd-timesyncd, a minimal SNTP client. Fine for a desktop; on servers I swap in chrony, and installing the package disables timesyncd for you:

sudo apt-get install chrony
systemctl status chrony

Only one NTP daemon at a time. If ntpd is installed, remove it: yum remove ntp or apt-get remove ntp.

Time sources

The config is /etc/chrony.conf on CentOS and /etc/chrony/chrony.conf on Ubuntu. The default distro pool works, but I prefer sources close to the server, or the internal time server if there is one:

# /etc/chrony.conf
server 0.kr.pool.ntp.org iburst
server 1.kr.pool.ntp.org iburst
server 2.kr.pool.ntp.org iburst
server 3.kr.pool.ntp.org iburst

driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony

iburst sends a burst of packets at startup so you sync in seconds, not minutes. makestep 1.0 3 lets the clock jump if it's off by more than a second during the first three updates; after that chrony only slews, which is what applications want. rtcsync periodically copies system time to the hardware clock.

Restart to apply:

sudo systemctl restart chronyd     # 'chrony' on Ubuntu

As a client, chrony needs only outbound UDP 123. firewalld and ufw allow outbound by default, so this matters only behind a strict egress firewall.

Timezone

NTP deals in UTC; the timezone is a separate local setting. I run servers in the local zone so log timestamps match what people expect, though many teams use UTC everywhere. Either works as long as every server agrees:

sudo timedatectl set-timezone Asia/Seoul
timedatectl

The timedatectl output should show NTP synchronized: yes after a minute or so.

Optional: be the time server

Pick one or two internal hosts to sync against the Internet and let everything else sync from them. On the internal server, add to chrony.conf:

allow 192.168.10.0/24
local stratum 10

allow permits clients from that subnet; local stratum 10 lets the server keep serving a fallback time if its own upstream becomes unreachable. Open the port:

sudo firewall-cmd --permanent --add-service=ntp
sudo firewall-cmd --reload

On the clients, replace the pool lines with server ntp01.example.internal iburst and restart chronyd.

Is it syncing?

chronyc sources -v
chronyc tracking

In sources, ^* is the selected source, ^+ are acceptable alternatives, ^? is unreachable. In tracking, look at System time (should be milliseconds or less) and Leap status : Normal. On a time server, chronyc clients lists who's asking.

Problems

  • Every source is ^? and chronyc tracking says Reference ID : 00000000 (): no packets getting through. Try chronyc -a 'burst 4/4', then check egress UDP 123 and DNS for the pool names.
  • timedatectl says NTP synchronized: no though chrony has sources: wait a couple of minutes after a restart. If it never changes, look for a second daemon with systemctl list-units | grep -E 'ntp|timesync'.
  • Clock jumps by minutes on a VM after live migration or snapshot restore: use makestep 1.0 -1 (step any time) if the workload tolerates it, or install the hypervisor's guest agent. Don't run the agent's time sync and chrony together; they fight.
  • 506 Cannot talk to daemon: chronyd isn't running, or on Ubuntu you need sudo chronyc.
  • A client says Not synchronised for the internal server: the server has no upstream and no local stratum, so it won't serve time it doesn't trust.

I add chronyc tracking to the monitoring checks and alert above 100 ms offset. It only fires when the network is broken for other reasons anyway.