ansible playbook что это

Что такое Ansible и как его использовать

Авторизуйтесь

Что такое Ansible и как его использовать

Что такое Ansible? Это ПО с открытым исходным кодом, которое автоматизирует поставку программного обеспечения, управление конфигурацией и развёртывание приложений. Ansible помогает DevOps-специалистам автоматизировать сложные задачи.

Примечание Вы читаете улучшенную версию некогда выпущенной нами статьи.

Ключевые особенности программы Ansible

Установка и запуск

Инструкцию по установке на другие ОС можно найти здесь.

Структура Ansible

Модули

Это небольшие программы, выполняющие определённую работу на сервере. Например, вместо запуска этой команды:

Мы можем использовать модуль apt и установить htop:

Использование модуля даст вам возможность узнать, установлен он или нет.

Плагины

Ansible поставляется с несколькими удобными плагинами, и вы можете легко написать свой собственный.

Инвентаризация хостов

Чтобы предоставить перечень хостов, нам нужно обозначить список, находящийся в файле инвентаризации. Он напоминает содержание файла hosts.

В простейшем виде он может содержать одну строку:

Playbooks

Ansible playbooks — это способ отправки команд на удалённые компьютеры с помощью скриптов. Вместо того, чтобы индивидуально использовать команды для удалённой настройки компьютеров из командной строки, вы можете настраивать целые сложные среды, передавая скрипт одной или нескольким системам.

group_vars

Файл содержит набор переменных, например имя пользователя и пароль базы данных.

Это способ сгруппировать несколько задач в один контейнер, чтобы эффективно автоматизировать работу с помощью понятной структуры каталогов.

Обработчики

Представляют собой списки задач, которые на самом деле не отличаются от обычных задач, на которые ссылается глобально уникальное имя и которые оповещаются уведомителями. Если ничто не уведомляет обработчик, он не будет запускаться. Независимо от того, сколько задач уведомляет обработчик, он запускается только один раз, после того как все задачи завершены.

Если у вас playbook с большим объёмом, может быть полезно иметь возможность запускать только определённую часть его конфигурации.

Демо «Реальное приложение»

Цель этой демонстрации — установить приложение Laravel в VPS. Для этого используем Lightsail.

Последовательность действий для создания и запуска Laravel APP:

Рассмотрим каждый пункт подробнее.

Создание экземпляра Ubuntu Lightsail

Перейдите на панель управления Lightsail и нажмите «Создать экземпляр».

ansible playbook что это

Выберите свою любимую ОС.

ansible playbook что это

Выберите «Добавить скрипт запуска», который запускается после создания вашего экземпляра. Не забудьте получить SSH-ключ.

ansible playbook что это

Установка зависимостей Ansible на нашем VPS

Добавьте эти sh-команды для установки зависимостей:

ansible playbook что этоansible playbook что это

Теперь у нас есть готовый экземпляр, перейдём к построению Ansible Project.

Добавление SSH-ключей в Git

Вы должны добавить свой сервер id_rsa.pub к своим ключам GitHub SSH, войдя в свой сервер.

Сборка хостов и ansible.cfg

Определение роли в Ansible

Используем модуль Ping, чтобы убедиться, что хост работает, после чего нужно обновить все пакеты и установить два модуля: git и htop.

Определение обработчика

Установка модулей PHP

Чтобы вызвать обработчик, мы должны использовать notify: Restart PHP-FPM, имена обработчиков должны быть уникальными.

В этом руководстве мы определили php как тег, поэтому, например, если вы хотите запустить только эту задачу из своего playbook, вам необходимо выполнить её с —tags = ”php”, которая будет исполнять только её.

Установка Nginx

Добавление default-конфигурации Nginx

vars.yml

Примечание: Рекомендуется использовать ansible-vault для шифрования и дешифрования переменных.

Как использовать Ansible-Vault

Создайте секретный файл хранилища, содержащий ключ шифрования, который шифрует ваши переменные.

Чтобы зашифровать переменные, используйте:

Чтобы расшифровать переменные, используйте:

Создание базы данных MySql, имени пользователя и пароля

mysql_user и mysql_pass определены внутри vars.yml.

Клонирование кодовой базы

repo_git_url и app_work_dir определены внутри vars.yml.

Генерирование .env

Ansible использует шаблонизатор Jinja2 для динамических выражений и доступа к переменным. Создадим файл env.conf.

Создание playbook

