Ubuntu 26.10에서 chrony를 ntpd-rs로 바꿔 보기 — NTS 설정과 27.04 기본값 전환 계획

Ubuntu는 sudo와 coreutils에 이어 시간 동기화 데몬도 Rust 구현으로 바꾸려 한다. 대상은 Trifecta Tech Foundation의 ntpd-rs다. Canonical은 27.04에서 ntpd-rs를 기본값으로 만드는 것을 목표로 한다. chrony, linuxptp, gpsd를 단계적으로 대체하는 계획이다. 26.10에는 ntpd-rs 1.9.0이 이미 main 컴포넌트에 들어 있다.

이 글에서는 26.10에서 chrony를 ntpd-rs로 바꾸고, NTS 설정과 상태 확인 방법을 정리한다. 실험은 26.10 클라우드 이미지를 QEMU(TCG)로 띄워 진행했다. KVM 없이 에뮬레이션한 VM이라 시간 정밀도 수치는 실제 하드웨어와 다르다.

릴리스별 패키지와 전환 계획

릴리스별 컨테이너에서 apt-cache policy로 확인한 값이다.

릴리스ntpd-rschrony기본 시간 데몬
24.04 LTS1.1.2-1 (universe)4.5-1ubuntu4.2 (main)systemd-timesyncd
26.04 LTS1.7.1-1 (universe)4.8-2ubuntu1 (main)chrony
26.101.9.0-0ubuntu2 (main)4.8-4ubuntu2 (main)chrony
27.04 (목표)NTP, NTS, PTP 통합 바이너리대체 대상ntpd-rs

27.04 기본값 전환은 확정이 아니다. Canonical은 chrony와 CPU, 메모리, 동기화 정확도를 비교한 뒤 결정한다고 밝혔다. 작업 기간은 2026년 7월부터 2027년 1월까지다.

26.10의 기본 상태: chrony와 NTS

26.10의 chrony는 Ubuntu NTS 서버를 기본으로 쓴다.

$ grep -hvE '^\s*(#|$)' /etc/chrony/sources.d/ubuntu-ntp-pools.sources
pool 1.ntp.ubuntu.com iburst maxsources 1 nts prefer
pool 2.ntp.ubuntu.com iburst maxsources 1 nts prefer
pool 3.ntp.ubuntu.com iburst maxsources 1 nts prefer
pool 4.ntp.ubuntu.com iburst maxsources 1 nts prefer
pool ntp-bootstrap.ubuntu.com iburst maxsources 1 nts certset 1
$ sudo chronyc -N authdata
Name/IP address             Mode KeyID Type KLen Last Atmp  NAK Cook CLen
=========================================================================
1.ntp.ubuntu.com             NTS     1   30  128   41    0    0    8   64
2.ntp.ubuntu.com             NTS     1   30  128   40    0    0    8   64
3.ntp.ubuntu.com             NTS     1   30  128   41    0    0    8   64
4.ntp.ubuntu.com             NTS     1   30  128   41    0    0    8   64
ntp-bootstrap.ubuntu.com     NTS     1   30  128   40    0    0    8   64

ubuntu-minimal은 chrony나 가상 패키지 time-daemon 중 하나에 의존한다. ntpd-rs는 time-daemon을 제공하므로 chrony를 대신할 수 있다.

$ apt-cache depends ubuntu-minimal | grep -A6 '|Depends: chrony'
 |Depends: chrony
  Depends: <time-daemon>
    ntpd-rs
    ntpsec
    openntpd
    ptpd
    systemd-timesyncd
$ apt-cache show ntpd-rs | grep -E '^(Version|Provides|Conflicts|Replaces)'
Version: 1.9.0-0ubuntu2
Replaces: time-daemon
Provides: time-daemon
Conflicts: time-daemon

ntpd-rs로 전환하기

ntpd-rs를 설치하면 APT가 chrony를 자동으로 제거한다.

$ sudo apt-get install -y ntpd-rs 2>&1 | grep -E "REMOVED|NEW packages|^  [a-z]|upgraded,|Removing|Created symlink"
The following packages will be REMOVED:
  chrony
The following NEW packages will be installed:
  ntpd-rs
