Комментарии 15
Идемпотентность — ключевое требование к Ansible-ролям.
Система после каждого запуска должна приходить в одинаковое состояние
Расскажите, как это выглядит на практике. Допустим, в версии 1 роль делала apt-get install libfoo. В версии 2 роли libfoo больше не нужна и она перестала делать apt-get install. Вопрос. Как привести машины, на которых ранее прогонялась версия 1, в одинаковое состояние с машинами, на которых сразу выполняли версию 2? Удалять в роли пакет? Нельзя, может он другим ролям нужен, не?
Добавить libfoo в эти самые другие роли, не?
Как вариант, делаем отдельный таск удаления пакета libfoo, если он установлен и прогоняем по нужной группе хостов. Навешиваем тэг таске для установки пакета libfoo, и при следующем запуске роли этот тэг игнорируем.
Давайте разберемся.
Во первых речь зашла о запуске двух разных версий роли на инфраструктуру.
Во вторых если речь о вспомогальном пакете- библиотеке, напрямую не влияющием на функционал ПО из роли (например jq) - я бы грохнул, без зазрения совести. Если же речь о пакете - зависимости, то либо он не нужен, так как меняется версия, устанавливаемого ПО (а значит меняются переменные - версии и ни о какой идемпотентности после запусков не может быть речи), либо в новой версии у нас появился пересобранный deb пакет без зависимости. А если другим ролям всё таки этот пакет нужен - то смотри пункт про проверку зависимостей. И пошагово:
Роль А версии 1 установила зависимость.
Роль Б подтвердила наличие зависимости.
Роль А версии 2 удалила зависимость при apt install -y.
Роль Б установила зависимость.
Роль А версии 2 не внесла изменений при apt install -y.
И пошагово
Эм в смысле, вы предлагаете вечно хранить все версии роли? Что будем делать когда древняя версия сломалась? Ну там сертификат протух или урл сменился или ещё какая хрень?
Не забывайте про SOLID. Принцип единой ответственности никто не отменял. Это существенная смена функционала. Т.е. в вашем случае пишем дополнительную проверку на наличие версии и формируем проведение в зависимости от потребностей (оставляем как есть/удаляем и ставим новую).
Кстати, я обычно делаю versionlock для пакета - это прям про идемпотентность, если на тачке пасётся ещё кто нибудь с котом кроме меня. При управляемом обновлении поконтурно указываю новую.
оставляем как есть/удаляем и ставим новую
Как роли принять решение об удалении если она не знает о существовании других ролей, которые могут не хотеть удаления?
Очень рекомендую делать снапшот чистой ВМ перед работой. Со временем создания роли/мультироли система обрастает мелочами, которые в последующих запусках не требуются, но на первом запуске - всегда нужны. А после каждого добавления нового функционала возвращать машину к первозданному виду.
Например, в ходе установки какого-то ПО понадобилось включить ip_forward. На первый раз решил включить руками, а потом это не требуется (можно запамятовать). Вот такие моменты помогает вычислить возвраты к первому состоянию ВМ.
Ещё рекомендую использовать мультироли. Каждая суброль должна выполнять маленький блок и быть независимой. Как раз теги помогут вызвать именно ту самую суброль, которая нужна. А meta поможет настроить между ними зависимости в случае необходимости.
Например, вам необходимо установить ПО, которое деплоится только через Docker Compose. Вот тут и пригодится зависимость через meta, которая устанавливает Docker.
Примеры очень упрощённые, но думаю суть вы поняли.
Опять по порядку, на основании собственно опыта.
Например, в ходе установки какого-то ПО понадобилось включить ip_forward. На первый раз решил включить руками
Один раз включаю руками, второй отлаживаю плэйбук, третий качу новой версией роли. Любой чих должен быть описан - так документируется инфраструктура как код.
Например, вам необходимо установить ПО, которое деплоится только через Docker Compose
Значит ставим Compose как зависимость. Вызывать тегами отдельную роль - для меня странно. Я придерживаюсь подхода в котором в любой роли теги имеют одинаковое именование. При вашем подходе, вместо изолированного конфигурирования роли А ( тег config) я пройдусь по по всему кластеру.
Про мультироли наверное самый яркий пример - установка отказоустойчивого кластера postgres. В некоторых случаях наверное это более понятная концепция, нежели вязать через CI/tower последовательный деплой.
Как запилить годную ролюху в Ansible