惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
罗磊的独立博客
小众软件
小众软件
T
Tailwind CSS Blog
宝玉的分享
宝玉的分享
博客园_首页
N
Netflix TechBlog - Medium
B
Blog
Recent Announcements
Recent Announcements
Y
Y Combinator Blog
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
F
Fortinet All Blogs
The GitHub Blog
The GitHub Blog
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
Jina AI
Jina AI
V
V2EX
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
博客园 - 【当耐特】

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания
Автообновления Linux: почему сервер моргает по утрам, а к...
sh112 · 2026-06-25 · via Все публикации подряд на Хабре

Средний

8 мин

71

Автообновления Linux: почему сервер моргает по утрам, а кластер теряет кворум

⚠️ Ахтунг: тут пробегал ИИ.

💡 Не все знали, но всё это время: Ubuntu Server и Debian устанавливают security-обновления автоматически и по умолчанию. Если на серверной инсталляции ничего специально не отключали — этот механизм уже работает прямо сейчас.

У одного и того же механизма — пакетных автообновлений — два типичных артефакта в эксплуатации.

На одиночном сервере — сервис «моргает» утрами. По журналу видно, что в 06:xx или около того он был остановлен и сразу же запущен, причиной никто конкретно не назначен, и админ месяцами ищет «плавающий ночной даунтайм», списывая его то на сеть, то на GC.

На кластере из трёх–пяти узлов — кластер устроен правильно с точки зрения избыточности, переживает падение одного узла, и в какой-то момент сам себя роняет: на всех узлах в одно и то же утро прилетело обновление с перезапуском сервиса. Кворума не осталось, клиент видит «недоступно».

Источник у обоих один. Разберём.

Откуда вообще приходят автообновления

Debian / Ubuntu — unattended-upgrades

В Ubuntu 24.04 и Debian 12 пакет unattended-upgrades устанавливается по умолчанию и включён, как минимум для канала security. Раскладка такая:

  • /etc/apt/apt.conf.d/20auto-upgrades — общий рубильник: включено ли вообще автоматическое обновление и нужно ли каждый день делать apt update.

  • /etc/apt/apt.conf.d/50unattended-upgrades — политика: какие репозитории трогать (Origins-Pattern), какие пакеты исключить (Package-Blacklist), писать ли отчёт на почту, разрешать ли автоматическую перезагрузку хоста (Automatic-Reboot).

Сам процесс запускается двумя systemd-таймерами:

  • apt-daily.timer — обновляет индекс пакетов и скачивает то, что разрешено. Срабатывает дважды в сутки, со случайной задержкой до 12 часов.

  • apt-daily-upgrade.timer — собственно ставит обновления. По умолчанию OnCalendar=*-*-* 6:00 с RandomizedDelaySec=60m.

Здесь уже видна потенциальная ловушка: окно установки — один час после шести утра, плюс-минус секундное распределение. У вас три одинаково настроенных узла — все три попали в это окно. Если для двух из них таймер случайно выпал в один и тот же 10-минутный интервал — обновление пакета с вашим сервисом запустилось на обоих почти синхронно.

Fedora и RedOS — dnf-automatic

В семействе RPM есть свой аналог: пакет dnf-automatic. В отличие от Debian-семейства, он не установлен по умолчанию ни в Fedora, ни в RedOS — администратор включает его сознательно:

sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timer

Конфигурация — в /etc/dnf/automatic.conf. Ключевые поля:

  • download_updates — скачивать ли заранее.

  • apply_updates — устанавливать или только скачать (по умолчанию no — то есть «только скачать», но это часто меняют).

  • upgrade_type — default (всё) или security (только security-канал).

Триггер — таймер dnf-automatic.timer. По умолчанию OnCalendar=*-*-* 6:00 с RandomizedDelaySec=1h. Та же узкая одночасовая полоса, что и в Ubuntu, та же проблема для кластера.

В RedOS Murom 7.x используется тот же dnf-automatic. Семантически ничего нового.

Что происходит при обновлении пакета