0 upgraded, 1 newly installed, 1 to remove and 5 not upgraded.
Removing chrony (4.8-4ubuntu2) ...
Created symlink '/etc/systemd/system/multi-user.target.wants/ntpd-rs.service' → '/usr/lib/systemd/system/ntpd-rs.service'.
$ systemctl is-active ntpd-rs chrony
active
inactive

패키지가 설치하는 파일과 기본 설정은 다음과 같다.

$ dpkg -L ntpd-rs | grep -E 'bin/|etc/|\.service|toml'
/etc/apparmor.d
/etc/apparmor.d/usr.bin.ntp-daemon
/etc/ntpd-rs
/etc/ntpd-rs/ntp.toml
/usr/bin/ntp-ctl
/usr/bin/ntp-daemon
/usr/lib/systemd/system/ntpd-rs.service
/usr/share/man/man5/ntp.toml.5.gz
$ grep -v '^\s*#' /etc/ntpd-rs/ntp.toml | grep .
[observability]
log-level = "info"
observation-path = "/var/run/ntpd-rs/observe"
[[source]]
mode = "pool"
address = "ntp.ubuntu.com"
count = 4
[synchronization]
single-step-panic-threshold = 1800
startup-step-panic-threshold = { forward="inf", backward = 86400 }

기본 설정은 NTS가 아닌 일반 NTP 풀이다. 그래서 전환 직후에는 chrony보다 보안 수준이 낮다.

$ grep -E 'Conflicts|Condition|Ambient|User=' /usr/lib/systemd/system/ntpd-rs.service
Conflicts=systemd-timesyncd.service ntp.service chrony.service
ConditionVirtualization=!container
User=ntpd-rs
AmbientCapabilities=CAP_SYS_TIME CAP_NET_BIND_SERVICE

유닛은 컨테이너에서 시작하지 않는다. rootless 컨테이너에서 데몬을 직접 실행해도 시계를 조정할 권한이 없어 바로 종료된다.

$ ntp-daemon -c /etc/ntpd-rs/nts.toml
2026-11-14T15:45:33.315758Z ERROR ntpd::daemon::system: Could not control clock: Insufficient permissions to interact with the clock.

ntp-ctl로 상태 확인

ntp-ctl status는 observation-path의 소켓으로 데몬 상태를 읽는다. 시작 2분 뒤의 출력이다.

$ ntp-ctl status
Synchronization status:
	Dispersion:	0.000000s
	Delay:		0.000000s
	Stratum:	16


Sources:

ntp.ubuntu.com:123 185.125.190.57:123 (4)
	Offset:			+0.288039
	Uncertainty:		±0.300657
	Delay:			±0.266466
	Poll interval:		16s
	Missing polls:		0
	Root dispersion:	0.000702s
	Root delay:		0.006531s

Stratum: 16은 아직 동기화되지 않았다는 뜻이다. 저널에는 소스끼리 합의하지 못했다는 로그가 반복됐다.

$ sudo journalctl -u ntpd-rs -o short-monotonic | tail -1 | cut -c1-120
[  370.655236] ntprs ntp-daemon[1162]: 2026-11-14T16:09:50.020948Z  INFO ntp_proto::algorithm::kalman: No consensus on current time
$ sudo journalctl -u ntpd-rs -o cat | grep -E 'Started|Jumped|Offset:' | head -3 | cut -c1-130
Started ntpd-rs.service - Network Time Service (ntpd-rs).
2026-11-14T16:10:21.362648Z  INFO ntp_proto::algorithm::kalman: Offset: 782.8251261101905+-2.3681045827284852ms, frequency: 59.681
2026-11-14T16:10:22.150634Z  WARN ntp_proto::algorithm::kalman: Jumped offset by 780.457021527462ms. This may cause problems for o

서비스 시작(16:07:20)부터 첫 동기화(16:10:21)까지 약 3분 걸렸다. 그 전에는 No consensus 로그만 반복됐다. 소스별 불확실성이 ±0.3초 수준이었기 때문이다. 이 값은 TCG 에뮬레이션의 시계 흔들림에서 나온 것이다.

NTS 소스로 바꾸기

chrony와 같은 Ubuntu NTS 서버 4개를 mode = "nts"로 지정한다.