Как видно, мы определили aws как хост для этого playbook, и sudo yes даёт нам возможность выполнять команду как пользователю sudo. У нас есть vars_files, где мы храним наши vars. Мы установили roles, каждая role выполняет определённую задачу. И, наконец, у нас есть handlers, которые содержат все обработчики проекта.

Источник

Использование Ansible Playbooks

В инструкции описано применение и работа с Ansible Playbook, а также кратко рассмотрена их структура.

Что такое Ansible Playbooks?

Playbook в Ansible определяет серию некоторых действий для выполнения и адресованы определенным наборам серверов. В отличие от некоторых других инструментов для выполнения настроек, Playbook не описывает состояние машины, а Ansible самостоятельно определяет все изменения, которые необходимо внести. Тем не менее, плейбуки должны быть разработаны как идемпотенты, а это значит, что они могут запускаться более одного раза без негативных последствий.

Например, следующий playbook будет входить на все серверы группы marketingservers и обеспечивать запуск веб-сервера Apache:

В плейбуке выше приведен пример задания (task):

Каждое задание должно иметь имя, которое впоследствии регистрируется и может помочь отслеживать прогресс. После строки имени (name) находится модуль, который будет запущен, в данном случае это служебный модуль. Другие атрибуты разрешают больше опций, в примере Ansible разрешается использовать привилегии sudo.

Запуск Ansible Playbook

Запустить готовый плейбук можно используя следующую команду:

Однако, если есть необходимость отфильтровать список хостов, чтобы сценарий применялся только к одному из этих хостов, можно добавить флаг и указать подмножество хостов в файле:

Регистрация результатов

Когда вы устанавливаете и настраиваете службы вручную, почти всегда необходимо знать результат действий. Настроить эту функциональность можно с помощью регистрации.

Для каждой задачи при желании возможно зарегистрировать ее результат (сбой или успех) в переменной, которую можно проверить позже. При использовании этой функциональности рекомендуется указывать Ansible игнорировать ошибки для такой задачи, так как обычно выполнение playbook прерывается в случае возникновения каких-либо проблем.

Таким образом, если необходимо проверить, выполнилась ли задача или нет и принять решение о последующих шагах, необходимо использовать функциональность регистрации.

Источник

Основы Ansible, без которых ваши плейбуки — комок слипшихся макарон

Я делаю много ревью для чужого кода на Ансибл и много пишу сам. В ходе анализа ошибок (как чужих, так и своих), а так же некоторого количества собеседований, я понял основную ошибку, которую допускают пользователи Ансибла — они лезут в сложное, не освоив базового.

Для исправления этой вселенской несправедливости я решил написать введение в Ансибл для тех, кто его уже знает. Предупреждаю, это не пересказ манов, это лонгрид в котором много букв и нет картинок.

Ожидаемый уровень читателя — уже написано несколько тысяч строк ямла, уже что-то в продакшене, но «как-то всё криво».

Названия

Главная ошибка пользователя Ansible — это не знать как что называется. Если вы не знаете названий, вы не можете понимать то, что написано в документации. Живой пример: на собеседовании, человек, вроде бы заявлявший, что он много писал на Ансибле, не смог ответить на вопрос «из каких элементов состоит playbook’а?». А когда я подсказал, что «ожидался ответ, что playbook состоит из play», то последовал убийственный комментарий «мы этого не используем». Люди пишут на Ансибле за деньги и не используют play. На самом деле используют, но не знают, что это такое.

Так что начнём с простого: как что называется. Может быть вы это знаете, а может и нет, потому что не обратили внимания, когда читали документацию.

ansible-playbook исполняет playbook. Playbook — это файл с расширением yml/yaml, внутри которого что-то такое:

Мы уже поняли, что весь этот файл — плейбука. Мы можем показать где тут роли (roles), где таски (tasks). Но где тут play? И чем отличается play от role или playbook?

В документации это всё есть. И это пропускают. Начинающие — потому что там слишком много и всё сразу не запомнишь. Опытные — потому что «тривиальные вещи». Если вы опытный — перечитывайте эти страницы хотя бы раз в полгода, и ваш код станет классом лучше.

и вот это тоже ещё одна play:

Что же такое play? Зачем она?

Если вы хотите «что-то» исполнить «где-то» — вы пишете play. Не роль. Не роль с модулями и делегейтами. Вы берёте и пишете play. В которой, в поле hosts вы перечисляете где исполнять, а в roles/tasks — что исполнять.