Допустим, в репозиторий вышла новая версия пакета, в нём — бинарь сервиса с systemd-юнитом. Дальше пакетный менеджер делает следующее:

  1. Распаковывает новый бинарь поверх старого.

  2. Запускает скриптлеты пакета (postinst в .deb%post / %posttrans в .rpm). Посмотреть их можно через dpkg -e или rpm -q --scripts <pkg>.

  3. В типовом случае postinstall дёргает systemctl daemon-reload, а дальше — systemctl try-restart <service> или restart, если юнит был запущен. Точная команда зависит от того, как пакет собрали: dh_installsystemd в Debian-семействе по умолчанию делает перезапуск; в RPM это решение мейнтейнера.

  4. В Ubuntu 22.04+ поверх этого работает ещё needrestart: он сканирует все процессы в системе и через /proc/PID/maps находит те, у которых обновлённый (а на самом деле — уже удалённый из файловой системы и заменённый новым) исполняемый файл или библиотека остались примонтированными в адресное пространство. Такие процессы он помечает к перезапуску.

Важная деталь: перезапуск касается не только сервиса, чей пакет обновился. Если в очередное unattended-upgrade попал security-фикс на популярную системную библиотеку — libssl3libcurl4libsystemd0libc6zlib1g — за ней перезапустится всё, что с ней динамически слинкованоnginxpostgresqlsshdredis, ваши собственные демоны. На практике это самая частая причина «кластер падает раз в две недели по непонятной причине»: обновляется не сам сервис, а маленький пакет в его транзитивных зависимостях.

Посмотреть, кто что держит:

sudo needrestart -b           # сводный список того,
                              # что собирается перезапустить
sudo lsof | grep '(deleted)'  # процессы с уже удалёнными
                              # файлами в адресном пространстве

Поведение needrestart в неинтерактивном режиме (то есть в unattended-upgrades) задаётся в /etc/needrestart/needrestart.conf ключом $nrconf{restart}:

  • 'a' — перезапускать всё автоматически (типовая настройка в Ubuntu Server по умолчанию);

  • 'i' — спрашивать у пользователя (на сервере без TTY означает «не перезапускать»);

  • 'l' — только записать список в журнал, ничего не трогать.

Заодно полезно знать: статически слинкованные бинари (Go с CGO_ENABLED=0, Rust с musl-target, нативные с -static) от обновления системных библиотек не страдают — у их процессов в /proc/PID/maps нет внешних .so, и needrestart их не трогает.

Итог: внутри одного apt upgrade или dnf upgrade ваш сервис — и не один он — действительно может быть перезапущен. Без вашего вмешательства, без уведомления и одновременно с обновлением на других узлах того же кластера.

Артефакт 1: одиночный сервер моргает по утрам

Одиночный сервер. На нём крутится сервис: веб-приложение, прокси, база, брокер очередей — не важно. Жалоба от пользователей или из мониторинга: «каждое утро около шести сервис недоступен 10–30 секунд». В течение дня — никаких проблем. Утром — повторяется.

Это не утечка памяти, не GC-пауза, не сетевой провал и не зависание после первой большой нагрузки. Скорее всего это автообновление какого-то пакета, в чьих транзитивных зависимостях оказался ваш сервис или одна из его системных библиотек.

Проверить за две минуты:

# Что вообще запускалось ночью?
sudo journalctl -u apt-daily-upgrade.service --since "7 days ago"
sudo journalctl -u dnf-automatic.service --since "7 days ago"

# Что обновлялось — список пакетов с временем
sudo tail -n 200 /var/log/apt/history.log
sudo tail -n 200 /var/log/dnf.log

# Перезапускался ли ваш сервис в эти же моменты?
sudo journalctl -u <ваш-сервис>.service --since "7 days ago" \
    | grep -E "Stopping|Started|Stopped"

Если временные метки совпадают — диагноз подтверждён. Дальше варианты:

  • Принять. Если сессии переподключаются автоматически и пользователь это не замечает — пусть моргает; зато безопасность накатывается сама.

  • Разнести по времени (см. ниже), чтобы окно обновления было не во время бизнес-часов и не в одинаковое время каждый день.

  • Запретить трогать конкретный пакет: добавить его в Package-Blacklist в /etc/apt/apt.conf.d/50unattended-upgrades или в exclude= в /etc/dnf/automatic.conf. Сервис не будет обновляться вообще, перезапусков не будет — но и security-фиксов не будет; принимаемое решение.

  • Запретить автоматический перезапуск сервисов через needrestart в режиме «только список» (см. ниже) — обновлять пакеты можно, но рестарт делает админ или CI.

