Debian 13: NTP працює, але дрейф не зникає — налаштування апаратного годинника та Chrony (Випадок №79)

Було корисно?

Усе показує «синхронізовано». Ваші панелі зелені. Але журнали наполягають, що сервер повільно подорожує в часі: TLS‑handshake’и ламаються, Kerberos поводиться примхливо, вікна резервного копіювання ковзають, а розподілені трейси нагадують сучасне мистецтво.

Це той специфічний збій, який змушує SRE підозрювати саму реальність: NTP «працює», але дрейф не зникає. Виправлення рідко зводиться до «перезапустити chrony». Потрібно зрозуміти, який годинник брешe, хто кого дисциплінує і що апаратне забезпечення (або гіпервізор) тихо робить за вашою спиною.

Що насправді означає «NTP працює, але дрейф не зникає»

Коли кажуть «NTP працює», зазвичай мають на увазі одне з наступного:

  • Служба запущена (chronyd активний).
  • Є доступні джерела (деякі сервери відображаються як онлайн).
  • Системний годинник не сильно неправий у момент перевірки.

Коли кажуть «дрейф не зникає», зазвичай мають на увазі зовсім інше:

  • Годинник правильний одразу після завантаження, але неправильний через кілька годин.
  • Годинник правильний, але іноді стрибком змінюється вперед/назад.
  • NTP повідомляє про синхронізацію, та в застосунках таймстемпи розходяться між вузлами.
  • Системний годинник у порядку, але апаратний годинник (RTC) неправильний, тому після перезавантаження починаєте з неправильної позначки часу.

Пастка: NTP — це не «встановити час один раз». Це система керування. Якщо контур керування бореться з поганим осциляторам, багатим clocksource, часними маніпуляціями гіпервізора або політикою, що забороняє стрибки, ви отримаєте статус «синхронізовано» й досі відчуєте симптоми дрейфу.

Цікаві факти та історичний контекст (щоб перестати боротися з фізикою)

  1. NTP старший за сучасний Інтернет. Перші роботи над специфікацією NTP почалися на початку 1980‑х; він старший за більшість «cloud‑native» кар’єр.
  2. Unix‑час не є монотонним. «Настінний годинник» може йти назад; монотонний час — окремий лічильник для вимірювання інтервалів.
  3. Секунди‑вставки (leap seconds) — не теоретичні. Їх додавали десятки разів з 1970‑х, і різні системи обробляють їх по‑різному.
  4. PC RTC ніколи не був призначений для точної синхронізації. Це зручний годинник для збереження часу при відключенні живлення, а не прилад для точності.
  5. Кварцові осцилятори дрейфують через температуру і старіння. Компоненти бюджетного класу регулярно дрейфують на десятки ppm; це секунди на добу, а не на місяць.
  6. Деякі гіпервізори «допомагають», примусово виставляючи час у гостя. Це може вступати в конфлікт із chrony, створюючи пилкоподібні відхилення та «таємничі» стрибки.
  7. Вибір kernel clocksource має значення. Стабільний TSC може бути відмінним; нестабільний — спричинити хаос з правдоподібною незнаністю.
  8. Chrony створено для «потворних» мереж. Він краще справляється з переривчастим звʼязком і великими варіаціями затримок, ніж класичний ntpd у багатьох випадках.

Швидка діагностика — план дій

Коли повідомляють про дрейф часу, потрібно швидко виявити вузьке місце: це вхід (погані джерела), політика керування (не дозволяє стрибків, неправильні пороги), осцилятор (дрейфуюче апаратне/VM) чи шлях при завантаженні (неправильний RTC)? Робіть у такому порядку:

1) Підтвердіть, який час неправильний (системний годинник проти RTC проти «часу в застосунку»)

  • Перевірте системний час, часовий пояс і стан синхронізації.
  • Перевірте час RTC і чи збережено він як UTC.
  • З’ясуйте, чи скарга стосується порядку записів у логах, терміну дії TLS/сертифікатів або монотонних таймерів (різні причини).

2) Подивіться на погляд chrony на реальність

  • Чи chrony відстежує стабільне джерело?
  • Чи він болісно слеїть через ліміти?
  • Чи часто він робить стрибки, бо зсуви стають великими?

3) Шукайте стрибки часу та конфлікти

  • Повідомлення ядра про нестабільність clocksource.
  • Інструменти VM / агент гіпервізора, що примусово встановлюють час гостя.
  • Декілька демонов синхронізації часу, що працюють одночасно.

4) Якщо під час роботи все стабільно, але після перезавантаження — неправильно: шлях RTC

  • Налаштування hwclock, невідповідність UTC/localtime, відсутність періодичної синхронізації.
  • Розряджена батарейка RTC (так, це ще трапляється).

Цитата, яку варто наклеїти собі на лоб: перефразована думка від Gene Kranz: «Будьте жорсткими й компетентними.» Багато помилок із часом вимагають обох якостей.

Ментальна модель: три годинники і кілька брехунів