Просто же, да? А как может быть иначе?

Одним из характерных моментов, когда у людей возникает желание сделать это не через play, это «роль, которая всё настраивает». Хочется иметь роль, которая настраивает и сервера первого типа, и сервера второго типа.

Архетипичным примером является мониторинг. Хочется иметь роль monitoring, которая настроит мониторинг. Роль monitoring назначается на хосты мониторинга (в соотв. play). Но, выясняется, что для мониторинга нам надо поставить пакеты на хосты, которые мы мониторим. Почему бы не использовать delegate? А ещё надо настроить iptables. delegate? А ещё надо написать/поправить конфиг для СУБД, чтобы мониторинг пускала. delegate! А если креатив попёр, то можно сделать делегацию include_role во вложенном цикле по хитрому фильтру на список групп, а внутри include_role можно ещё делать delegate_to снова. И понеслось.

Благое пожелание — иметь одну-единственную роль monitoring, которая «всё делает» — ведёт нас кромешный ад из которого чаще всего один выход: всё переписать с нуля.

Где тут случилась ошибка? В тот момент, когда вы обнаружили, что для выполнения задачи «x» на хосте X вам надо пойти на хост Y и сделать там «y», вы должны были выполнить простое упражнение: пойти и написать play, которая на хосте Y делает y. Не дописывать что-то в «x», а написать с нуля. Пусть даже с захардкоженными переменными.

Вроде бы, в абзацах выше всё сказано правильно. Но это же не ваш случай! Потому что вы хотите написать переиспользуемый код, который DRY и похож на библиотеку, и нужно искать метод как это сделать.

Вот тут вот притаилась ещё одна грубая ошибка. Ошибка, которая превратила множество проектов из терпимо написанных (можно лучше, но всё работает и легко дописать) в совершенный ужас, в котором даже автор не может разобраться. Оно работает, но упаси боже что-то поменять.

Эта ошибка звучит так: роль — это библиотечная функция. Эта аналогия сгубила столько хороших начинаний, что просто грустно смотреть. Роль — не библиотечная функция. Она не может делать вычисления и она не может принимать решения уровня play. Напомните мне, какие решения принимает play?

Спасибо, вы правы. Play принимает решение (точнее, содержит в себе информацию) о том, какие таски и роли на каких хостах выполнять.

Если вы делегируете это решение на роль, да ещё и с вычислениями, вы обрекаете себя (и того, кто ваш код будет пытаться разобрать) на жалкое существование. Роль не решает где ей выполняться. Это решение принимает play. Роль делает то, что ей сказали, там, где ей сказали.

Почему заниматься программированием на Ансибле опасно и чем COBOL лучше Ансибла мы поговорим в главе про переменные и jinja. Пока что скажем одно — каждое ваше вычисление оставляет за собой нестираемый след из изменения глобальных переменных, и вы ничего с этим не можете сделать. Как только два «следа» пересеклись — всё пропало.

play и только play решает на каких хостах что исполняется.

В этом разделе мы разобрались с противостоянием play и role. Теперь поговорим про отношения tasks vs role.

Таски и Роли

… И куда делись tasks?

Мы снова начинаем с азов — устройство play. Если вы плаваете в этом вопросе, вы не можете использовать play как основу для всего остального, и ваш результат получается «шатким».

Устройство play: директива hosts, настройки самой play и секции pre_tasks, tasks, roles, post_tasks. Остальные параметры для play нам сейчас не важны.

Но мы всё ещё не ответили на вопрос: а куда вызов модуля foo писать? Надо ли нам под каждый модуль писать целую роль? Или лучше иметь толстую роль подо всё? А если не роль, то куда писать — в pre или в post?

Разумеется, формулировка вопроса намекает, что сломается. Но что именно?

И, возвращаемся, к нашему ‘foo’. Куда его поместить? В pre, post или в roles? Очевидно, это зависит от того, нужны ли нам результаты работы хэндлера для foo. Если их нет, то foo не нужно класть ни в pre, ни в post — эти секции имеют специальный смысл — выполнение тасок до и после основного массива кода.

Теперь ответ на вопрос «роль или таска» сводится к тому, что уже есть в play — если там есть tasks, то надо дописать в tasks. Если есть roles — надо делать роль (пусть и из одной task). Напоминаю, tasks и roles одновременно не используются.

