Николай Месропян, системный инженер Southbridge, подробно рассказал редакции Слёрма о шестилетнем опыте работы с Ansible. Что стоит за слоганом «Simple IT automation»? Почему нельзя остановить темное движение мысли специалиста? И насколько это ясно на старте работы с Ansible? Николай досконально «разложил» все плюсы инструмента на минусы и наоборот.
Ansible – для кого, когда и зачем
Ansible — инструмент автоматизации. Он необходим, чтобы упросить и ускорить работу с IT-инфраструктурой, когда bash-скриптов уже недостаточно. Скрипты – сложны в поддержке.
Компаниям, у которых уже есть развитые и устраивающие всех средства работы с инфраструктурой, сетями, настройкой серверов и деплоем приложений, логично продолжать использовать имеющиеся инструменты. В остальных случаях он может помочь даже специалистам без навыков работы с другим подобным ПО. Для Ansible есть готовые модули стандартизации описания конфигурации и работы с инфраструктурными компонентами. Также хорошо организована работа с данными сериализованными и не очень: есть фильтры, как заимствованные из Jinja2, так и собственные.
«Точка входа» в сложные процессы
Работу с Ansible я начал с автоматизации рутинных действий по настройке серверов и созданию площадок под веб-сайты. Пару лет работал с ним не особо много. Потом втянулся, начал читать документацию и делать более сложные вещи.
За это специалисты чаще всего и хвалят Ansible. С ним можно начать работать, бегло ознакомившись с документацией и примерами, не изучая каких-то языков программирования и прочих сложностей. Так как уже написано огромное количество модулей для решения самых разных задач:
развёртывания облачных окружений у различных провайдеров;
настройки операционных систем;
установки приложений;
работы с сетевыми устройствами — коммутаторами, роутерами, в том числе виртуальными;
работы с cgroup-контейнерами разных видов (Docker, Podman);
взаимодействия с Kubernetes API и так далее.
По мере развития кодовой базы можно углублять знания, постепенно совершенствуя свои навыки работы с Ansible.
В целом, проще перечислить, чего Ansible не умеет. А недостающий модуль можно написать самому. Но лично мне не требовалось. Я всегда обходился штатными специфическими модулями + command/shell. При грамотном применении их можно сделать квази-идемпотентными. Мой пример не может быть полностью репрезентативным, разумеется. В профессиональных сообществах, связанных с Ansible, строго рекомендуют написание собственных модулей в случаях, когда реализация с помощью модулей общего назначения требует «обмазки» сложной логикой. У меня в практике не было подобного примера.
YAML: за и против
В качестве плюса можно добавить использование языка разметки YAML для описания конфигурации. Он интуитивно понятен и весьма популярен сегодня благодаря распространению решений типа Kubernetes.
Фундаментальный недостаток связан с тем, что синтаксис YAML позволяет реализовать любые, самые изощренные bad practices. Просто потому, что это универсальный язык разметки, и при его создании ничего не знали ни про какой Ansible. Он никак не ограничивает самые темные движения мысли разработчика.
Главная слабость Ansible — обратная сторона низкого порога вхождения
Можно легко и непринуждённо породить монстра, который будет выполнять свои функции, но весь состоять из bad practice — сложного в поддержке и непредсказуемо ведущего себя при нетипичных входных данных.
Наиболее зловещими и распространенными антипаттернами, с моей точки зрения, являются два. Назовем их условно «всеобъемлющие роли» и «убей их всех, бог потом рассортирует» «запускаем плейбук на всех хостах, разбираем условия выполнения в процессе».
Всеобъемлющие роли. Бывает, что вместо набора ролей, каждая из которых делает что-то одно, но хорошо, пишется роль, пытающаяся «объять необъятное». Она, как правило, оказывается пронизанной неочевидными зависимостями и условиями выполнения тасков, крайне затрудняющими чтение и понимание кода. Такое происходит или при добавлении функционала в первоначально простенькую роль (упускается момент, в который становится нужно её декомпозировать на отдельные роли), или просто при изначальном недостатке понимания требуемой архитектуры.
Например:
roles ┐
└ web-server
Верно:
roles ┐
│‐nginx
│‐php
│‐php-fpm
│‐rvm
│‐nodejs
└ selinux
Неиспользование групп хостов. Эта «bad practice» весьма распространена и встречается слишком часто, даже в больших и серьёзных проектах. Подобная проблема также связана с недостаточной декомпозицией, но уже не в контексте «UNIX way», а в контексте «потока выполнения». Вместо того чтобы разбить хосты на группы и, используя набор плеев, выполнять отдельные роли на нужных группах хостов, разработчик ставит hosts: all
и внутри tasks
с помощью условий разбирает, какой таск на каком хосте выполнить. В результате получается «вермишель», глядя в которую сложно понять, «кто на ком стоял».
Например:
- name: Play for all hosts
hosts: all
tasks:
- name: >
Include role bar
conditionally
include_role:
name: bar
when: foo_var is defined
Верно:
[foo]
bar1.example.com
bar2.example.com
- name: Play for foo hosts
hosts: foo
tasks:
- name: Import role bar
import_role:
name: bar
Умело применяя оба этих подхода можно написать проект, который при изменении входных условий может ломаться в самых неожиданных местах и будет весьма неудобен в поддержке и развитии даже для того, кто его написал.
Разумеется, список негодных практик и антипаттернов не исчерпывается двумя описанными случаями. Можно вспомнить и более очевидные вещи, которые изрядно портят жизнь новичкам.
Так называемый «bashsible», когда вместо имеющихся специфических модулей не к месту применяются
command
иshell
. При этом теряется идемпотентность и могут возникнуть лишние сторонние эффекты.Использование
lineinfile
вместоtemplate
— теряется предопределённость и декларативность конфигурации.Использование имен переменных, не уникальных для данной роли — это, очевидно, рано или поздно приводит к конфликтам.
Push or pull
Наиболее часто применяющийся способ работы любого сложного ПО — это взаимодействие с удалёнными хостами через ssh. Оно происходит по модели push: сам Ansible запускается на «центральном» управляющем хосте, ходит на управляемые серверы и что-то там делает. И тут возникает проблема со скоростью работы и зависимость от стабильности сети.
Справедливости ради добавлю: в последние год-два разработчики уделяют большое внимание скорости работы Ansible, и это приносит видимые результаты. Доработки позволяют нам потихоньку отказываться от использования стороннего модуля Mitogen, который ранее использовали для увеличения скорости выполнения. Тем не менее в скорости работы он уступает тем системам, которые выполняются непосредственно на конечных хостах — по модели pull.
Я выбрал Ansible. Этот инструмент показался мне более понятным для начинающего, чем один его основной конкурент и более популярным, перспективным и стабильным чем другой. Слоган Ansible: «Simple IT automation».
НЕ Ansible – для кого, когда и зачем
Поскольку это инструмент максимально универсальный, то, разумеется, в некоторых узких нишах он будет проигрывать каким-то специализированным конкурентам.
Как средство настройки и поддержания конфигурации серверов он проигрывает в скорости работы таким распространённым системам, как SaltStack и Chef. Chef конкурирует с Ansible ещё и как средство деплоя.
В нише конфигурации сетевых устройств у Ansible тоже есть конкуренты, но это, как правило, решения от вендоров, которые пишут инструменты под своё железо Так делают, например, Cisco, D-Link.
В нише доставки приложений есть целый мир инструментов, заточенных под язык/фреймворк.
В моей практике были ситуации, когда эффективнее выбрать другой инструмент. Например, те операторы Kubernetes, которые требуют постоянного согласования описанной и действительной конфигураций (reconсiling), лучше писать на Go. Ansible – слишком медленный и однопоточный для подобных задач. Приходилось идти на компромиссы за неимением квалификации для полноценного использования Golang.
Я знаю случаи, когда с Ansible уходили на SaltStack, так как для конкретного кейса нужна была более распределённая система. С другой стороны, Ansible используют даже на Windows. Признаться, я в этом плохо разбираюсь, но раз используют, значит, видят преимущество перед «родными» системами управления конфигурациями.
Подводя итог, Ansible является достаточно мощным и гибким инструментом для того, чтобы закрывать большинство инфраструктурных задач и вполне пригоден для создания верхних уровней абстракции для задач деплоя, если уметь с ним работать правильно.
Народная мудрость советует учиться на чужих ошибках.
Всеволод Севостьянов, автор курса «Ansible: Infrastructure as Code», собрал множество примеров и кейсов, демонстрирующих «что такое хорошо, а что такое плохо». Для закрепления наглядной теории студентам придется выполнить 78 тестовых и 46 практических заданий на стендах в личном кабинете. Один из 8 блоков курса посвящен горячо обсуждаемому в профессиональных сообществах вопросу: когда и как писать собственный модуль? А еще встречи со спикером, общение в чатах, настоящий IT-поединок и целая коллекция забавных мемов. Результат: быстрый «вход» в Ansible без порождения «монстров», о которых предупреждал Николай Месропян.
amarao
А вот, внезапно, за всё время, это первый дельный обзор.
gecube
внезапно, я согласен. Но деталей все равно не хватает.
например здесь. Какой такой инструмент менее стабильный? puppet/salt? Смешно. Ансибл более понятный для новичков? Наверное, да, но эта "кажущаяся" простота и приводит к тому, что очень легко наделать говнокода на башсибле или реализовать те самые антипримеры в статье. Никто не придет и не побьет по рукам за это. Более сложные инструменты, очевидно, имеют более высокий порог входа - это, во-первых, отсекает людей, которые не включают голову, а, во-вторых, подумаешь два раза, перед тем как приступать к решению задачи.