На системі Debian 13 вас цікавлять три часові конструкції:

  • Системний годинник (також wall clock): те, що друкує date; використовується для таймстемпів, валідності сертифікатів, cron, Kerberos, логів.
  • Монотонний годинник: використовується для вимірювання інтервалів; не повинен іти назад; демони часу можуть опосередковано регулювати його швидкість, але він не «стрибає» так само, як wall clock.
  • Апаратний годинник (RTC): батарейно‑підтримуваний годинник на материнській платі (або віртуальний еквівалент). Використовується при завантаженні для ініціалізації системного часу.

NTP/chrony дисциплінує системний годинник. Він не «виправляє» RTC автоматично, якщо ви явно не синхронізуєте його або не налаштуєте сервіс для цього. Якщо RTC неправильний, після перезавантаження ви отримаєте неправильний час, а chrony витратить час, щоб його виправити — іноді повільно, іноді не взагалі, якщо політика забороняє стрибки.

Також: Debian може запускати systemd-timesyncd або chrony (або обидва, що не є хорошою ідеєю). Оберіть один. Для серверів — chrony. Він прозоріший, більш керований і показує, що саме відбувається.

Жарт №1: Час — ілюзія. Chrony — ілюзія з логами.

Практичні завдання: команди, виводи та рішення (12+)

Це завдання, які я виконую в продакшені, коли хтось каже «NTP в порядку», а системний час явно ні. Кожне завдання містить: команду, реалістичну форму виводу та яке рішення слід прийняти далі.

Завдання 1: Перевірити поточний стан за допомогою timedatectl

cr0x@server:~$ timedatectl
               Local time: Tue 2025-12-31 10:14:22 UTC
           Universal time: Tue 2025-12-31 10:14:22 UTC
                 RTC time: Tue 2025-12-31 09:58:05
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Що це означає: Системний годинник синхронізований, але RTC відстає приблизно на 16 хвилин. Це пастка при перезавантаженні.

Рішення: Якщо це справжній апаратний RTC, заплануйте синхронізацію RTC із системним часом після стабілізації chrony (і дослідіть причину дрейфу RTC). Якщо це VM, перевірте налаштування синхронізації між гостем і хостом.

Завдання 2: Перевірити, який сервіс синхронізації часу активний (щоб уникнути конфліктів)

cr0x@server:~$ systemctl status chrony --no-pager
● chrony.service - chrony, an NTP client/server
     Loaded: loaded (/lib/systemd/system/chrony.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-12-31 09:50:10 UTC; 24min ago
       Docs: man:chronyd(8)
             man:chronyc(1)
    Process: 612 ExecStart=/usr/sbin/chronyd -F 1 (code=exited, status=0/SUCCESS)
   Main PID: 640 (chronyd)
      Tasks: 1
     Memory: 3.2M
        CPU: 120ms
     CGroup: /system.slice/chrony.service
             └─640 /usr/sbin/chronyd -F 1
cr0x@server:~$ systemctl status systemd-timesyncd --no-pager
● systemd-timesyncd.service - Network Time Synchronization
     Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; disabled; preset: enabled)
     Active: inactive (dead)

Що це означає: Добре: активний лише chrony.

Рішення: Якщо обидва активні, вимкніть systemd-timesyncd (або видаліть chrony, але не робіть цього на серверах без вагомої причини).

Завдання 3: Подивитися на погляд chrony (чи він упевнений чи ні?)

cr0x@server:~$ chronyc tracking
Reference ID    : 203.0.113.10 (ntp1.example.net)
Stratum         : 3
Ref time (UTC)  : Tue Dec 31 10:14:18 2025
System time     : 0.000423812 seconds slow of NTP time
Last offset     : -0.000221901 seconds
RMS offset      : 0.000612554 seconds
Frequency       : 24.731 ppm fast
Residual freq   : -0.112 ppm
Skew            : 0.931 ppm
Root delay      : 0.022741 seconds
Root dispersion : 0.004921 seconds
Update interval : 64.2 seconds
Leap status     : Normal

Що це означає: Системний час фактично в порядку зараз. Частота 24.7 ppm швидша — це не дивина для бюджетного обладнання, але це вказує на наявний дрейф, який chrony компенсує.

Рішення: Якщо користувачі все ще скаржаться на дрейф, швидше за все причина в перезавантаженнях/RTC, періодичних стрибках або іншому компоненті, що переустановлює час.

Завдання 4: Проінспектувати якість джерел (проти чого ви дисциплінуєтесь)

cr0x@server:~$ chronyc sources -v
  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unreachable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.    |            |  yyyy = measured offset,
||                                \   |            |  zzzz = estimated error.
||                                 |  |            |
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* ntp1.example.net              2   6   377    22   -221us[ -311us] +/-  8ms
^+ ntp2.example.net              2   6   377    21   -102us[ -190us] +/- 10ms
^- ntp3.example.net              3   6   377    20   +891us[ +830us] +/- 22ms

