Патч-менеджмент на Linux в масштабе: как yum-cron избавил нас от просроченных серверов
Аудит показал: треть Linux-серверов не обновлялась больше полугода. Ручной процесс не масштабируется. Настроили yum-cron в режиме security-only на всём парке CentOS 5.
yum-cron для автоматического обновления систем на RHEL/CentOS входит в стандартные практики в 2007 году
Всё началось с аудита, который мы провели в октябре. Хотели зафиксировать состояние парка после летней миграции на CentOS 5 - сколько серверов живёт, что на них крутится, как обстоит дело с обновлениями. Картина по обновлениям вышла неудобная: примерно треть машин не получала апдейтов дольше полугода. Некоторые - дольше года.
Формально процесс существовал: есть ответственный за каждую группу серверов, есть регламент «проверять обновления раз в месяц». На практике это означало - никто не проверяет, пока не случается что-то конкретное. Ручной процесс в таком виде не работает: когда серверов десяток, ещё можно удерживать в голове, когда их несколько десятков - нет.
Почему это вообще проблема
Непропатченные серверы - это не абстрактный риск. В августе мы мигрировали на CentOS 5, в октябре разбирались с SELinux-политиками. Параллельно через списки рассылки приходили уведомления RHEL о критических CVE в ядре, openssl, glibc. Некоторые из этих уязвимостей были закрыты патчем через несколько дней после публичного раскрытия - но только на тех серверах, где обновления реально ставились.
Остальные просто ждали. Неизвестно чего.
Что такое yum-cron
В RHEL 5 / CentOS 5 в комплекте идёт пакет yum-cron - это, по сути, обёртка над yum с cron-расписанием и несколькими режимами работы. Устанавливается стандартно:
yum install yum-cron
Ключевой параметр в /etc/sysconfig/yum-cron - CHECK_ONLY. Если CHECK_ONLY=yes, демон только проверяет и пишет в лог что доступно, но ничего не ставит. Если no - ставит автоматически.
Есть ещё SECURITY_ONLY - при yes обновляются только пакеты, для которых в yum-updateinfo есть метка security. Red Hat маркирует критические обновления именно так, и на CentOS это работает через зеркала updateinfo.
Что мы в итоге настроили
После обсуждения в команде пришли к двухрежимной схеме:
- Security-only автоматически.
SECURITY_ONLY=yes,CHECK_ONLY=no- критические патчи безопасности ставятся без участия человека каждую ночь в 3:00. Перезагрузка не производится - если патч требует ребута (новое ядро), сервер остаётся на старом ядре до следующего обслуживания. - Все остальные обновления - в окно. Каждую субботу в 01:00 запускается полный
yum updateбез фильтра. Только на машинах, для которых согласовано окно обслуживания. Тут уже может поменяться что угодно, и мы хотим знать об этом заранее.
На продакшн-серверах, где обновление пакетов может сломать что-то в приложении, CHECK_ONLY=yes с почтовым уведомлением - человек смотрит что предлагается и принимает решение. Автоматической установки нет.
Получилось три класса:
Класс A - инфраструктурные серверы (DNS, NTP, syslog, мониторинг)
security-only: автомат
всё остальное: окно по субботам
Класс B - продакшн-приложения
security-only: check_only + уведомление
всё остальное: ручное, по согласованию
Класс C - тестовые и внутренние машины
всё: автомат по ночам
Уведомления и контроль
yum-cron умеет отправлять письма через MAILTO в конфиге. На каждое автоматическое обновление приходит письмо с перечнем того, что было установлено - или пустое письмо если ставить было нечего. Это важно: тишина должна означать «ничего нового», а не «что-то сломалось и молчит».
В Zabbix добавили проверку - агент раз в сутки запускает yum check-update и пишет количество доступных обновлений в метрику. Если значение больше нуля держится дольше трёх дней на машине класса A - триггер. Смотрим почему не поставилось.
Что пошло не так при первом прогоне
На нескольких серверах первый автоматический прогон завис на интерактивном prompt - yum просил подтвердить импорт GPG-ключа репозитория. В cron-режиме нет TTY, и процесс просто висел до таймаута.
Лечится флагом --nogpgcheck или предварительным импортом ключа через rpm --import. Мы выбрали второе - импортировали ключи явно при первичной настройке серверов. Это надёжнее.
Ещё один нюанс: на паре машин в /etc/yum.conf был выставлен exclude=kernel* - кто-то когда-то зафиксировал ядро вручную и забыл. yum-cron это уважает, патчи ядра туда не приходили. Нашли только когда проверяли лог вручную.
Где мы сейчас
Схема работает несколько недель. Количество серверов с нулевыми pending security updates растёт - не потому что мы каждый день садимся и обновляем руками, а потому что процесс идёт сам. Именно так и должно быть.
Открытый вопрос - что делать с перезагрузками после обновления ядра. Автоматический ребут в 3 ночи звучит опасно даже для инфраструктурных машин. Пока фиксируем в мониторинге «ядро обновлено, требуется ребут» и выполняем в ближайшее окно вручную. Не идеально, зато без сюрпризов.
Это один из рабочих процессов, которые мы выстраиваем в рамках сопровождения серверной инфраструктуры: убрать человека из петель, где человек - слабое звено, и оставить его там, где нужно реальное решение.