Time Synchronization with chrony
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
^?andchronyc trackingsaysReference ID : 00000000 (): no packets getting through. Trychronyc -a 'burst 4/4', then check egress UDP 123 and DNS for the pool names. timedatectlsaysNTP synchronized: nothough chrony has sources: wait a couple of minutes after a restart. If it never changes, look for a second daemon withsystemctl 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 needsudo chronyc.- A client says
Not synchronisedfor the internal server: the server has no upstream and nolocal 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.