Що це означає: Reach 377 — здорово, декілька джерел, малі відхилення. Не ваша проблема.

Рішення: Якщо бачите ? unreachable або ~ занадто змінний, виправляйте мережу, фаєрвол або обирайте кращі сервери.

Завдання 5: Перевірити події стрибків і великі корекції

cr0x@server:~$ journalctl -u chrony --since "today" --no-pager
Dec 31 09:50:10 server chronyd[640]: chronyd version 4.5 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS)
Dec 31 09:50:11 server chronyd[640]: System clock was stepped by -963.241 seconds
Dec 31 09:50:11 server chronyd[640]: Selected source 203.0.113.10
Dec 31 09:52:15 server chronyd[640]: System clock TAI offset set to 37 seconds

Що це означає: На старті годинник був відкоригований на майже 16 хвилин назад і було зроблено стрибок. Зазвичай це походить від поганого RTC або неправильної початкової іниціалізації часу.

Рішення: Виправте RTC і переконайтеся, що chrony дозволяє стрибки на ранній стадії завантаження (makestep), інакше служби стартують із неправильним часом і можуть не відновитися повністю.

Завдання 6: Порівняти RTC і системний час безпосередньо

cr0x@server:~$ sudo hwclock --show
2025-12-31 09:58:15.123456+00:00
cr0x@server:~$ date -u
Tue Dec 31 10:14:31 UTC 2025

Що це означає: RTC відстає. Якщо зараз перезавантажити, ви стартуєте в минулому.

Рішення: Якщо це фізичний сервер, розгляньте проблеми з батарейкою RTC/прошивкою. Якщо VM — не вважайте RTC авторитетним і виправте інтеграцію часу між хостом і гостем.

Завдання 7: Перевірити, чи RTC налаштований як UTC (має бути)

cr0x@server:~$ cat /etc/adjtime
0.000000 1767174612 0.000000
0
UTC

Що це означає: RTC очікується як UTC. Добре.

Рішення: Якщо бачите LOCAL тут на сервері, виправте це, якщо тільки у вас немає специфічної потреби для dual‑boot.

Завдання 8: Визначити clocksource і чи вважає ядро його стабільним

cr0x@server:~$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
cr0x@server:~$ dmesg | grep -i clocksource | tail -n 8
[    0.000000] tsc: Detected 2592.000 MHz processor
[    0.120000] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x2557f2f71a, max_idle_ns: 440795309246 ns
[    0.130000] clocksource: Switched to clocksource tsc

Що це означає: Використовується TSC. На сучасному обладнанні це може бути відмінно. На деяких віртуалізованих або з енергозбереженням сценаріях — проблема.

Рішення: Якщо бачите попередження про нестабільність або часті стрибки часу, протестуйте інший clocksource (див. розділ нижче).

Завдання 9: Виявити стрибки часу та «годинник пішов назад» на рівні застосунку

cr0x@server:~$ journalctl -k --since "today" | grep -E "time.*(jump|backward)|clocksource.*unstable" --no-pager
Dec 31 10:02:44 server kernel: clocksource: timekeeping watchdog on CPU2: Marking clocksource 'tsc' as unstable because the skew is too large
Dec 31 10:02:44 server kernel: clocksource: Switched to clocksource hpet

Що це означає: Ядро помітило нестабільність TSC і перемкнуло clocksource. Це серйозна ознака для «дрейфу, що не зникає».

Рішення: Виправте налаштування BIOS/прошивки, відключіть агресивні C‑стани або закріпіть стабільний clocksource. На VM — виправте налаштування host time/tsc.

Завдання 10: Переконатися, що NTP‑пакети не блокуються або не змінюються

cr0x@server:~$ sudo ss -uapn | grep :123
UNCONN 0      0          0.0.0.0:123        0.0.0.0:*    users:(("chronyd",pid=640,fd=5))
UNCONN 0      0             [::]:123           [::]:*    users:(("chronyd",pid=640,fd=6))
cr0x@server:~$ sudo nft list ruleset | grep -n "dport 123" | head
127: udp dport 123 accept

Що це означає: chrony слухає; фаєрвол дозволяє NTP.

Рішення: Якщо немає правила accept і джерела недоступні, додайте правило або виправте мережеве фаєрволювання.

Завдання 11: Перевірити стан дисципліни системного годинника (поведінка kernel PLL)

cr0x@server:~$ timedatectl show-timesync --all
SystemNTPServers=
FallbackNTPServers=
ServerName=
ServerAddress=
RootDistanceMaxUSec=5s
PollIntervalMinUSec=32s
PollIntervalMaxUSec=34min 8s
Frequency=24731

Що це означає: Цей вивід більше стосується systemd-timesyncd, але все ще може показувати значення дисципліни частоти. Не читаєте занадто багато з нього, якщо ви на chrony.

Рішення: Використовуйте інструменти chrony для істини; уникайте змішування інтерпретацій між демонами.

Завдання 12: Перевірити, чи chrony дозволено робити стрибки при потребі (коректність на старті)

