Комментарии 17
Мой опыт показывает, что все то, что дают теги в плане разделения сценариев запуска, можно реализовать и без тегов. Т.е. иметь все плюсы, но без минусов. Если можно обойтись без костылей, то зачем их использовать?
Я писал довольно много больших проектов на Ansible. Как ролей, так и плейбуков. И даже модули с плагинами. Так что некоторое представление имею. И да - я не видел еще ни одной реальной задачи на Ansible, которую нельзя было бы реализовать без тегов.
Ну как же, вот: https://t.me/pro_ansible/329020 😬
Теги очень хороши когда у вас роли вынесены в библиотеку, по умолчанию роли написаны для работы без тегов, но специфичные таски обвешаны тегами, что позволяет точечно запускаться для разбора инцидентов
Вы придумали какое-то экзотическое употребление тегов для передачи с помощью них логики действия, а потому самостоятельно же победили свою же выдумку. Но зачем?
Статью в целом можно свести к 2 тезисам:
Не используйте теги в тасках ролей, используйте в плейбуках на уровне ролей.
Используйте членство в группах и переменные для управления ролями.
Но кажется что проблема кроется глубже:
Итак, лично мое мнение на этот счет такое. Теги в Ansible – это аналог оператора GOTO в инфраструктурном коде. В программировании оператор безусловного перехода (goto) давно считается плохим стилем.
Нет, конечно.
Использую теги только над ролями и не понимаю о какой проблеме говорит автор?
Если одним тегом помечается несколько ролей, то в плейбуке они и так перечисляются в порядке их преполагаемого выполнения.
Где проблема?
Потому что он позволяет нарушить естественный порядок исполнения кода, делая программу трудно читаемой и сложно поддерживаемой, особенно при масштабировании и росте кодовой базы
Отсюда и растет непонимание. Ansible - это не программа с порядком исполнения, а набор шагов последовательно преводяший состояние к желаемому. Это никак не код с каким-то локальным контекстом из-за выскакивания/заскакивания из/в который так не любят goto. В идеальном ansible playbook никакого контекста нет вовсе (такого конечно не бывает на практике, но мы стремимся).
В мире Ansible аналогичную роль играют теги.
Нет. Теги играют роль ОПЕРАТИВНОГО (нужного не всегда, а в редких моментах) включения/отключения ролей при отладочном прогоне плейбука и при применении конкретных изменений. (например если мне нужно выкатить только изменения firewall, то я пишу --tag nftables (покрывающий одноименную роль) и получаю результат без ожидания прохода сотен тасок).
Отсутствие иерархии и дефолтных значений
А зачем мне иерария и дефолтные значения тагов если я ими только ОПЕРАТИВНО включаю/выключаю роли?
Иерархия включения ролей уже есть в каждом play в ключе hosts, что разумеется наследуется.
Дефолтные значения того чем нет необходимости постоянно пользоваться? Зачем?
Вы не можете просто взять и переопределить или структурировать теги при импорте чужого кода или при попытке интеграции в более крупный проект.
Это не имеет отношения только к тегам. Проблема в соглашении об именовании всех вообще сущностей в ansible.
Аналогичные проблемы встречаются и с переменными. Возьмите какой-нибудь крупный проект (например kubespray) и посмотрите как там переменные называются.
Например, представьте плейбук с несколькими задачами, каждая из которых помечена разными тегами: install, config, deploy
Это неправильные границы разбития плейбука/ролей на задачи. Должна быть просто 1 роль: - { role: что_вы_там_запускаете }
. Возможности дергать роль за потроха быть не должно.
если у вас есть аналогичные теги с таким же названием
А если будут аналогичные переменные? Что-то изменится?
Ну так скорее будет хуже, таги - просто включат/выключат отдельные роли и сервер останется в корректном текущем/прерыдущем состоянии, а переменные - сломают состояние сервера.
Теги просто не позволяют установить чёткую иерархию и структуру исполнения.
Она написана в плейбуке. Зачем мне для этого еще и теги? Неудобно.
потом пытаемся получить предсказуемый результат, запуская их в неком произвольном сочетании.
Почему пытаемся? Вполне себе получаем. Тагируя только роли мы получаем ситуацию что прогон плейбука гарантированно корректно исполняется. Роли ведь не зависят друг от друга, а те которые зависят, помечаются одним тагом.
Вместо создания сценариев в виде плейбук, где каждая отвечает за отдельную часть процесса (например, nginx_install, nginx_configure, nginx_deploy), вы помечаете разные задачи тегами типа setup, configuration, deployment и т.п. В итоге получается код, который очень сложно поддерживать и масштабировать, так как задачи теряют контекст, превращаясь просто в набор абстрактных команд, запускаемых хаотично.
У вас какая-то ложная дихотомия или "аксиома Эскобара" ("что то... что это...").
Правильный выбор границ разбиения - { role: nginx }
.
На практике, каждый новый тег удваивает число потенциальных комбинаций исполнения кода.
А какая разница как сильно растет это сочетание покуда таги не зависят друг от друга?
Допустим, у вас есть три задачи с тегами install, configure, start. Если мы используем все три тега в нашем коде автоматизации, то появляется не просто три сценария запуска, а восемькомбинаций: install, configure, start, install&configure, install&start, configure&start, install&configure&start
В очередно раз неправильная граница разбиения. Уже не смешно.
Можно выделить три условных плейбука: app_full_deploy app_packages_upgrade app_config
Снова неверные границы. Зачем?
Вот так надо: { role: app }
.
Зачем мне плодить на каждую роль еще и несколько плейбуков?
По вашему "Infrastructure as a bash history" работает только в отношении тагов? А в отношении 100500 плейбуков не работает? Почему?
Нужно избавляться от сложности, а не переносить её в другую плоскость, где пока вы её не видите.
В эти плейбуки вы можете выборочно включать нужные файлы тасков или задавать гибкие критерии их запуска, используя различные инструменты ветвления кода (when, with_first_found, incude_tasks, tasks_from для ролей и т.п.)
Вот это уже просто пушка.
Правильное использование тагов конечно же в 1000 раз лучше, чем оголтелое навязывание вместо них любых условных конструкций. (Не рекомендую для всех: но последнее время максимально отказываюсь от when, как раз чтобы было видно отсутствие ветвления. И использую вместо него "{{ obj | selectattr() }}" (и т.п. и в том же духе) так что запуск превращается в запуск над подмножеством, а не ответвлением.)
инструменты ветвления кода
С "оператора ветвления" в контексте ансибл... кекнул в голос.
А что думаете на этот счет вы?
Думаю 10 кеков/10
Вы придумали какое-то экзотическое употребление тегов для передачи с помощью них логики действия, а потому самостоятельно же победили свою же выдумку.
Я ничего не придумал. Я описываю то, с чем регулярно сталкиваюсь на практике в чужом коде.
Использую теги только над ролями и не понимаю о какой проблеме говорит автор?
Т.е. вы заведомо ограничиваете применение тегов. Ок, это тоже вариант. Но зачем тогда притворяться, что не понимаете, что так делают далеко не все?
В идеальном ansible playbook никакого контекста нет вовсе (такого конечно не бывает на практике, но мы стремимся).
Есть, конечно же. Это факты в виде набора данных, которые могут много раз меняться по ходу выполнения плейбука. Если включаете участки кода из разных мест - у них может быть разный контекст.
Нет. Теги играют роль ОПЕРАТИВНОГО (нужного не всегда, а в редких моментах) включения/отключения ролей при отладочном прогоне плейбука и при применении конкретных изменений. (например если мне нужно выкатить только изменения firewall, то я пишу --tag nftables (покрывающий одноименную роль) и получаю результат без ожидания прохода сотен тасок).
Что "нет"? Я описываю то, как теги используются в общем. И это встречается во многих проектах. То, что в ваших личных теги используются очень ограниченно и только для специальных целей, не означает, что всего остального нет.
А зачем мне иерария и дефолтные значения тагов если я ими только ОПЕРАТИВНО включаю/выключаю роли?
Опять вы все сводите только к своему случаю. Ваш юзкейс далеко не единственный.
Это не имеет отношения только к тегам. Проблема в соглашении об именовании всех вообще сущностей в ansible.Аналогичные проблемы встречаются и с переменными.
С переменными такая проблема тоже есть. Но у переменных есть иерархия и разные области применимости. Я, например, могу одной роли задать одно значение какой-то переменной, а другой - совершенно другое, хотя имя переменной тоже самое. И все это в рамках одного плейбука. С тегами так не получится.
P.S. В целом спасибо за интересные комментарии.
А теперь по другим - более странным комментариям:
Это неправильные границы разбития плейбука/ролей на задачи. Должна быть просто 1 роль:
- { role: что_вы_там_запускаете }
. Возможности дергать роль за потроха быть не должно.
В идеальном мире - да. Но мы живем не в идеальном мире. На практике часто бывает, что часть кода внутри роли иногда хочется переиспользовать вне контекста самой роли. И выделять эту часть в отдельную роль тоже не всегда бывает оптимальным выбором из-за области определения дефолтных переменных.
А если будут аналогичные переменные? Что-то изменится?
Конечно. Потому что у переменных есть:
Иерархия
Приоритеты
Область применения
Об этом в статье довольно детально написано.
У вас какая-то ложная дихотомия или "аксиома Эскобара" ("что то... что это...").Правильный выбор границ разбиения -
{ role: nginx }
.
Я описываю конкретные примеры наиболее частого применения тегов. С которыми постоянно сталкиваюсь, смотря образцы чужого кода. При чем тут аксиома Эскобара?
А какая разница как сильно растет это сочетание покуда таги не зависят друг от друга?
Если вы не понимаете в чем проблема роста числа возможных сценариев запуска одного и того же кода, мне сложно будет это объяснить. Как столкнетесь - поймете.
Снова неверные границы. Зачем?Вот так надо:
{ role: app }
.Зачем мне плодить на каждую роль еще и несколько плейбуков?
Потому что у одной роли может быть больше одного сценария запуска. Вы серьезно не понимаете, о чем речь?
Вот это уже просто пушка.Правильное использование тагов конечно же в 1000 раз лучше, чем оголтелое навязывание вместо них любых условных конструкций. (Не рекомендую для всех: но последнее время максимально отказываюсь от when, как раз чтобы было видно отсутствие ветвления. И использую вместо него "{{ obj | selectattr() }}" (и т.п. и в том же духе) так что запуск превращается в запуск над подмножеством, а не ответвлением.)
И как это поможет? Допустим, роль у вас должна выполняться на нескольких разных дистрибутивах. Для одних дистрибутивов нужны одни модули, для других - другие. Для некоторых версий бывают нужны отдельные дополнительные таски. Расскажите, как эти сценарии использования роли покрывает "{{ obj | selectattr() }}"?
С "оператора ветвления" в контексте ансибл... кекнул в голос.
Не очень понятно, что вы там сделали, но если поясните, то будет понятнее.
В целом, статья лишена всякого смысла банально из-за того, что вы пытаетесь объяснить, что условного оглавления в книге достаточно и можно обойтись без предметного указателя.
Можно обойтись, да. А можно пользоваться инструментом, когда в нем есть необходимость. В большинстве случаев, задачи можно решить разными способами, серебряной пули нет.
Банально, у вас есть плейбук, который запускает приложение в docker на 1000 хостов, и все замечательно, но в моменте, вы осознаете, что у вас каждый раз при запуске плейбука уходит около часа времени на то, чтобы проверить, что на хостах установлен docker. Есть вариант распилить плейбук на 2, установку docker и установку приклада. Получается у нас 2 плейбука, вам надо написать инструкцию условному пользователю, а он должен понять, в какой последовательности запустить плейбуки. Можно вызавть оба плейбука их из третьего, можно придумать еще кучу сценариев, и один из них, который может в моменте оказаться наиболее подходящим - проставить теги.
Теги дают гибкость, они не всегда про удобство.
Интересный подход, почему бы тегами не помечать отдельные логические участки роли, при условии что сама роль линейная и монолитная? Допустим базовое развертывание приложения? Оно отлично будет работать и без тегов, и с тегами в любом порядке с любой комбинацией.
В программировании оператор безусловного перехода (goto) давно считается плохим стилем.
разработчики ядра линукс: ну да ну да, пошли мы нафиг
$ find ./linux-6.12/ -type f -name "*.c" -exec grep -E ".*goto\s.*" {} \; | wc -l
201596
Не умеешь варить, отдай другому. Для динамических инклудов делаешь apply: tags:
Не используйте теги в Ansible