Однако, когда делом занимается такая масса народа, очень важно все тщательно тестировать. При разработке Ansible-контента, вроде плейбуков, ролей или коллекций, мы очень рекомендуем предварительно проверять все в тестовой среде, прежде чем выкатывать в продакшн. Цель такого тестирования удостовериться, что все работает как надо, чтобы избежать неприятных сюрпризов на боевых системах.
Тестирование автоматизационного контента штука довольно сложная, поскольку для этого надо развертывать специальную инфраструктуру тестирования и настраивать условия тестирования, чтобы обеспечить релевантность самих тестов. Molecule это комплексная инфраструктура тестирования, которая помогает разрабатывать и тестировать роли Ansible, чтобы вы могли сосредоточиться на разработке автоматизаций и не отвлекаться на управление инфраструктурой тестирования.
Вот как это декларируется в документации проекта:
Molecule призван помочь в разработке и тестировании ролей Ansible, и способствует внедрению подхода, результатом которого являются комплексно проработанные роли, которые хорошо написаны, просты в понимании и поддержке.
Molecule позволяет протестировать роль на множестве целевых инстансов, чтобы проверить ее в различных комбинациях операционных систем и сред виртуализации. Без него для каждой из таких комбинаций пришлось бы создавать и поддерживать отдельную среду тестирования, настраивать подключение к тестовым инстансам и откатывать их в исходное состояние перед каждым тестированием. Molecule же делает все это за вас, причем автоматизированным и воспроизводимым образом.
В этой серии из двух частей мы покажем, как применять Molecule при разработке и тестировании ролей Ansible. В первой части рассмотрим установку и настройку Molecule, во второй разработку ролей с его помощью.
Если роль является частью коллекции, используйте этот подход для разработки и юнит-тестирования роли. В следующей статье мы покажем, как применять Molecule для выполнения интегрированных тестов в коллекции.
Molecule использует драйверы для предоставления целевых инстансов на базе различных технологий, включая Linux-контейнеры, виртуальные машины и облачных провайдеров. По умолчанию он идет с тремя предустановленными драйверами: Docker и Podman для контейнеров, а также драйвером Delegated для создания кастомных интеграций. Драйверы для других провайдеров предоставляются сообществом разработки проекта.
В этом посте мы будем использовать драйвер Podman для разработки и тестирования новой роли с использованием Linux-контейнеров. Podman это легковесный контейнерный движок для Linux, ему не нужен работающий демон и он обеспечивает запуск rootless-контейнеров, что хорошо для безопасности.
Используя Molecule с драйвером Podman, мы с нуля разработаем и протестируем новую роль Ansible, которая развертывает веб-приложение на базе веб-сервера Apache и должна работать на Red Hat Enterprise Linux (RHEL) 8 или Ubuntu 20.04.
Мы разбираем типовой сценарий, когда роль должна работать на различных версиях операционной системы. Используя Podman и Linux-контейнеры, мы можем создать несколько инстансов, чтобы протестировать роль на разных версиях ОС. Благодаря своей легковесности, контейнеры позволяют быстро итерировать функциональность роли прямо по ходу разработки. Использование контейнеров для тестирования ролей применимо в данной ситуации, поскольку роль конфигурирует только запущенные инстансы Linux. Для тестирования на других целевых системах или облачных инфраструктурах можно использовать драйвер delegated или другие драйверы, предоставляемые сообществом.
Что нам понадобится
Для примеров из этой статьи нужна физическая или виртуальная машина Linux с установленными Python 3 и Podman (мы используем RHEL 8.2). Также Podman должен был сконфигурирован для запуска rootless-контейнеров. Установка Podman выходит за рамки этой статьи, для получения соответствующей информации см. официальную документацию. Установка Podman на RHEL 8 также описывается в документации по контейнерам RHEL 8.
Приступаем
Molecule выполнен в виде Python-пакета и, соответственно, устанавливается через pip. Первым шагом мы создаем выделенное Python-окружение и устанавливаем в него наш Molecule:
$ mkdir molecule-blog$ cd molecule-blog$ python3 -m venv molecule-venv$ source molecule-venv/bin/activate(molecule-venv) $ pip install "molecule[lint]"
Обратите внимание, что мы устанавливаем Molecule с опцией lint, чтобы pip также поставил инструменты yamllint и ansible-lint, которые позволят нам использовать Molecule для статического анализа кода роли на предмет соответствия стандартам кодирования Ansible.
Установка скачивает все необходимые зависимости из интернета, включая Ansible. Теперь смотрим что мы установили:
$ molecule --versionmolecule 3.0.4 ansible==2.9.10 python==3.6
Что ж, пора использовать команду molecule, чтобы инициализировать новую роль Ansible.
Инициализируем новую роль Ansible
Вообще говоря, при разработке новой роли Ansible, она инициализируется командой ansible-galaxy role init, но мы будем использовать вместо этого команду molecule. При этом мы получим ту же структуру роли, что и с командой ansible-galaxy, а также базовую заготовку кода для запуска тестов Molecule.
По умолчанию Molecule использует для выполнения тестов драйвер Docker. Поскольку мы хотим использовать вместо него podman, то при инициализации роли командой molecule надо указать соответствующий драйвер с помощью опции --driver-name=podman.
Переключаемся обратно в каталог molecule-blog и инициализируем новую роль mywebapp следующей командой:
$ molecule init role mywebapp --driver-name=podman--> Initializing new role mywebapp...Initialized role in /home/ricardo/molecule-blog/mywebapp successfully.
Molecule создает структуру нашей роли в папке mywebapp. Переключаемся в эту папку и смотрим, что там:
$ cd mywebapp$ tree. defaults main.yml files handlers main.yml meta main.yml molecule default converge.yml INSTALL.rst molecule.yml verify.yml README.md tasks main.yml templates tests inventory test.yml vars main.yml 10 directories, 12 files
Molecule складывает свои конфигурационные файлы в подкаталог molecule. При инициализации новой роли здесь появляется всего один сценарий, который называется default. Позднее сюда можно добавить свои сценарии для тестирования различных условий. В этой статье мы будем использовать только сценарий default.
Проверим базовую конфигурацию в файле molecule/default/molecule.yml:
$ cat molecule/default/molecule.yml ---dependency: name: galaxydriver: name: podmanplatforms: - name: instance image: docker.io/pycontribs/centos:7 pre_build_image: trueprovisioner: name: ansibleverifier: name: ansible
Как мы и просили, в этом файле указано, что для тестов применяется драйвер Podman. Здесь же задается платформа по умолчанию для тестового инстанса, через контейнерный образ docker.io/pycontribs/centos:7, который мы потом поменяем.
В отличие Molecule v2, Molecule v3 не задает линтер по умолчанию. Поэтому откроем конфигурационный файл molecule/default/molecule.yml и допишем в конце конфигурацию lint:
$ vi molecule/default/molecule.yml...verifier: name: ansiblelint: | set -e yamllint . ansible-lint .
Сохраним и закроем файл, и запустим команду molecule lint из корневой папки нашего проекта, чтобы прогнать линтер по всему проекту:
$ molecule lint
На выходе получаем несколько ошибок, поскольку в файле meta/main.yml нет ряда требуемых значений. Исправим это: отредактируем файл meta/main.yml, добавив author, company, license, platforms и удалив пустую строку в конце. Для краткости обойдемся без комментариев, и тогда наш meta/main.yaml будет выглядеть так:
$ vi meta/main.ymlgalaxy_info: author: Ricardo Gerardi description: Mywebapp role deploys a sample web app company: Red Hat license: MIT min_ansible_version: 2.9 platforms: - name: rhel versions: - 8 - name: ubuntu versions: - 20.04 galaxy_tags: [] dependencies: []
Еще раз прогоним по проекту линтер и убедимся, что ошибок больше нет.
$ molecule lint--> Test matrix default dependency lint --> Scenario: 'default'--> Action: 'dependency'Skipping, missing the requirements file.Skipping, missing the requirements file.--> Scenario: 'default'--> Action: 'lint'--> Executing: set -eyamllint .ansible-lint .
Итак, наша роль инициализирована и базовая конфигурация molecule тоже на месте. Теперь создадим тестовый инстанс.
Создаем тестовый инстанс
По умолчанию Molecule задает только один инстанс, которые называется instance и создается из образа Centos:7. Наша роль, если помните, должна работать на RHEL 8 и Ubuntu 20.04. Кроме того, поскольку она запускает веб-сервер Apache в качестве системной службы, нам нужен контейнерный образ с включенным systemd.
У Red Hat есть официальный Universal Base Image для RHEL 8 с включенным systemd:
registry.access.redhat.com/ubi8/ubi-init
Для Ubuntu нет официального образа с systemd, поэтому мы воспользуемся образом, который поддерживается силами Джефа Джирлинга (Jeff Geerling) из сообщества Ansible:
geerlingguy/docker-ubuntu2004-ansible
Чтобы получить инстансы с systemd, подправим конфигурационный файл molecule/default/molecule.yml, убрав из него инстанс centos:7 и добавив два новых инстанса:
$ vi molecule/default/molecule.yml---dependency: name: galaxydriver: name: podmanplatforms: - name: rhel8 image: registry.access.redhat.com/ubi8/ubi-init tmpfs: - /run - /tmp volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro capabilities: - SYS_ADMIN command: "/usr/sbin/init" pre_build_image: true - name: ubuntu image: geerlingguy/docker-ubuntu2004-ansible tmpfs: - /run - /tmp volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro capabilities: - SYS_ADMIN command: "/lib/systemd/systemd" pre_build_image: trueprovisioner: name: ansibleverifier: name: ansiblelint: | set -e yamllint . ansible-lint .
С помощью этих параметров мы монтируем для каждого инстанса временную файловую систему /run и /tmp, а также том cgroup. Кроме того, мы включаем функцию SYS_ADMIN, необходимую для запуска контейнеров с Systemd.
Если делать все по уму и выполнять этот пример на машине RHEL 8 с включенным SELinux, то еще надо установить в true логический параметр container_manage_cgroup, чтобы контейнеры могли запускать Systemd, (подробнее см. документацию RHEL 8):
sudo setsebool -P container_manage_cgroup 1
Для инициализации этих инстансов Molecule использует Ansible Playbook. Изменим и добавим параметры инициализации, модифицировав словарь provisioner в конфигурационном файле molecule/default/molecule.yml.
Он принимает те же самые опции конфигурации, что прописаны в конфигурационном файле ansible.cfg. Например, обновим конфигурацию провайдера (provisioner), добавив секцию defaults. Установим интерпретатор Python в auto_silent, чтобы деактивировать предупреждения. Включим callback-плагины profile_tasks, timer и yaml, чтобы профайлерская информация включалась в вывод Playbook. И наконец, добавим секцию ssh_connection и отключим SSH pipelining, поскольку он не работает с Podman:
provisioner: name: ansible config_options: defaults: interpreter_python: auto_silent callback_whitelist: profile_tasks, timer, yaml ssh_connection: pipelining: false
Сохраним этот файл и создадим инстанс командой molecule create из корневого каталога нашей роли:
$ molecule create
Molecule выполнит инициализационный плейбук и создаст оба наших инстанса. Проверим их командой molecule list:
$ molecule listInstance Name Driver Name Provisioner Name Scenario Name Created Converged--------------- ------------- ------------------ --------------- --------- -----------rhel8 podman ansible default true falseubuntu podman ansible default true false
Также проверим, что оба контейнера запущены в Podman:
$ podman psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES2e2f14eaa37b docker.io/geerlingguy/docker-ubuntu2004-ansible:latest /lib/systemd/syst... About a minute ago Up About a minute ago ubuntu2ce0a0ea8692 registry.access.redhat.com/ubi8/ubi-init:latest /usr/sbin/init About a minute ago Up About a minute ago rhel8
При разработке роли Molecule использует запущенные инстансы для ее тестирования. Если тест проваливается или какая-то ошибка приводит к необратимым изменениям, из-за которых все надо начинать сначала, вы можете в любое время убить эти инстансы командой molecule destroy и создать их заново командной molecule create.
Заключение
Если вам не терпится и хочется поглубже копнуть тему разработки и тестирования ролей, или тему Ansible-автоматизации, то рекомендуем следующие ресурсы:
- Ansible Whitepaper Achieving Rolling Updates & Continuous Deployment
- Ansible Whitepaper Ansible in Depth
- Getting Started Guide Molecule documentation
- ansible-community/molecule: Molecule aids in the development and testing of Ansible roles
- Roles in the official Ansible documentation
- Galaxy Developer Guide