cr0x@server:~$ grep -nE "^(makestep|rtcsync|driftfile|leapsectz)" /etc/chrony/chrony.conf
12:driftfile /var/lib/chrony/chrony.drift
18:makestep 1.0 3
22:rtcsync
26:leapsectz right/UTC

Що це означає: makestep 1.0 3 дозволяє стрибок, якщо зсув > 1 секунди, але лише в перші 3 оновлення. rtcsync періодично копіює системний час в RTC.

Рішення: Якщо ви завантажуєтеся з великим відхиленням, збільште вікно step (кількість) тимчасово або виправте RTC, щоб не потребувати «героїчних» дій. Зазвичай тримати rtcsync правильно на фізичному обладнанні.

Завдання 13: Перевірити оновлення driftfile (чи chrony вчиться осцилятора?)

cr0x@server:~$ sudo ls -l /var/lib/chrony/chrony.drift
-rw-r--r-- 1 _chrony _chrony 18 Dec 31 10:14 /var/lib/chrony/chrony.drift
cr0x@server:~$ sudo cat /var/lib/chrony/chrony.drift
24.731 0.931

Що це означає: Chrony виміряв частоту (~24.7 ppm) і оцінив похибку. Якщо це ніколи не оновлюється, щось неправильно (права, файловий розділ readonly, обмеження контейнера).

Рішення: Відновіть збереження; без навчання дрейфу ви будете перенавчатися при кожному завантаженні і довше сходитися до правильного часу.

Завдання 14: Переконатися, що нічого іншого не примусово встановлює час (VM‑агенти, скрипти)

cr0x@server:~$ ps aux | egrep -i "(ntpd|timesyncd|openntpd|ptp4l|phc2sys)" | grep -v egrep
root         640  0.0  0.1  81200  3520 ?        Ssl  09:50   0:00 /usr/sbin/chronyd -F 1

Що це означає: У очевидному списку лише chronyd.

Рішення: Якщо знайдете кілька демонів часу, оберіть один і вимкніть інші. Якщо ви на VM, окремо перевірте агенти гостя (див. розділ про віртуалізацію).

Налаштування chrony, які дійсно допомагають

Параметри за замовчуванням chrony розумні, але «розумні» припускають, що ваш RTC не катастрофа і платформа не випадково стрибає час. Коли дрейф не зникає, налаштовують під два цілі:

  1. Швидко завантажуватися з правильним часом, щоб залежні служби не стартували з неправильними мітками.
  2. Залишатися стабільним, навіть коли джерела шумні або звʼязок переривчастий.

1) Дозвольте стрибки на початку, але не назавжди: makestep

Стрибок — це миттєва зміна. Slew — поступове регулювання швидкості. Стрибок потрібний при завантаженні, коли відхилення на хвилини; slew підходить у звичайній роботі при мілісекундних відхиленнях.

Типове серверне налаштування:

cr0x@server:~$ sudo grep -n "^makestep" /etc/chrony/chrony.conf
18:makestep 1.0 3

Рекомендація: Якщо ваш RTC іноді неправильний на десятки секунд, тимчасово поставте makestep 1.0 10, поки не виправите RTC. Не залишайте політику «завжди стрибати» на вузлах, чутливих до затримок, якщо вам подобається розбиратися з дивними таймстемпами транзакцій.

2) Забезпечте персистентність навчання осцилятора: driftfile має бути записуваним

Chrony може компенсувати постійно швидший/повільніший годинник, якщо він може вчитися і зберігати поправку частоти в driftfile.

Якщо ви використовуєте immutable images або readonly rootfs, переконайтеся, що /var/lib/chrony зберігається. Інакше ви кожного разу довго конвергуєтесь після перезавантаження.

3) Синхронізувати RTC із системним часом (для фізичних серверів): rtcsync

rtcsync дозволяє періодично копіювати системний час в RTC. Це не робить RTC пристроєм високої точності. Це робить наступне завантаження менш соромним.

На bare metal я зазвичай хочу rtcsync. На деяких VM «RTC» — абстракція, і синхронізація може бути неважливою або контрпродуктивною, якщо гіпервізор також управляє часом.

4) Контролюйте частоту оновлень і чутливість до мережі

Якщо ваші NTP‑джерела через нестабільну WAN, chrony впорається, але відхилення можуть бути більш шумними. Ви можете покращити стабільність, обравши ближчі сервери або зменшивши залежність від одного джерела.

Коли хтось пропонує «просто опитувати частіше», пам’ятайте: частіше опитування може підвищити чутливість до шуму і навантаження. Воно також може розстроїти upstream NTP‑сервери, якщо ви завзятий опитувач.

5) Використовуйте хороші джерела, а не «що завгодно, що резолвиться»

Для корпоративних мереж вкажіть в chrony:

  • внутрішні stratum‑1/2 сервери (якщо вони керуються вправно),
  • або надійний провайдер NTP,
  • або локальні мережеві пристрої з GPS/PTP (де доречно).