[observability]
log-level = "info"
observation-path = "/var/run/ntpd-rs/observe"

[[source]]
mode = "nts"
address = "1.ntp.ubuntu.com"

[[source]]
mode = "nts"
address = "2.ntp.ubuntu.com"

[[source]]
mode = "nts"
address = "3.ntp.ubuntu.com"

[[source]]
mode = "nts"
address = "4.ntp.ubuntu.com"

[synchronization]
single-step-panic-threshold = 1800
startup-step-panic-threshold = { forward="inf", backward = 86400 }
$ ntp-ctl validate
2026-11-14T16:20:05.289280Z  INFO ntpd::daemon::config: using config file at default location `"/etc/ntpd-rs/ntp.toml"`
Config looks good
$ sudo systemctl restart ntpd-rs

12분 뒤에도 동기화되지 않았다. 4개 중 2개가 NTS-KE(포트 4460)로 쿠키는 받았지만, NTP 응답을 한 번도 돌려주지 않았다.

$ ntp-ctl status | grep -E 'Stratum|NTS\]|Missing|cookies|Uncertainty'
	Stratum:	16
1.ntp.ubuntu.com:4460 185.125.190.122:123 [NTS] (3)
	Uncertainty:		±0.006137
	Missing polls:		0
	NTS cookies:		8/8 available
2.ntp.ubuntu.com:4460 185.125.190.123:123 [NTS] (4)
	Uncertainty:		±0.003900
	Missing polls:		0
	NTS cookies:		8/8 available
3.ntp.ubuntu.com:4460 91.189.91.112:123 [NTS] (31)
	Uncertainty:		±2147483648.500000
	Missing polls:		8
	NTS cookies:		6/8 available
4.ntp.ubuntu.com:4460 91.189.91.113:123 [NTS] (32)
	Uncertainty:		±2147483648.500000
	Missing polls:		8
	NTS cookies:		6/8 available

ntpd-rs는 minimum-agreeing-sources의 기본값이 3이다. 응답하는 소스가 2개뿐이면 시계를 맞추지 않는다. chrony의 minsources 기본값은 1이다. 같은 VM의 chrony는 91.189.91.112, .113에도 NTS로 정상 접속했다.

NTS 소스 두 개를 더 넣어 6개로 늘렸다.

[[source]]
mode = "nts"
address = "time.cloudflare.com"

[[source]]
mode = "nts"
address = "nts.netnod.se"
$ ntp-ctl status | grep -E 'Stratum|NTS\]|Missing|Uncertainty'
	Stratum:	4
1.ntp.ubuntu.com:4460 185.125.190.122:123 [NTS] (5)
	Uncertainty:		±0.005880
	Missing polls:		0
2.ntp.ubuntu.com:4460 185.125.190.123:123 [NTS] (4)
	Uncertainty:		±0.715650
	Missing polls:		2
3.ntp.ubuntu.com:4460 91.189.91.112:123 [NTS] (13)
	Uncertainty:		±2147483648.500000
	Missing polls:		8
4.ntp.ubuntu.com:4460 91.189.91.113:123 [NTS] (14)
	Uncertainty:		±2147483648.500000
	Missing polls:		8
nts.netnod.se:4460 194.58.205.196:4123 [NTS] (6)
	Uncertainty:		±0.003496
	Missing polls:		0
time.cloudflare.com:4460 162.159.200.123:123 [NTS] (1)
	Uncertainty:		±0.000735
	Missing polls:		0

재시작 약 3분 30초 뒤 Stratum: 4로 동기화됐다. Netnod는 NTS-KE로 NTP 포트를 4123으로 알려 준다.

chrony와 비교

리소스 값은 같은 TCG VM에서 systemd가 기록한 값이다. 에뮬레이션 환경이라 절대값보다 크기 차이만 참고한다.

