CentOS 8 в продакшне: первые недели с DNF, модулями и Ansible-ролями
Развернули первые продакшн-серверы на CentOS 8. DNF заметно быстрее, но modules/streams ломают привычные Ansible-роли - перестраиваем шаблоны.
CentOS 8.0 вышел в сентябре 2019; сообщество делится первым опытом с DNF, AppStream-модулями и SELinux enforcing в продакшн-окружениях
Прошло около трёх недель с того момента, как мы подняли первые продакшн-серверы на CentOS 8. Не тестовые стенды - реальные машины в managed-инфраструктуре. Пришло время зафиксировать что реально поменялось в повседневной работе, а не в release notes.
Коротко: работает нормально. Но процесс обслуживания в нескольких местах стал другим, и к этому надо привыкать.
DNF: быстрее - это не просто ощущение
На тестовом стенде скорость DNF против YUM была заметна, но не критична. На продакшн-машинах с более тяжёлыми зависимостями разница чётче. dnf install с типичным набором пакетов отрабатывает ощутимо быстрее - особенно стадия разрешения зависимостей, которая на YUM с длинным списком репозиториев иногда уходила в раздумья на полминуты и больше.
История с yum как симлинком на dnf работает без сюрпризов. Команды совместимы, привычные флаги не ломаются. Но в плейбуках мы начали явно переходить на модуль dnf - не потому что yum сломался, а потому что dnf даёт доступ к управлению модулями, а yum - нет.
Модули на практике: где сломалось
Тестовый стенд мы гоняли в сентябре и уже понимали, что AppStream меняет контракт. Но одно дело - знать, другое - столкнуться под боевой нагрузкой.
Первое, что сломалось: роль для nginx. Она была написана под CentOS 7 и делала простой yum: name=nginx. На восьмёрке nginx есть в AppStream, но поток по умолчанию - 1.14. Нам нужен был 1.16. Роль отработала, поставила 1.14, и никаких предупреждений не выдала. Хорошо что сразу проверяем версии после деплоя - иначе жили бы с не той версией непонятно сколько.
Второе - роль для PHP, где мы прошлый раз использовали yum-priorities и Webtatic-репозиторий для PHP 7.2/7.3. На CentOS 8 Webtatic пока не имеет совместимых сборок. PHP идёт через AppStream, потоки 7.2 и 7.3 там есть, это хорошо. Но привычная механика yum-priorities исчезла - приоритеты репозиториев в DNF работают через другой механизм, и старые priority= в .repo-файлах просто игнорируются. Это не падение, это тихая смена поведения, которая хуже - всё работает, но не так как думаешь.
Третье - dnf module и идемпотентность. В Ansible, когда роль запускается повторно, нужна идемпотентность: второй прогон не должен ничего менять, если первый прошёл успешно. С модулями это работает, но надо аккуратно прописывать состояние. Если написать state: enabled для потока который уже включён - ок, ошибки нет. Но если написать state: present для пакета без явного указания потока - DNF может взять другой поток при повторном запуске на чистой машине. Не падение, но сюрприз в специфичных случаях.
Как перестраиваем роли
На текущий момент у нас три подхода в зависимости от роли.
Для простых ролей (один пакет, один поток): добавляем явную задачу dnf module enable <module>:<stream> перед установкой пакетов. Синтаксис @module:stream в имени пакета тоже работает, но мы предпочитаем явный шаг - понятнее при ревью.
Для ролей с несколькими пакетами из одного модуля: группируем установку через профили AppStream где они есть. Например, @php:7.3/common ставит базовый профиль PHP 7.3 одной командой. Если профиль не подходит - явный список пакетов, но с обязательным enable потока до установки.
Для унаследованных ролей, где переписать быстро не получается: временный костыль - явно добавить нужный .repo-файл для тех пакетов, у которых нет AppStream-аналога. Это не решение, это заглушка до нормального рефакторинга.
Про yum-priorities и приоритеты репозиториев: в DNF есть плагин dnf-plugin-priorities, он понимает директиву priority= в .repo-файлах. Но его нужно явно поставить - dnf install dnf-plugin-priorities. На CentOS 7 он был частью yum-plugin-priorities, который ставился сам. Добавили установку плагина в базовую роль bootstrap.
SELinux: без сюрпризов, но с работой
Писали ещё в сентябре что SELinux enforcing - это ожидаемо. Держим его включённым, не выключаем. Но первые две недели periodically прилетало что-нибудь в /var/log/audit/audit.log от сервисов, которые деплоились с CentOS 7-шаблонов.
Типичный случай: rsync для резервного копирования читает файлы из директории, которая на CentOS 7 не требовала особой метки, а на CentOS 8 нужна метка backup_t или var_t в зависимости от контекста. audit2allow выдаёт конкретный модуль, но мы пошли по другому пути - добавляем semanage fcontext в роль, чтобы метка проставлялась как часть деплоя, а не вручную после инцидента.
Хорошая новость: audit2why на CentOS 8 стал чуть информативнее - не просто показывает что запрещено, но и иногда подсказывает какой boolean нужно включить. Мелочь, но полезно.
Где мы сейчас
Три продакшн-сервера на CentOS 8 работают стабильно. Роли переписаны примерно на треть - те, которые затронули реальные деплои. Остальные перепишем по мере использования, не ради галочки.
Главный вывод этих трёх недель: CentOS 8 - это не «тот же CentOS только новее». Это другая механика работы с пакетами, и если заходить с CentOS 7-рефлексами - будут тихие несоответствия. Не критические, но неприятные. Хорошо что у нас под рукой аудит плейбуков сделан ещё летом - иначе копались бы дольше.
- CentOS 8 вышел: разворачиваем тестовый стенд и разбираемся с AppStream на практике · 24 сентября 2019
- 80+ серверов с CentOS 6: составляем дорожную карту миграции на CentOS 8 · 30 сентября 2019