І завжди конфігуруйте кілька джерел. Одне джерело — єдина точка самообману.

Апаратний годинник (RTC) і hwclock: зробіть його нудним знову

Більшість випадків «дрейф не зникає» насправді не є провалом NTP. Це провали в життєвому циклі RTC: машина завантажується з неправильним часом, потім NTP виправляє його, потім хтось перезавантажує і знову звинувачує NTP. Ви не переслідуєте дрейф; ви женетесь за петлею скидання в неправильний стан.

RTC має бути в UTC, майже завжди

На Linux‑серверах тримайте RTC у UTC. ОС може застосувати часові пояси; RTC не повинен. Правила часових поясів змінюються. UTC — ні. Це не ідеологія; це контроль ушкоджень.

Записуйте системний час в RTC після синхронізації (коли доречно)

Якщо chrony дає хороший час, оновіть RTC:

cr0x@server:~$ sudo hwclock --systohc --utc

Що це означає: RTC встановлено з поточного системного часу й збережено як UTC.

Рішення: Робіть це на bare metal після підтвердження стабільності chrony. Якщо RTC швидко дрейфує, очікуйте повторів і досліджуйте апаратну проблему.

Прочитати RTC у системний час (переважно для відновлення)

cr0x@server:~$ sudo hwclock --hctosys --utc

Що це означає: Ви встановлюєте системний час з RTC. Зазвичай це виконується на ранньому етапі завантаження ОС.

Рішення: Не використовуйте це для «виправлення» робочої системи, яка вже дисциплінована NTP, якщо ви не навмисно робите це для інцидентного реагування.

Коли дрейф RTC — апаратна проблема

На фізичних серверах постійний дрейф RTC може бути викликаний:

  • Поганою батарейкою RTC (класика, нудна, реальна).
  • Багами прошивки при оновленні RTC.
  • Коливаннями температури в edge‑деплойментах.
  • RTC‑пристроєм, який просто поганий.

Для серверів у дата‑центрі швидкий дрейф RTC часто означає «замініть компонент», а не «налаштовуйте chrony сильніше».

Kernel clocksource, TSC і чому «стабільний» умовний

Якщо ваш системний годинник стрибає, chrony легко звинуватити, бо воно видиме. Але двигун під капотом — kernel clocksource. Якщо він нестабільний, ви можете спостерігати:

  • offsetи chrony, що мають пилкоподібну форму або ніколи не сходяться,
  • журнали ядра про дії watchdog для clocksource,
  • застосунки повідомляють «годинник пішов назад»,
  • гості VM дрейфують у такт із завантаженням хоста або подіями міграції.

Перегляньте доступні clocksources

cr0x@server:~$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm

Що це означає: Існують декілька clocksources; ядро обирає один. TSC зазвичай найшвидший і найкращий, коли він invariant/stable.

Рішення: Якщо ядро позначає TSC як нестабільний, розгляньте привʼязку до іншого джерела як тимчасову міру, поки ви не виправите прошивку/налаштування VM.

Закріпити clocksource (помʼякшення, а не постійна практика)

Для тесту можна задати параметр ядра при завантаженні (через GRUB), наприклад clocksource=hpet або інший. Це залежить від середовища і потребує тестування. Мета не «HPET назавжди». Мета — «припинити стрибки часу, поки ми виправляємо платформу».

Жарт №2: TSC — як табель часу стажера: точний під наглядом, творчий, якщо залишити одного.

Пастки віртуалізації: коли хост газлайтить гостьову систему

У VM «апаратний годинник» — те, що емулює гіпервізор. Це може бути стабільним або «достатньо близько», доки не станеться жива міграція, перевантаження хоста чи подія паузи/відновлення.

Класичний режим відмови VM: два майстри

Ви запускаєте chrony всередині гостя, в той час як гіпервізор (або агент гостя) також періодично примушує час гостя. Це створює боротьбу:

  • chrony повільно слеїть, намагаючись залишатися стабільним,
  • гіпервізор різко стрибає, «щоб допомогти»,
  • застосунки бачать стрибок назад/вперед,
  • chrony логування показує стрибки і його звинувачують.

Виявити поширені агенти гостя

Наприклад, на деяких платформах ви можете бачити qemu‑guest‑agent або подібне:

cr0x@server:~$ systemctl status qemu-guest-agent --no-pager
● qemu-guest-agent.service - QEMU Guest Agent
     Loaded: loaded (/lib/systemd/system/qemu-guest-agent.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-12-31 09:49:58 UTC; 25min ago
   Main PID: 510 (qemu-ga)
      Tasks: 1
     Memory: 2.8M
        CPU: 52ms
     CGroup: /system.slice/qemu-guest-agent.service
             └─510 /usr/sbin/qemu-ga

Що це означає: Агент гостя запущений. Це не гарантує, що він встановлює час, але це підозрілий елемент.

Рішення: Перевірте політику гіпервізора: або дозвольте гостю керувати часом за допомогою chrony, або нехай хост контролює час і відключіть NTP в гості. Змішане керування — місце, куди йде здоровий глузд.

Жива міграція і «раптові» повідомлення про дрейф

Якщо дрейф зʼявляється після міграцій, перевірте:

  • налаштування стабільності TSC на хості,
  • модель CPU для VM і експозицію invariant TSC,
  • здоровʼя NTP хоста (якщо хост неправий — гості успадковують дивності).

У корпоративних середовищах виправляють час на рівні хоста перш за все. Гості — споживачі знизу вгору.

Три корпоративні міні‑історії (анонімізовано)

Інцидент через неправильне припущення: «Синхронізовано» означає правильний після перезавантаження

Середня компанія працювала з Debian‑логгерами на bare metal. Моніторинг перевіряв chronyc tracking раз на годину і тривожив, якщо системний зсув перевищував поріг. Він ніколи цього не робив. Усі почувалися впевнено щодо часу.

Потім настала вікно обслуговування. Вони перезавантажили половину флоту для застосування оновлень ядра. Негайно затримки інжесту зросли, і частина логів опинилася поза порядком. На черговому дзвінку людина бачила «System clock synchronized: yes» і думала, що проблема в іншому місці.

Справжня причина була приземлена: дрейф RTC. До перезавантаження chrony дисциплінував системний час, тож моніторинг виглядав ідеально. Після перезавантаження служби стартували з неправильним часом, записали купу неправильних таймстемпів, а потім chrony повернув годинник на місце. «Шкода» вже було завдано.

Виправлення не було екзотичним. Вони ввімкнули rtcsync, перевірили, що RTC у UTC, і додали час‑захист при завантаженні: критичні сервіси стартували після підтвердження синхронізації chrony. Також додали моніторинг, який щодня порівнює RTC і системний час. Урок закарбувався через свою простоту і сором.

Оптимізація, що відкотилася: агресивне уникнення стрибків на вузлах чутливих до затримки

Інша організація мала чітку політику: «Ніколи не стрибати час; лише слеїти». Розуміння звучало професійно: стрибки можуть плутати бази даних і порушувати порядок. Вони налаштували chrony так, щоб ніколи не стрибати після старту і поставили маленький поріг на початку.

Це працювало, поки частина флоту не переїхала в шумний мережевий сегмент. NTP‑пакети йшли з варіативною затримкою, і іноді зсуви перевищували секунду під час коротких провалів. Chrony робив те, що йому наказали — лише слеїв — але слеїнг з максимальною швидкістю ядра займав занадто багато часу для багатосекундних відхилень.

Застосунки не падали. Вони поводилися тонше: токени автентифікації «закінчувалися раніше», заплановані задачі дрейфували, і координація між вузлами була непослідовною. Оскільки час не стрибав, інциденти важче було помітити. Це виглядало як випадкова флака по різних системах.

Зрештою вони прийняли реалістичнішу політику: дозволяти стрибки лише в перші N оновлень після завантаження (makestep) і виправляти базову мережеву нестабільність. Правило «ніколи стрибати» стало «стрибай лише коли альтернатива — години неправильного часу». Менш «чисто», але ефективніше.

Нудна, але правильна практика, що врятувала день: затримка запуску критичних сервісів до синхронізації часу

Платформа платежів (регульована, підзвітна та алергична до сюрпризів) мала неефектне, але робоче правило: системи, що підписують токени або працюють з Kerberos, не стартують, поки синхронізація часу не підтверджена. Ніяких винятків.

Вони реалізували це через systemd: chrony стартує рано; застосунок має ExecStartPre перевірку, що чекає на chronyc tracking до нормального leap status і системної синхронізації. Також був окремий «time sanity» юніт, який відмовляє в старті, якщо годинник сильно неправильний.

Це врятувало їх під час інциденту в дата‑центрі, коли NTP‑доступність тимчасово впала під час завантаження частини хостів. Без такої затримки машини б піднялися зі старим RTC і почали видавати токени з невірними таймстемпами. З затримкою вони просто чекали. Старт був повільніший; коректність залишилася.

Було нудно. Було правильно. Це запобігло інциденту, який в іншому випадку списали б на «мережу», «Linux» або «ретроградний Меркурій», залежно від автора постмортему.

Поширені помилки: симптом → корінна причина → виправлення

1) «timedatectl каже synchronized, але час після перезавантаження все одно неправильний»

Симптом: Негайно після завантаження час відстає на хвилини; пізніше виглядає нормально.

Корінна причина: RTC неправильний, і при завантаженні система ініціалізує час з RTC. NTP коригує пізніше.

Виправлення: Переконайтеся, що RTC в UTC (/etc/adjtime), увімкніть rtcsync у chrony, виконайте hwclock --systohc --utc після стабілізації chrony, дослідіть батарейку/прошивку RTC.

2) «chrony показує доступні джерела, але відхилення ніколи не сходяться»

Симптом: chronyc sources показує reach, але RMS offset у tracking високий; частота коливається.