$ date -u +%T; systemctl show ntpd-rs -p ActiveEnterTimestamp -p CPUUsageNSec -p MemoryCurrent -p MemoryPeak
16:37:02
ActiveEnterTimestamp=Sat 2026-11-14 16:32:44 UTC
MemoryCurrent=3559424
MemoryPeak=4362240
CPUUsageNSec=3335499000
$ date -u +%T; systemctl show chrony -p ActiveEnterTimestamp -p CPUUsageNSec -p MemoryCurrent -p MemoryPeak
16:42:41
ActiveEnterTimestamp=Sat 2026-11-14 16:38:09 UTC
MemoryCurrent=4968448
MemoryPeak=5324800
CPUUsageNSec=1885433000
항목chrony 4.8ntpd-rs 1.9.0
설정 파일/etc/chrony/chrony.conf, sources.d//etc/ntpd-rs/ntp.toml (TOML)
26.10 기본 소스Ubuntu NTS 서버일반 NTP 풀 ntp.ubuntu.com
동기화 최소 소스 수minsources 1minimum-agreeing-sources 3
AppArmor 프로필enforcecomplain
상태 확인chronyc sources, chronyc authdatantp-ctl status (Prometheus 형식 지원)
실측 CPU 시간1.89초 / 4분 32초3.34초 / 4분 18초
실측 메모리 최댓값5.1 MiB4.2 MiB
미지원 기능–로컬 참조 시계(refclock), 대칭(symmetric) 모드, burst/iburst, 소스별 poll 설정

ntpd-rs의 CPU 시간에는 응답하지 않는 소스 2개를 반복해서 다시 만든 비용이 들어 있다. AppArmor 모드는 aa-status로 확인했다.

$ grep flags /etc/apparmor.d/usr.bin.ntp-daemon /etc/apparmor.d/usr.sbin.chronyd
/etc/apparmor.d/usr.bin.ntp-daemon:/usr/bin/ntp-daemon flags=(complain, attach_disconnected) {
/etc/apparmor.d/usr.sbin.chronyd:/usr/sbin/chronyd flags=(attach_disconnected) {

chrony로 되돌리기

chrony를 다시 설치하면 ntpd-rs가 제거된다. chrony 설정은 rc 상태로 남아 있었으므로 그대로 복원된다.

$ sudo apt-get install -y chrony 2>&1 | grep -E "REMOVED|NEW packages|^  [a-z]|upgraded,|Removing|Setting up chrony"
  networkd-dispatcher
  dnsutils gpsd iw | wireless-tools
The following packages will be REMOVED:
  ntpd-rs
The following NEW packages will be installed:
  chrony networkd-dispatcher
0 upgraded, 2 newly installed, 1 to remove and 5 not upgraded.
Removing ntpd-rs (1.9.0-0ubuntu2) ...
Setting up chrony (4.8-4ubuntu2) ...
$ dpkg -l chrony ntpd-rs | tail -2 | cut -c1-50
ii  chrony         4.8-4ubuntu2   amd64        Ver
rc  ntpd-rs        1.9.0-0ubuntu2 amd64        Rus

주의사항

  • 전환 직후 ntp.toml을 NTS 소스로 바꿀 것. 26.10 패키지의 기본 설정은 인증 없는 NTP 풀을 쓴다.
  • 응답하는 소스를 3개 이상 확보할 것. 그보다 적으면 ntpd-rs는 시계를 맞추지 않는다. 소스를 늘리거나 minimum-agreeing-sources를 낮춘다.
  • AppArmor 프로필이 complain 모드라는 점을 고려할 것. 위반은 기록만 되고 차단되지 않는다. chrony는 enforce 모드다.
  • 컨테이너에서는 ntpd-rs를 돌리지 말 것. 유닛에 ConditionVirtualization=!container가 있고, 시계 조정 권한도 없다. 시간은 호스트가 맞춘다.
  • refclock이나 대칭 모드를 쓰는 서버는 chrony를 유지할 것. ntpd-rs는 아직 이 기능을 지원하지 않는다.
  • 되돌릴 계획이 있으면 purge하지 말 것. remove로 지워진 chrony는 설정 파일과 NTS 쿠키를 유지한다.

마무리

26.10에서 ntpd-rs로 바꾸는 작업은 패키지 하나를 설치하는 것으로 끝난다. 하지만 기본 설정, 최소 소스 수, AppArmor 모드가 chrony와 다르다. 27.04에서 기본값이 바뀌기 전에 이 차이부터 확인해 두는 것이 좋다.

참고

답글 남기기