Понимание основ Ансибла даёт обоснованные ответы на, казалось бы, вопросы вкусовщины.

Таски и роли (часть вторая)

Теперь обсудим ситуацию, когда вы только начинаете писать плейбуку. Вам надо сделать foo, bar и baz. Это три таски, одна роль или три роли? Обобщая вопрос: в какой момент надо начинать писать роли? В чём смысл писать роли, когда можно писать таски?… А что такое роль?

Одна из грубейших ошибок (я про это уже говорил) — считать, что роль — это как функция в библиотеке у программы. Как выглядит обобщённое описание функции? Она принимает аргументы на вход, взаимодействует с side causes, делает side effects, возвращает значение.

Теперь, внимание. Что из этого можно сделать в роли? Вызвать side effects — всегда пожалуйста, это и есть суть всего Ансибла — делать сайд-эффекты. Иметь side causes? Элементарно. А вот с «передать значение и вернуть его» — вот тут-то и нет. Во-первых, вы не можете передать значение в роль. Вы можете выставить глобальную переменную со сроком жизни размером в play в секции vars для роли. Вы можете выставить глобальную переменную со сроком жизни в play внутри роли. Или даже со сроком жизни плейбуки ( set_fact / register ). Но вы не можете иметь «локальные переменные». Вы не можете «принимать значение» и «возвращать его».

Итого: роль — это не функция.

Что же хорошего есть в роли? Во-первых, у роли есть default values ( /default/main.yaml ), во-вторых у роли есть дополнительные каталоги для складывания файлов.

Ещё одна деталь: можно пытаться делать роли, которые будут доступны для переиспользования (через galaxy). После появления коллекций распространение ролей можно считать почти забытым.

Таким образом, роли обладают двумя важными особенностями: у них есть дефолты (уникальная особенность) и они позволяют структурировать код.

Возвращаясь к исходному вопросу: когда делать таски а когда роли? Таски в плейбуке чаще всего используются либо как «клей» до/после ролей, либо как самостоятельный строительный элемент (тогда в коде не должно быть ролей). Груда нормальных тасок в перемешку с ролями — это однозначная неряшливость. Следует придерживаться конкретного стиля — либо таски, либо роли. Роли дают разделение сущностей и дефолты, таски позволяют прочитать код быстрее. Обычно в роли выносят более «стационарный» (важный и сложный) код, а в стиле тасок пишут вспомогательные скрипты.

Существует возможность делать import_role как таску, но если вы такое пишете, то будьте готовы к объяснительной для собственного чувства прекрасного, зачем вы это хотите делать.

Въедливый читатель может сказать, что роли могут импортировать роли, у ролей может быть зависимость через galaxy.yml, а ещё есть страшный и ужасный include_role — напоминаю, мы повышаем навыки в базовом Ансибле, а не в фигурной гимнастике.

Хэндлеры и таски

Давайте обсудим ещё одну очевидную вещь: хэндлеры. Умение их правильно использовать — это почти искусство. В чём разница между хэндлером и таской?

Так как мы вспоминаем основы, то вот пример:

У роли handler’ы лежат в rolename/handlers/main.yaml. Handler’ы шарятся между всеми участниками play: pre/post_tasks могут дёргать handler’ы роли, а роль может дёргать handler’ы из плей. Однако, «кросс-ролевые» вызовы handler’ов вызывают куда больший wtf, чем повтор тривиального handler’а. (Ещё один элемент best practices — стараться не делать повторов имён handler’ов).

Основное различие в том, что таска выполняется (идемпотентно) всегда (плюс/минус теги и when ), а хэндлер — по изменению состояния (notify срабатывает только если был changed). Чем это чревато? Например, тем, что при повторном запуске, если не было changed, то не будет и handler. А почему может быть так, что нам нужно выполнить handler когда не было changed у порождающей таски? Например, потому что что-то сломалось и changed был, а до хэндлера выполнение не дошло. Например, потому что сеть временно лежала. Конфиг поменялся, сервис не перезапущен. При следующем запуске конфиг уже не меняется, и сервис остаётся со старой версией конфига.

Ещё одно положительное свойство handler’а состоит в том, что он не засоряет вывод. Не было изменений — нет лишних skipped или ok в выводе — легче читать. Оно же является и отрицательным свойством — если опечатку в линейно исполняемой task’е вы найдёте на первый же прогон, то handler’ы будут выполнены только при changed, т.е. при некоторых условиях — очень редко. Например, первый раз в жизни спустя пять лет. И, разумеется, там будет опечатка в имени и всё сломается. А второй раз их не запустить — changed-то нет.