Корінна причина: Шумний мережевий шлях, асиметричний роутинг або проблемні upstream‑сервери; іноді локальний фаєрвол/NAT змінює UDP.

Виправлення: Використовуйте ближчі/кращі джерела, перевірте шлях UDP/123, уникайте надто агресивного опитування, розгляньте внутрішні stratum‑сервери.

3) «Годинник іноді стрибає назад/вперед; додатки логують ‘time went backwards’»

Симптом: Логи ядра або застосунків згадують зворотні стрибки; journald показує стрибки chrony поза вікном очікування.

Корінна причина: Нестабільність kernel clocksource, примусове встановлення часу гіпервізором або кілька демонов часу в боротьбі.

Виправлення: Перевірте dmesg на повідомлення watchdog для clocksource, забезпечте лише один механізм синхронізації часу, налаштуйте VM‑параметри часу, помʼякшіть шляхом вибору стабільного clocksource.

4) «Усе ок, поки VM не мігрує»

Симптом: Відхилення зростають у кореляції з міграціями або обслуговуванням хоста.

Корінна причина: Хост має неправильний час або експонує нестабільний TSC; гість бачить розриви.

Виправлення: Виправте NTP/PTP на хості, забезпечте послідовну модель CPU/invariant TSC для VM, уникайте конфліктного синхронізування часу агентами гостя.

5) «Chrony кожного завантаження робить великі стрибки»

Симптом: В journal є великий стрибок щоразу при старті.

Корінна причина: RTC не оновлюється, driftfile не персистентний або система завантажується без мережі занадто довго, і служби стартують з неправильним часом.

Виправлення: Увімкніть rtcsync, забезпечте персистентність driftfile, затримуйте запуск критичних сервісів до синхронізації.

6) «Час повільно дрейфує навіть під час роботи chrony»

Симптом: Протягом годин відхилення росте і chrony не тримає його в межах.

Корінна причина: Ядро відмовляється дисциплінувати достатньо швидко через обмеження конфігурації, clocksource нестабільний або NTP‑джерела неузгоджені.

Виправлення: Перевірте частоту і skew у chrony; підтвердіть джерела; перевірте нестабільність clocksource; розгляньте PTP, якщо потрібні тісніші межі, ніж NTP може забезпечити у вашому середовищі.

Контрольні списки / покроковий план

Покроково: виправити «NTP працює, але дрейф не зникає» на Debian 13

  1. Виберіть один демон часу.

    Використовуйте chrony на серверах; вимкніть systemd-timesyncd, якщо він присутній.

    cr0x@server:~$ sudo systemctl disable --now systemd-timesyncd
    Removed "/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service".
    

    Рішення: Якщо відключення timesyncd щось ламає — у вас були приховані залежності. Виправте їх, не вмикайте дуелі демонів.

  2. Переконайтеся, що chrony має стабільні джерела.

    cr0x@server:~$ chronyc sources -v
    ...^* ntp1.example.net ...
    

    Рішення: Якщо ви не можете досягти жодного джерела, виправте мережу/фаєрвол перед тим, як чіпати налаштування chrony.

  3. Дозвольте стрибки на ранньому етапі завантаження.

    В /etc/chrony/chrony.conf переконайтеся в наявності чогось на кшталт:

    cr0x@server:~$ sudo grep -n "^makestep" /etc/chrony/chrony.conf
    18:makestep 1.0 3

    Рішення: Якщо зсуви на старті часто > 1s, тимчасово збільшіть ліміт, поки не виправите RTC.

  4. Зробіть навчання дрейфу персистентним.

    cr0x@server:~$ sudo stat /var/lib/chrony/chrony.drift
      File: /var/lib/chrony/chrony.drift
      Size: 18        	Blocks: 8          IO Block: 4096   regular file
    Access: (0644/-rw-r--r--)  Uid: (  109/_chrony)   Gid: (  116/_chrony)
    Access: 2025-12-31 10:14:18.000000000 +0000
    Modify: 2025-12-31 10:14:18.000000000 +0000
    Change: 2025-12-31 10:14:18.000000000 +0000

    Рішення: Якщо файл не оновлюється — виправте права або персистентність (особливо в образах/контейнерах).

  5. Виправте RTC: UTC і синхронізований.

    cr0x@server:~$ cat /etc/adjtime
    0.000000 1767174612 0.000000
    0
    UTC
    cr0x@server:~$ sudo hwclock --systohc --utc
    

    Рішення: Якщо RTC продовжує швидко дрейфувати на bare metal — вирішіть це як апаратну/прошивкову проблему, а не як питання налаштування NTP.

  6. Полюйте на стрибки часу: clocksource і конфлікти VM.

    cr0x@server:~$ journalctl -k --since "today" | grep -i clocksource --no-pager | tail
    Dec 31 10:02:44 server kernel: clocksource: Switched to clocksource hpet

    Рішення: Якщо бачите нестабільність — виправте налаштування платформи (BIOS/host) і розгляньте привʼязку clocksource як помʼякшувальний захід.

  7. Затримуйте запуск критичних сервісів до синхронізації часу.

    Для систем, що підписують токени, виконують автентифікацію або координують розподілені транзакції, не запускайте їх до досягнення синхронізації. Це нудно й правильно.