Артефакт 2: кластер теряет большинство по совпадению окон

Простой счёт. Допустим:

  • Три узла кластера, одинаково настроенные.

  • Стандартный таймер apt-daily-upgrade.timer с RandomizedDelaySec=60m. Распределение равномерное по 60-минутному окну.

  • Обновление пакета сервиса занимает 20 секунд, перезапуск — ещё 5–10.

Вероятность того, что два узла из трёх попадут в окно перекрытия в 30 секунд — порядка 1,5–2 % на одно ночное обновление. На дистанции в год это срабатывает примерно раз. На пяти узлах — уже заметно чаще; и достаточно одного раза, чтобы кластер на короткое время потерял большинство и оборвал текущие сессии.

Если ваше приложение допускает потерю одного узла, но не двух одновременно (типовая ситуация для систем с кворумом — Raft, Paxos, большинство брокеров с N+1 резервом), это проблема обнаружения: вы её увидите как редкие, плохо воспроизводимые «ночные провалы» доступности.

Как разнести во времени

Идея простая: расписание автообновления не должно быть одинаковым на всех узлах. Дальше вопрос — насколько системно вы это разносите.

Минимум: разный OnCalendar на каждом узле

На каждом узле кластера переопределяете таймер локальным drop-in:

sudo systemctl edit apt-daily-upgrade.timer

Содержимое drop-in для первого узла:

[Timer]
OnCalendar=
OnCalendar=*-*-* 03:00
RandomizedDelaySec=10m

Для второго:

[Timer]
OnCalendar=
OnCalendar=*-*-* 05:00
RandomizedDelaySec=10m

И так далее. Пустая OnCalendar= обязательна — она сбрасывает значение из юнита, заданное по умолчанию, иначе расписаний будет два. Применить:

sudo systemctl daemon-reload
sudo systemctl restart apt-daily-upgrade.timer
sudo systemctl list-timers --all | grep apt-daily-upgrade

Для dnf-automatic.timer всё то же самое, имя только другое: systemctl edit dnf-automatic.timer.

Получше: убрать автоматический перезапуск сервиса

Если вы не хотите, чтобы пакетное обновление трогало ваш сервис в принципе — даже если бинарь обновился — можно настроить needrestart в режиме «только список, без действий»:

sudo $EDITOR /etc/needrestart/needrestart.conf
# $nrconf{restart} = 'l';   # list only

В режиме l он только запишет в журнал, какие сервисы следовало бы перезапустить — и оставит решение администратору.

Для Debian/Ubuntu без needrestart можно временно блокировать запуск сервисов через policy-rc.d:

sudo install -m 0755 /dev/stdin /usr/sbin/policy-rc.d <<'EOF'
#!/bin/sh
exit 101
EOF

exit 101 означает «действие не разрешено» — dh_installsystemd это понимает и перезапуск не выполняет. Сервис при этом продолжит работать со старым бинарём, пока вы не перезапустите его вручную. На системах с настроенными Linux capabilities и долго живущими подключениями это часто как раз то, что нужно — перезапуск делает дежурный или CI.

Серьёзно: координация через внешний инструмент

Когда узлов много или они в нескольких регионах — разные OnCalendar становятся хрупкими (легко забыть один при добавлении). Тогда нужна координация уровнем выше пакетного менеджера:

  • Ansible с serial: 1 (или serial: "30%") — обновляет кластер по одному, с проверкой работоспособности между шагами;

  • Kubernetes через PodDisruptionBudget и rolling-update — гарантирует, что одновременно недоступно не более N узлов;

  • Salt orchestrate / Chef runlist — то же.

Автообновление пакета при этом обычно отключают совсем:

# Debian/Ubuntu
sudo systemctl disable --now apt-daily-upgrade.timer
# Fedora/RedOS
sudo systemctl disable --now dnf-automatic.timer

И полагаются на оркестратор, у которого есть карта кластера и понимание кворума.

На первый взгляд кажется лишней суетой ради «всё равно когда обновится» — но цена разъехавшегося NAS, ушедшего в split-brain посреди ночи, обычно сильно выше, чем час, разово потраченный на правильный конфиг расписания и перезапусков.


Оригинал статьи — с подсветкой кода и актуальной версией текста — лежит в блоге: ololo.tech/articles/sysadmin/auto-updates-cluster.