Коротко. Кластер из трёх нод был здоров по GUI: узлы ONLINE, службы работают, внутренние запросы с самой ноды проходят 200 OK. При этом ни один внешний S3-клиент не мог получить листинг: шлюз отвечал 403, подпись отклонялась. Причина — системные часы одной ноды отстали на 23 ч 44 мин, а подпись S3 действует в окне ±15 мин. Починка — вернуть ntpd на штатный конфиг и убрать источник подмены конфига; после этого 403 исчезли без переустановки.
Симптом
Как это выглядело у оператора:
- S3-клиент (командная строка, бэкап-агент) на любой запрос получал:
403 Forbidden — The difference between the request time and the current time is too large. - Листинг бакетов не проходил вообще, PUT/GET — тоже; поведение одинаковое у всех клиентов сразу, на разных площадках клиента.
- GUI управления открывается, узлы зелёные. В модели все три ноды
ONLINE, событий про диск, сеть или службы нет. Привычные ошибки по задачам — те же, что были и раньше. - Внутренние проверки с самой ноды (
curlк локальному эндпоинту) отвечают200.
Ключевое противоречие: статус узла в модели не показывает время, поэтому «зелёный GUI» не означает «S3 работает для клиента».
Что проверить первым (read-only)
-
Время и синхронизация на каждой ноде:
bash date -u timedatectl | grep -i synchronized ntpq -pОжидается: одинаковое UTC на всех нодах,System clock synchronized: yes, вntpq -pесть строка с*(сейчас выбранный источник) и стратум < 16. Пустойntpq -pилиst= 16 — нет рабочего источника. -
С каким конфигом запущен
ntpd:bash ps -ef | grep "[n]tpd"Ожидается запуск с/etc/ntp.conf. Если в аргументах видно-c /run/ntp.conf.dhcp, демон читает конфиг, сгенерированный DHCP-хуком, — там нет кластерных peer'ов. -
Следы DHCP-хука на провижиненной ноде:
bash ls -l /run/ntp.conf.dhcp ps -ef | grep "[d]hclient" systemctl is-enabled marvin-dhcp.service; systemctl is-active marvin-dhcp.serviceОжидается: файла нет,dhclientне запущен, службаdisabledиinactive. Наличие любого из трёх — повод разбираться. -
Что видит клиент снаружи: фронт отвечает и на
307/200с заголовкомServer: Quantum-ActiveScale, но конкретный подписанный запрос —403. Разделять «фронт жив» и «подпись принята». -
Разброс часов между нодами — сравнить
date -uтрёх нод. Расхождение больше секунды — аномалия; расхождение в минуты/часы — это и есть причина 403.
Причина
Механизм: окно подписи
S3-подпись (SigV4) включает дату и время запроса в подписываемую строку. Шлюз принимает запрос,
только если время подписи отличается от собственного времени шлюза не более чем на 15 минут
(стандартное поведение S3-совместимых реализаций). При выходе за окно шлюз обязан ответить 403
с формулировкой про разницу времени — это не ошибка прав и не ошибка ключей.
В кейсе часы ноды отстали на 23 ч 44 мин. Отсюда:
- любой внешний подписанный запрос —
403; - внутренние запросы с самой ноды, которые идут по локальному адресу и подписываются тем же локальным временем, проходят: клиент и шлюз «согласны» друг с другом, обе стороны ошибаются одинаково;
- модель видит узел живым (
ONLINE), heartbeat и внутренние вызовы работают. Время узла в статусе не инспектируется.
Как потерялся контроль времени
Причина здесь — не аппаратные часы: RTC (батарейные часы платы) были верны, ошибка была только в системном времени. Механика — наша, от правки установочного образа:
- Патч
marvin-dhcp.serviceдержитdhclientна сетевом порту без линка — «фантомный» DHCP-клиент. - Каждые 300 с он продлевает аренду, а стоковый хук Ubuntu при продлении пишет
/run/ntp.conf.dhcpи перезапускаетntpdс этим конфигом. - В сгенерированном конфиге нет кластерных peer'ов —
ntpdтеряет синхронизацию с соседними нодами и остаётся на внешнем источнике, которого в сегменте нет. - Служба была включена только на одной ноде — поэтому проблема была локальной: две другие держали время правильно, а шлюз на «уехавшей» ноде отклонял всё.
Что доказано, а что нет. Подмена конфига и отставание часов доказаны прямыми выводами
(ps с -c /run/ntp.conf.dhcp, date -u против соседей, возврат времени после остановки
ntp). Точный момент и источник скачка часов по журналам восстановить не удалось — журнал
на этой ноде был пуст. Поэтому «сбой внешнего NTP-сервера» мы не объявляем: причиной считается
отсутствие синхронизации с кластером, а не конкретное событие.
Решение (штатное)
-
Остановить
ntpd, убрать конфиг от DHCP, запустить снова — на ноде с уехавшим временем:bash sudo systemctl stop ntp sudo rm -f /run/ntp.conf.dhcp sudo systemctl start ntpПроверить:date -u,timedatectl | grep synchronized,ntpq -p— есть*, стратум < 16. В кейсе после этого стратум был2, offset около0.2 мс. -
Убедиться, что проблема не вернётся через 5 минут. Подмена возвращалась на каждой аренде, поэтому удалить файл недостаточно. По отмашке оператора на всех нодах:
bash sudo systemctl stop marvin-dhcp.service sudo systemctl disable marvin-dhcp.serviceУбедиться, что фантомныйdhclientснят (вместе с cgroup службы). -
Вернуть
ntpdна вендорский/etc/ntp.confи проверить, что вntpq -pснова видны кластерные peer'ы — соседние ноды, а не только внешний источник. -
Поставить исправленный DHCP-скрипт с защитой (
marvin-dhcp.shиз нашего образа): даже случайное включение службы на провижиненной ноде больше не подменяет конфиг NTP. Старую версию сохранить вне каталога продукта. -
Контроль через 4 минуты (один период аренды):
dhclient— 0 процессов,/run/ntp.conf.dhcpотсутствует,date -uверный, листинг бакетов клиентом — OK.
Если штатный путь недоступен
Если доступа к службе нет или перезапуск ntpd запрещён в окне обслуживания — временная мера,
не штатно: разово выставить время с соседней ноды
(sudo date -u -s "$(ssh <USER>@<NODE_IP> date -u +%Y-%m-%dT%H:%M:%SZ)") и немедленно открыть
заявку на штатную правку NTP. Пометка обязательна: это маскирует симптом, но не убирает источник
подмены — часы уедут снова на следующем цикле аренды, а date -s без синхронизации даст дрейф.
Проверить причину и закрыть её в тот же день.
Проверка
| Что | Ожидаемое значение |
|---|---|
date -u на всех нодах |
совпадает до секунды |
timedatectl |
synchronized: yes |
ntpq -p |
источник с *, st ≤ 3, offset — единицы миллисекунд |
ps -ef \| grep ntpd |
запуск с /etc/ntp.conf, без -c /run/ntp.conf.dhcp |
/run/ntp.conf.dhcp |
файла нет |
dhclient |
0 процессов |
marvin-dhcp.service |
inactive, disabled |
| S3 листинг бакета клиентом | 200 (не 403) |
| События | нет новых WARNING/CRITICAL про NTP или службы |
Отдельно: сравнение date -u против RTC (hwclock --show) — расхождение означает, что системное
время рассинхронизировано с платой, а не что плата сломана.
Профилактика
- NTP — не «настройка по умолчанию», а кластерный механизм.
ntpdдолжен ходить к peer'ам соседних нод; внешние источники — дополнение, а не единственный путь. - Не оставлять работающий DHCP в mgmt-сегменте после провижина.
marvin-dhcp(или его аналог) на провижиненной ноде —disabled; скрипт — с защитой от подмены конфига. - Добавить время в полевой health-check. Наш
as-field-health.shза ~30 секунд проверяет: синхронизацию, отсутствие-c /run/ntp.conf.dhcp, отсутствиеdhclientи/run/ntp.conf.dhcp, выключенность службы, разброс часов между нодами — и это вышло прямо из этого кейса. - S3-мониторинг делать снаружи. Проверка «листинг бакета подписанным запросом» раз в несколько минут ловит 403 от расхождения часов раньше, чем клиент напишет в поддержку. Внутренние проверки с самой ноды эту проблему не видят по устройству.
- Регламент: время и NTP — в чек-лист еженедельного обслуживания, подробности — в регламенте обслуживания и статье про NTP.
Источники и дата
- Вендор: Управление системой (GUI) (доступ 2026-11-07)
- Вендор: Software Documentation Center (доступ 2026-11-07)
- Наша практика: обезличенный разбор — 3-нодный кластер, отставание одной ноды 23 ч 44 мин, RTC при этом верный; окно подписи ±15 мин.
- Обновлено: 2026-11-07.