Операційний чекліст для постійної безпеки

  • Щодня моніторити дельту RTC проти системного годинника на bare metal.
  • Тривожити про події стрибків chrony поза очікуваним ранньо‑завантажувальним вікном.
  • Тримати принаймні три NTP‑джерела, ідеально — у різних доменах відмов.
  • Фіксувати, чи вузол — VM чи bare metal; режими помилок часу відрізняються.
  • Під час міграцій VM корелюйте з піками відхилення, щоб довести причинно‑наслідковий звʼязок.

FAQ

1) Якщо System clock synchronized: yes, як час може бути «неправильним»?

Бо «синхронізовано» — це стан у конкретний момент і часто стосується лише системного годинника. Ваш RTC може залишатися неправильним (проблема при перезавантаженні), або ви можете мати періодичні стрибки через clocksource/гіпервізор.

2) Що обрати — systemd-timesyncd чи chrony на Debian 13?

Для серверів: chrony. Він більш діагностичний і регульований. Для мінімалістичних десктопів чи невеликих пристроїв — timesyncd може бути достатнім. Не запускайте обидва.

3) У чому різниця між stepping і slewing операційно?

Стрибок миттєво змінює wall‑clock. Slew змінює швидкість, щоб годинник поступово сходився. Стрибайте при старті, якщо сильно відстаєте. Слеїть у звичайній роботі, щоб не плутати застосунки.

4) Чи безпечно вмикати rtcsync?

На bare metal серверах — зазвичай так. Це зменшує сюрпризи при перезавантаженні. На деяких VM це може бути неважливо або контрпродуктивно, якщо гіпервізор управляє RTC.

5) Мій RTC встановлений у локальний час. Це справді проблема?

Для серверів — так. Зміни DST і оновлення правил часових поясів створюють проблеми з «локальним» RTC. Використовуйте UTC, якщо немає явної потреби в dual‑boot.

6) Чому мій годинник дрейфує більше під навантаженням?

Велике навантаження може виявити проблеми з clocksource, затримки планувальника VM і мережеву джиттерність. Chrony може впоратися з багатьма випадками, але якщо базовий годинник нестабільний або NTP‑пакети приходять із непередбачуваною затримкою, відхилення стають шумнішими.

7) Чи можна виправити постійний дрейф, частіше опитуючи NTP?

Іноді трохи допомагає; часто це лише підсилює шум. Краще мати хороші джерела і стабільний clocksource, ніж агресивне опитування. Якщо потрібна більша точність — розглядайте PTP і апаратну підтримку.

8) Чому я бачу великі стрибки при старті, навіть з chrony?

Бо початкове насіння часу (RTC) дуже далеко або driftfile не зберігається. Chrony може виправити тільки після старту і підключення до джерел; усе, що стартувало раніше, бачитиме неправильний час.

9) Як зрозуміти, що гіпервізор перевизначає час?

Шукайте стрибки часу, корельовані з міграціями або подіями хоста, і перевірте наявність агентів гостя чи налаштувань платформи, що «синхронізують час». На практиці треба прийняти рішення: час контролює хост або гість, а не обидва одночасно.

10) Яку точність варто очікувати від NTP у типовій локальній мережі?

Зазвичай — мілісекунди, іноді краще. У WAN або шумних мережах — десятки мілісекунд або гірше. Якщо потрібна субмілісекундна або мікросекундна синхронізація — це вже PTP і потрібна апаратна підтримка.

Наступні кроки, які варто зробити

  1. Вимірюйте правильні речі: відстежуйте системний зсув (chronyc tracking) і дельту RTC (hwclock --show проти date -u) окремо.
  2. Усуньте конфлікти: переконайтеся, що на кожному вузлі контролює час лише один механізм (а в VM визначте, хто контролює час — хост або гість).
  3. Зробіть старт безпечним: налаштуйте makestep для ранньої корекції і затримуйте запуск часовочутливих сервісів до підтвердження синхронізації.
  4. Зробіть RTC нудним: тримайте його в UTC, увімкніть rtcsync на bare metal і без емоцій міняйте батарейки RTC.
  5. Негайно досліджуйте попередження про clocksource: якщо ядро позначає clocksource нестабільним, ставте це як апаратну помилку з міткою часу.

Якщо ви зробите ці пʼять кроків, «NTP працює, але дрейф не зникає» перестане бути містичною історією і перетвориться на пункт чекліста. Продакшн любить нудність. Час має бути агресивно нудним.

← Попередня
Контроль доступу офісного VPN: дозволяйте лише необхідне (не мережа‑до‑мережі)
Наступна →
ZFS ashift: Тиха невідповідність, яка скорочує продуктивність удвічі

Залишити коментар