Отдельно надо говорить про доступность переменных. Например, если вы notify для таски с циклом, то что будет в переменных? Можно аналитическим путём догадаться, но не всегда это тривиально, особенно, если переменные приходят из разных мест.

… Так что handler’ы куда менее полезны и куда более проблемны, чем кажется. Если можно что-то красиво (без выкрутас) написать без хэндлеров лучше делать без них. Если красиво не получается — лучше с ними.

Чем меньше if’ов (явных или декларативных — в форме when или форме include_vars по набору переменных), тем лучше роль. Иногда приходится делать ветвления, но, повторю, чем их меньше, тем лучше. Так что вроде бы хорошая роль с galaxy (работает же!) с кучей when может быть менее предпочтительна, чем «своя» роль из пяти тасок. Момент, когда роль с galaxy лучше — когда вы что-то начинаете писать. Момент, когда она становится хуже — когда что-то ломается, и у вас есть подозрение, что это из-за «роли с galaxy». Вы её открываете, а там пять инклюдов, восемь таск-листов и стопка when ‘ов… И в этом надо разобраться. Вместо 5 тасок линейным списком, в котором и ломаться-то нечему.

Источник

Пособие по Ansible

ansible playbook что это

Это практическое пособие познакомит вас c Ansible. Вам понадобится виртуальная или реальная машина, которая будет выступать в роли узла для Ansible. Окружение для Vagrant идет в комплекте с этим пособием.

Ansible — это программное решение для удаленного управления конфигурациями. Оно позволяет настраивать удаленные машины. Главное его отличие от других подобных систем в том, что Ansible использует существующую инфраструктуру SSH, в то время как другие (chef, puppet, и пр.) требуют установки специального PKI-окружения.

Пособие покрывает такие темы:

Ansible использует так называемый push mode: конфигурация «проталкивается» (push) с главной машины. Другие CM-системы обычно поступают наоборот – узлы «тянут» (pull) конфигурацию с главной машины.

Этот режим интересен потому что вам не нужно иметь публично доступную главную машину для удаленной настройки узлов; это узлы должны быть доступны (позже мы увидим, что скрытые узлы также могут получать конфигурацию).

Что нужно для Ansible

Необходимы следующие Python-модули

На Debian/Ubuntu запустите:

У вас также должна быть пара ключей в

Установка Ansible

Из исходников

Ветка devel всегда стабильна, так что используем ее. Возможно, вам нужно будет установить git ( sudo apt-get install git на Debian/Ubuntu).

Теперь можно загрузить окружение Ansible.

Из deb пакета

В этом пособии предполагается, что вы использовали именно этот способ.

Установка Vagrant

Vagrant позволяет с легкостью создавать виртуальные машины и запускать их на VirtualBox. Vagrantfile идет в комплекте с пособием.

Чтобы запустить Vagrant вам нужно установить:

и налейте себе кофе (если вы используете vagrant-hostmaster, то вам нужно будет ввести root-пароль). Если что-то пошло не так, загляните в туториал по Vagrant’у.

Добавление SSH-ключей на виртуальной машине

Чтобы продолжить, вам нужно добавить свои ключи в authorized_keys root’а на виртуальной машине. Это не обязательно (Ansible может использовать sudo и авторизацию по паролю), но так будет намного проще.

Ansible идеально подходит для этой задачи, поэтому используем его. Однако, я не буду пока ничего объяснять. Просто доверьтесь мне.

В качестве пароля введите vagrant. Если возникнут ошибки «Connections refused», то проверьте настройки фаервола.

Теперь добавьте свои ключи в ssh-agent ( ssh-add ).

Inventory

Мы создали такой файл inventory:

ansible_ssh_host это специальная переменная, которая содержит IP-адрес узла, к которому будет создаваться соединение. В данном случае она не обязательна, если вы используете gem vagrant-hostmaster. Также, вам нужно будет менять IP-адреса если вы устанавливали и настраивали свою виртуальную машину с другими адресами.

ansible_ssh_user это еще одна специальная переменная которая говорит Ansible’у подключаться под указанным аккаунтом (юзером). По умолчанию Ansible использует ваш текущий аккаунт, или другое значение по умолчанию, указанное в

Проверка

Теперь когда Ansible установлен, давайте проверим, что все работает:

Здесь Ansible попытается запустить модуль ping (подробнее о модулях позже) на каждом хосте. Вывод должен быть примерно таким:

Отлично! Все три хоста живы и здоровы, и Ansible может общаться с ними.

Общение с узлами

Сделаем что-нибудь полезное

Модуль shell

Этот модуль позволяет запускать shell-команды на удаленном узле:

Вывод должен быть вроде:

Модуль copy

Модуль copy позволяет копировать файл из управляющей машины на удаленный узел. Представим, что нам нужно скопировать наш /etc/motd в /tmp узла:

Ansible (точнее, модуль copy, запущенный на узле) ответил кучей полезной информации в формате JSON. Позже мы увидим, как это можно использовать.

У Ansible есть огромный
список модулей, который покрывает практически все, что можно делать в системе. Если вы не нашли подходящего модуля, то написание своего модуля – довольно простая задача (и не обязательно писать его на Python, главное, чтобы он понимал JSON).

Много хостов, одна команда

Все что было выше – замечательно, но нам нужно управлять множеством хостов. Давайте попробуем. Допустим, мы хотим собрать факты про узел и, например, хотим узнать какая версия Ubuntu установлена на узлах. Это довольно легко:

all означает «все хосты в файле inventory». Вывод будет примерно таким:

Больше фактов

Вывод был сокращен для простоты, но вы можете узнать много интересного из этой информации. Вы также можете фильтровать ключи, если вас интересует что-то конкретное.

Заметьте, что узлы ответили не в том порядке, в котором они отвечали выше. Ansible общается с хостами параллельно!

Выбор хостов

Мы видели, что all означает «все хосты», но в Ansible есть
куча иных способов выбирать хосты:

Группировка хостов

Можно даже сократить:

Если хотите задавать дочерние группы, используйте [groupname:children] и добавьте дочерние группы в него. Например, у нас есть разные дистрибутивы Линукса, их можно организовать следующим образом:

Установка переменных

Вы можете добавлять переменные для хостов в нескольких местах: в файле inventory, файлах переменных хостов, файлах переменных групп и др.

Ansible будет искать файлы по имени. Например, при использовании упомянутого ранее файле inventory, Ansible будет искать переменные host0.example.org в файлах:

Если этих файлов не существует – ничего не произойдет, но если они существуют – они будут использованы.

Теперь, когда мы познакомились с модулями, инвентаризацией и переменными, давайте, наконец, узнаем о настоящей мощи Ansible с плейбуками.

Плейбуки Ansible

Пример с Apache (a.k.a. «Hello World!» в Ansible)

Продолжаем с допущением, что ваш файл inventory выглядит так (назовем его hosts ):

и все хосты — это системы на основе Debian.

Заметка: помните, что вы можете (и в нашем упражнении мы делаем это) использовать ansible_ssh_host чтобы задать реальный IP-адрес хоста. Вы также можете изменять inventory и использовать реальный hostname. В любом случае, используйте машину, с которой безопасно экспериментировать. На реальных хостах мы также добавляем ansible_ssh_user=root чтобы избежать потенциальных проблем с разными конфигурациями по умолчанию.

Нам всего лишь нужно сказать, что мы хотим сделать, используя правильные модули Ansible. Здесь мы используем модуль apt, который может устанавливать пакеты Debian. Мы также просим этот модуль обновить кэш.

Нам нужно имя для этой задачи. Это не обязательно, но желательно для вашего же удобства.

Ну, в целом было довольно легко! Теперь можно запустить плейбук (назовем его apache.yml ):

При запуске команды будет вывод подобный этому:

Давайте проанализируем вывод строчка за строчкой.

Наконец, Ansible выводит выжимку того, что произошло: две задачи были выполнены, и одна из них изменила что-то на хосте (это была наша задача apache; модуль setup ничего не меняяет).

Давайте запустим это еще раз и посмотрим, что произойдет:

Улучшаем набор apache

Мы установили apache, давайте теперь настроим virtualhost.

Улучшение плейбука

Нам нужен лишь один виртуальный хост на сервере, но мы хотим сменить дефолтный на что-то более конкретное. Поэтому нам придется удалить текущий virtualhost, отправить наш virtualhost, активировать его и перезапустить apache.

Давайте создадим директиорию под названием files и добавим нашу конфигурацию для host1.example.org, назовем ее awesome-app :

Теперь небольшое обнуление плейбука и все готово:

Круто! Ну, если задуматься, мы немного опережаем события. Не нужно ли проверить корректность конфигурации перед тем, как перезапускать apache? Чтобы не нарушать работоспособность сервиса в случае если конфигурация содержит ошибку.

Перезапуск в случае ошибки конфигурации

Мы установили apache, изменили virtualhost и перезапустили сервер. Но что, если мы хотим перезапускать сервер только когда конфигурация корректна?

Откатываемся, если есть проблемы

Ansible содержит классную особенность: он остановит всю обработку, если что-то пошло не так. Мы используем эту особенность чтобы остановить плейбук, когда конфигурация не валидна.

Давайте изменим файл конфигурации виртуального хоста awesome-app и сломаем его:

Как я сказал, если задача не может исполниться, обработка останавливается. Так что нужно удостовериться в валидности конфигурации перед перезапуском сервера. Мы также начнем с добавления виртуального хоста до удаления дефолтного виртуального хоста, так что последующий перезапуск (возможно, сделанный напрямую на сервере) не сломает apache.

Нужно было сделать это в самом начале. Так как мы уже запускали этот плейбук, дефолтный виртуальный хост уже деактивирован. Не проблема: этот плейбук можно использовать на других невинных хостах, так что давайте защитим их.

Как вы заметили, apache2ctl возвращает код ошибки 1. Ansible видит это и останавливает работу. Отлично!

Ммм, хотя нет, не отлично… Наш виртуальный хост все равно был добавлен. При любой последующей попытке перезапуска Apache будет ругаться на конфигурацию и выключаться. Так что нам нужен способ отлавливать ошибки и возвращаться к рабочему состоянию.

(прим. переводичка: хабраюзер @clickfreak в комментариях советует взлянуть на специальную фичу Ansible 2.x).

Использование условий

Мы установили Apache, добавили виртуальный хост и перезапустили сервер. Но мы хотим вернуться к рабочему состоянию, если что-то пошло не так.

Возврат при проблемах

Как было сказано ранее, если задача не может исполниться – обработка останавливается… но мы можем принять ошибку (и нам нужно это делать). Так мы и поступим: продолжим обработку в случае ошибки, но только чтобы вернуть все к рабочему состоянию.

Кажется, все работает как нужно. Давайте попробуем перезапустить apache:

Теперь наш Apache защищен от ошибок конфигурации. Помните, переменными можно пользоваться практически везде, так что этот плейбук можно использовать для apache и в других случаях. Напишите один раз и пользуйтесь везде.

Деплоим сайт с помощью Git

Мы установили Apache, добавили виртуальный хост и безопасно перезапустили сервер. Теперь давайте используем модуль git чтобы сделать деплой приложения.

Модуль git

но в Ansible есть способ лучше. Он может проходить по набору элементов и использовать каждый в определенном действии, вот так:

Строка tags: deploy позволяет запустить определнную порцию плейбука. Допустим, вы запушили новую версию сайта. Вы хотите ускорить процесс и запустить только ту часть, которая ответственна за деплой. Это можно сделать с помощью тегов. Естественно, «deploy» — это просто строка, можно задавать любую. Давайте посмотрим, как это можно использовать:

PLAY [web] *****

GATHERING FACTS *****
ok: [host1.example.org]

TASK: [Deploy our awesome application] *****
changed: [host1.example.org]

PLAY RECAP *****
host1.example.org: ok=2 changed=1 unreachable=0 failed=0

Добавляем еще один веб-сервер

У нас есть один веб-сервер. Мы хотим два.

Обновление inventory

Мы ожидаем наплыва трафика, так что давайте добавим еще один веб-сервер и балансировщик, который мы настроим в следующем шаге. Давайте закончим с inventory:

Помните, здесь мы указываем ansible_ssh_host потому что хост имеет не тот IP, что ожидается. Можно добавить эти хосты к себе в /etc/hosts или использовать реальные имена (что вы и будете делать в обычной ситуации).

Сборка второго веб-сервера

Мы не зря напрягались перед этим. Деплой второго сервера очень прост:

Теперь у нас есть чудесная ферма веб-серверов, давайте превратим ее в кластер с помощью балансировщика нагрузок.

Шаблоны

Шаблон конфигурации HAProxy

Ansible использует Jinja2, систему шаблонов для Python. Внутри Jinja2-шаблона можно использовать любую переменную, которая определена Ansible’ом.

