ADG Оставить заявку
Блог Автоматизация 4 мин чтения

Ansible 5.2 и обновление коллекций: фиксируем зависимости в AWX и перестаём бояться CI

Обновили ansible-core и набор коллекций в AWX-кластере до Ansible 5.2. Разбираем, как зафиксировать версии коллекций в requirements.yml и не получить сюрпризов в CI.

Контекст момента

Ansible 5.x (community): регулярные выпуски коллекций, community.general и ansible.posix обновления

Ansible 5.2 вышел в конце января, и на прошлой неделе мы прокатили обновление на AWX-кластер - сначала в staging-окружении, потом в prod. Заодно разобрались с накопившимися расхождениями в версиях коллекций между проектами. Рассказываем что было, что поправили и почему requirements.yml с плавающими версиями - это тихая мина.

Что изменилось в 5.2

Ansible 5.x строится на ansible-core 2.12, и в 5.2 основная активность - в коллекциях, а не в ядре. Из заметного:

  • community.general добрался до 4.3.x в составе пакета. Несколько модулей получили новые параметры, один устаревший alias убрали без особых анонсов в changelog верхнего уровня.
  • ansible.posix перешёл на 1.3.x - изменения в ansible.posix.sysctl и ansible.posix.firewalld, в основном расширение параметров.
  • ansible-core 2.12 ужесточил работу с collections_paths и стал строже к FQCN в некоторых контекстах, где раньше молча прощал короткие имена.

Всё это звучит управляемо - до первого взгляда в requirements.yml, где написано version: ">=4.0.0".

Как мы получили сюрприз

После обновления AWX один из клиентских проектов упал на стадии синхронизации коллекций. Причина нашлась быстро: в requirements.yml проекта стояло community.general: ">=3.0.0", AWX при синхронизации честно скачал последнюю доступную версию - 4.4.x. А там один из модулей, который использовался в плейбуке, слегка поменял имя обязательного параметра. Не breaking change в классическом смысле - параметр остался, просто старое имя стало deprecated, а поведение при его использовании без явного указания нового изменилось.

Итог: плейбук, который работал без изменений три месяца, упал в CI с невнятным сообщением об ошибке в параметрах задачи.

Это знакомая история - летом прошлого года мы уже наступали на этот же камень при переходе на Ansible 4.0. Тогда сделали вывод, зафиксировали версии в нескольких проектах. Но не во всех. Теперь зафиксировали в оставшихся.

Как зафиксировать зависимости правильно

Принцип простой: версии коллекций в requirements.yml должны быть пиннингом, а не диапазоном. == вместо >=. Обновление - осознанное действие, а не побочный эффект синхронизации проекта в AWX.

Рабочая структура collections/requirements.yml, к которой мы сейчас пришли:

collections:
  - name: ansible.posix
    version: "==1.3.0"
  - name: community.general
    version: "==4.4.0"
  - name: community.crypto
    version: "==2.1.0"
  - name: community.postgresql
    version: "==1.7.0"
  - name: ansible.windows
    version: "==1.9.0"
  - name: community.windows
    version: "==1.8.0"

Файл хранится в git, обновляется отдельным коммитом с явным описанием что именно и зачем. При следующей синхронизации AWX берёт ровно то, что написано, - никаких неожиданностей.

Несколько практических наблюдений из этого обновления:

Первое - ansible.posix стоит выделять явно. В некоторых старых проектах он не был указан в requirements.yml вообще - просто подтягивался транзитивно через основной пакет ansible. После обновления AWX это поведение стало менее предсказуемым. Лучше прописывать явно, версию - фиксировать.

Второе - changelog коллекций надо читать отдельно. Release notes к Ansible 5.2 как пакету перечисляют только самое важное. Реальные изменения в community.general живут в changelog самой коллекции на GitHub. Перед обновлением версии коллекции в requirements.yml стоит пробежаться по CHANGELOG.rst - обычно это пять минут, которые сохраняют час отладки потом.

Третье - staging обязателен, но недостаточен. У нас есть staging-AWX, и мы катим туда изменения первыми. Но staging воспроизводит только те плейбуки, которые запускаются регулярно. Плейбук «разворачивает новый сервер с нуля» запускается редко - и именно он сломался в prod, потому что в staging его просто не прогоняли при обновлении.

Проверка после обновления

После каждого обновления коллекций мы прогоняем минимальный чек-лист:

  • ansible-galaxy collection list - убеждаемся что установлены именно зафиксированные версии
  • ansible-lint по ключевым ролям - ловим предупреждения о deprecated параметрах
  • dry-run плейбуков (там где есть --check режим) - смотрим что plan не падает с ошибкой модуля

Последний пункт звучит очевидно, но на практике его легко пропустить когда обновление выглядит «просто минорным». community.general 4.4.0 от 4.3.0 - это минорная версия, какие там могут быть проблемы. Могут.

Где сейчас

После фиксации версий во всех проектах картина стала заметно спокойнее. AWX-синхронизации предсказуемы, CI не преподносит сюрпризов по субботам. Обновление до следующей версии коллекции - теперь маленький, но явный ритуал: посмотреть changelog, обновить версию в requirements.yml, прогнать в staging, закоммитить.

Для managed-сопровождения это важно особенно: клиент не должен узнавать об изменениях в Ansible-коллекциях через внезапно сломанный деплой в пятницу вечером. Версионирование в requirements.yml - простой способ держать этот класс проблем под контролем.

Ansible 5.x в целом работает стабильно. ansible-core 2.12 пока никаких неожиданностей не принёс. Следующее плановое обновление - когда выйдет 5.3, смотрим на changelog коллекций заранее.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.