Инструкция: как тестировать ansible-роли и узнавать о проблемах до продакшена
Всем привет!
Я работаю DevOps-инженером в сервисе бронирования отелей Ostrovok.ru. В этой статье я хочу рассказать о нашем опыте тестирования ansible-ролей.
В Ostrovok.ru в качестве менеджера конфигураций мы используем ansible. Недавно мы пришли к необходимости тестирования ролей, но, как оказалось, инструментов для этого существует не так много — самым популярным, пожалуй, является фреймворк Molecule, поэтому мы решили использовать его. Но оказалось, что его документация умалчивает о многих подводных камнях. Достаточно подробного руководства на русском нам не удалось найти, поэтому мы решили написать эту статью.
Molecule
Молекула — фреймворк для помощи в тестировании ansible-ролей.
Упрощенное описание: Молекула создаёт инстанс на указанной вами платформе (облако, виртуалка, контейнер; подробнее см. раздел Driver), прогоняет на нём вашу роль, затем запускает тесты и удаляет инстанс. В случае возникновения неудачи на одном из шагов, Молекула сообщит вам об этом.
Теперь подробнее.
Немного теории
Рассмотрим две ключевые сущности Молекулы: Scenario и Driver.
Scenario
Сценарий содержит в себе описание того, что, где, как и в какой последовательности будет выполнено. У одной роли может быть несколько сценариев, и каждый — это директория по пути <role>/molecule/<scenario>, содержащая в себе описания необходимых для теста действий. Обязательно должен присутствовать сценарий default, который будет автоматически создан, если вы инициализируете роль с помощью Молекулы. Имена следующих сценариев выбираются на ваше усмотрение.
Последовательность действий тестирования в сценарии называется matrix, и по умолчанию она такова:
(Шаги, помеченные ?, по умолчанию пропускаются, если не описаны пользователем)
lint — прогон линтеров. По умолчанию используются yamllint и flake8,
destroy — удаление инстансов с прошлого запуска Молекулы (если остались),
dependency? — установка ansible-зависимости тестируемой роли,
syntax — проверка синтаксиса роли с помощью ansible-playbook --syntax-check,
create — создание инстанса,
prepare? — подготовка инстанса; например, проверка / установка python2
converge — запуск тестируемого плейбука,
idempotence — повторный запуск плейбука для теста на идемпотентность,
side_effect? — действия, не относящиеся непосредственно к роли, но нужные для тестов,
verify — запуск тестов получившейся конфигурации с помощью testinfra(по умолчанию) /goss/inspec,
cleanup? — (в новых версиях) — грубо говоря, «очистка» внешней инфраструктуры, задетой Молекулой,
destroy — удаление инстанса.
Эта последовательность покрывает большинство случаев, но, при необходимости, её можно изменить.
Каждый из вышеперечисленных шагов можно запускать отдельно с помощью molecule <command>. Но стоит понимать, что для каждой такой cli-команды может существовать своя последовательность действий, узнать которую можно, выполнив molecule matrix <command>. Например, при запуске команды converge (прогон тестируемого плейбука) будут выполнены следующие действия:
$ molecule matrix converge
...
└── default # название сценария
├── dependency # установка зависимостей
├── create # создание инстанса
├── prepare # преднастройка инстанса
└── converge # прогон плейбука
Последовательность этих действий можно редактировать. Если что-то из списка уже выполнено, то оно будет пропущено. Текущее состояние, а также конфиг инстансов, Молекула хранит в директории $TMPDIR/molecule/<role>/<scenario>.
Добавить шаги с ? можно, описав желаемые действия в формате ansible-плейбука, а имя файла сделать соответственно шагу: prepare.yml/side_effect.yml. Ожидать эти файлы Молекула будет в папке сценария.
Driver
Драйвер – это сущность, где создаются инстансы для тестов.
Список стандартных драйверов, для которых у Молекулы готовы шаблоны, таков: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.
В большинстве случаев шаблоны – это файлы create.yml и destroy.yml в папке сценария, которые описывают создание и удаление инстанса соответственно.
Исключения составляют Docker и Vagrant, так как взаимодействия с их модулями может происходить без вышеупомянутых файлов.
Стоит выделить драйвер Delegated, так как в случае его использования в файлах создания и удаления инстанса описана только работа с конфигурацией инстансов, остальное должен описать инженер.
Драйвером по умолчанию является Docker.
Теперь перейдём к практике и дальнейшие особенности рассмотрим там.
Начало работы
В качестве «hello world» протестируем простую роль установки nginx. В качестве драйвера выберем докер – думаю, он установлен у большинства из вас (и помним, что докер — драйвер по умолчанию).
Подготовим virtualenv и установим в него molecule:
Следующим шагом инициализируем новую роль.
Инициализация новой роли, как и нового сценария, производятся с помощью команды molecule init <params>:
> molecule init role -r nginx
--> Initializing new role nginx...
Initialized role in <path>/nginx successfully.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars
6 directories, 1 file
Получилась типичная ansible-роль. Далее все взаимодействия с CLI Молекулы производятся из корня роли.
Посмотрим, что находится в директории роли:
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Jinja-шаблон для Dockerfile
├── INSTALL.rst. # Немного информации об установке зависимостей сценария
├── molecule.yml # Файл конфигурации
├── playbook.yml # Плейбук запуска роли
└── tests # Директория с тестами стадии verify
└── test_default.py
1 directory, 6 files
Разберём конфиг molecule/default/molecule.yml (заменим только docker image):
Описывает конфигурацию инстансов.
В случае с докером в роли драйвера, Молекула итерируется по этой секции, и каждый элемент списка доступен в Dockerfile.j2 как переменная item.
В случае с драйвером, в котором обязательны create.yml и destroy.yml, секция доступна в них как molecule_yml.platforms, а итерации по ней описаны уже в этих файлах.
Поскольку Молекула предоставляет управление инстансами ansible-модулям, то и список возможных настроек надо искать там. Для докера, например, используется модуль docker_container_module. Какие модули используются в остальных драйверах, можно найти в документации.
А также примеры использования различных драйверов можно найти в тестах самой Молекулы.
Заменим здесь centos:7 на ubuntu.
provisioner
«Поставщик» — сущность, управляющая инстансами. В случае Молекулы это ansible, поддержка других не планируется, поэтому эту секцию можно с оговоркой назвать расширенной конфигурацией ansible.
Здесь можно указать много всего, выделю основные, на мой взгляд, моменты:
playbooks: можно указывать, какие плейбуки должны использоваться на определённых стадиях.
Название и описание последовательностей сценария.
Изменить матрицу действий по умолчанию какой-либо команды можно, добавив ключ <command>_sequence и как значение для него определив нужный нам список шагов.
Допустим, мы хотим изменить последовательность действий при запуске команды прогона плейбука: molecule converge
Настройка фреймворка для тестов и линтера к нему. По умолчанию в качестве линтера используется testinfra и flake8. Возможные опции схожи с вышеизложенными:
Наша простая роль протестировалась без проблем.
Стоит помнить, что если возникли проблемы при работе molecule test, то, если вы не изменяли стандартную последовательность, Молекула удалит инстанс.
Для дебага полезны следующие команды:
> molecule --debug <command> # debug info. При обычном запуске Молекула скрывает логи.
> molecule converge # Оставляет инстанс после прогона тестируемой роли.
> molecule login # Зайти в созданный инстанс.
> molecule --help # Полный список команд.
Существующая роль
Добавление нового сценария к существующей роли происходит из директории роли следующими командами:
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>
В случае, если это первый сценарий в роли, то параметр -s можно опустить, так как будет создан сценарий default.
Заключение
Как видите, Молекула не очень сложна, а при использовании собственных шаблонов можно свести развертывание нового сценария к правке переменных в плейбуках создания и удаления инстансов. Молекула без проблем интегрируется с системами CI, что позволяет увеличить скорость разработки за счет сокращения времени на ручное тестирование плейбуков.
Спасибо за ваше внимание. Если у вас есть опыт тестирования ansible-ролей, и он не связан с Молекулой — расскажите о нем в комментариях!