Jinja2 также поддерживает условия, циклы и прочее.

Тут есть несколько новых для нас деталей.

Во-первых, << ansible_eth1['ipv4']['address'] >> заменится на IP балансировщика нагрузки на eth1.

HAProxy playbook

Самое сложное позади. Написать плейбук для устновки и конфигурации HAproxy очень легко:

А теперь… попробуем. В нашем inventory содержатся только необходимые для кластера хосты, поэтому нам не нужно делать дополнительных ограничений и можно даже запустить оба плейбука. Ну, на самом деле, нам нужно запускать их одновременно, так как haproxy-плейбуку нужны факты из двух веб-серверов. Чуть позже мы узнаем, как избежать этого.

Вроде все хорошо. Зайдите на http://192.168.33.10/ и оцените результат. Кластер задеплоен! Можно даже посмотреть на статистику HAproxy: http://192.168.33.10/haproxy?stats.

Снова переменные

Итак, мы установили балансировщик нагрузки, и он работает нормально. Мы берем переменные из фактов и используем их для генерации конфигурации.

Тонкая настройка конфигурации HAProxy

Обычно HAProxy проверяет, живы ли бэкенды. Если бэкенд не откликается, то он удаляется из пула, и HAProxy больше не шлет ему запросы.

У бэкэндов может быть указан вес (от 0 до 256). Чем выше вес, тем больше запросов сервер получит по сравнению с другими серверами. Это полезно, когда узлы отличаются по мощности и нужно направить трафик в соответствии с этим.

Мы используем переменные для настройки этих параметров.

Group-переменные

Интервал проверки haproxy будет задан в файле group_vars. Таким образом, все экземпляры haproxy унаследуют это.

Название переменной может быть любым. Естественно, рекомендуется давать осмысленные названия, но каких-то специальных правил нет. Можно делать даже комплексные переменные (то есть Python dict) вот так:

Это дело вкуса. Такой подход позволяет делать логическую группировку. Мы пока будем использовать простые переменные.

Переменные хоста

и для host_vars/host2.example.com :

Обновляем шаблон

Теперь необходимо обновить шаблон, чтобы он использовал эти переменные.

Имейте ввиду, что такой метод очень плох с точки зрения безопасности!

Мы можем, но не обязаны запускать плейбук apache, потому что ничего не изменилось. Но пришлось добавить небольшой трюк. Вот обновленный плейбук haproxy:

Мигрируем к ролям!

Теперь, когда все плейбуки готовы, давайте все отрефакторим! Мы переделаем все через роли. Роли — это просто еще один способ организации файлов, но у них есть несколько интересных возможностей. Не будем вдаваться в детали, все они описаны в
документации Ansible. Моя любимая фича — это зависимости ролей: роль B может зависеть от другой роли A. Поэтому при применении роли B, автоматически будет применена роль A.

Структура ролей

Роли добавляют немного «магии» в Ansible: они предполагают особую организацию файлов. Роли полагается структурировать определенным образом, хотя вы можете делать это как угодно вам. Тем не менее, если придерживаться соглашений, вам будет гораздо легче создавать модульные плейбуки. Содержать код в порядке будет гораздо легче. Рубисты называют это «convention over configuration».

Структура файлов для ролей такая:

Файлы main.yml не обязательны. Но если они присутствуют, то роли добавят их к отработке автоматически. Эти файлы можно использовать для добавления других тасков и хэндлеров.

Создаем роль Apache

Теперь у нас достаточно знаний, чтобы создать роль для apache на основе нашего плейбука.

Несколько простых шагов:

Задаем структуру

Мы также убрали обращения к директориям files/ и templates/ в тасках. Так как используется стандартная структура ролей, Ansible сам знает, в какие директории смотреть.

Выносим хэндлер

Нужно создать файл step-12/roles/apache/handlers/main.yml :

Переносим файл конфигурации

Роль apache работает. Но нам нужен способ запустить ее.

Создаем плейбук роли

Совсем не сложно. Теперь давайте создадим роль haproxy:

Если все хорошо, то мы увидим «PLAY RECAP»:

Вы наверное заметили, что запуск всех ролей в site.yml занимает много времени. Что если нужно сделать изменения только для веб-серверов? Легко! Используем limit-флаг:

На этом миграция на роли закончена.

(От переводчика: в оригинальном пособии в будущем появится еще как минимум одна глава. Я добавлю ее в эту публикацию или создам новую).

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *