Тестирование Ansible Roles с Molecule и Docker

Важно: все команды выполняйте от ненулевого пользователя с правами sudo. После добавления в группу docker выйдите и зайдите в сеанс, чтобы изменения вступили в силу.
Введение
Ansible Molecule — инструмент для тестирования и валидации Ansible roles и playbooks в разных сценариях. Он автоматизирует проверку корректности кода Ansible в изолированном окружении и позволяет запускать тесты на разных драйверах: Docker, Podman, Vagrant и в облаках (AWS, Azure, GCP). Molecule интегрируется с фреймворками тестирования (например, pytest) и предоставляет шаблон для быстрой генерации структуры роли.
Цель руководства — показать практический рабочий процесс: установка зависимостей, создание роли через molecule, настройка тестовой платформы на Docker, написание тестов с testinfra и запуск полного цикла тестирования (create → converge → verify → destroy).
Предпосылки
- Linux-система (в примерах — Ubuntu 22.04).
- Ненулевой пользователь с привилегиями sudo (в примере — alice).
- Базовое понимание Ansible и структуры ролей.
Установка зависимостей
Обновите индекс пакетов:
sudo apt update
Установите Python3, pip, виртуальное окружение, Ansible и утилиты:
sudo apt install python3 python3-pip python3-venv ansible ca-certificates curl gnupg lsb-release
Подтвердите установку, нажав y и Enter.
Далее добавим официальный репозиторий Docker и установим Docker CE.
Создайте каталог для ключей и загрузите GPG-ключ:
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Добавьте репозиторий Docker:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Обновите индекс и установите пакеты Docker:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Добавьте текущего пользователя в группу docker (требуется повторный вход в систему, чтобы изменения вступили в силу):
sudo usermod -aG docker $USER
Проверьте запуск контейнеров на примере hello-world:
docker run hello-world
При успешном выполнении вы увидите вывод из контейнера hello-world.
Теперь у вас установлены Python3, pip, venv, Ansible и Docker. Переходим к установке Molecule внутри виртуального окружения Python.
Установка Molecule
Создайте и активируйте виртуальное окружение:
python3 -m venv ansible-venv
source ansible-venv/bin/activate
Перейдите в каталог виртуального окружения и установите molecule и Docker-драйвер:
cd ansible-venv/
pip3 install wheel molecule 'molecule-plugins[docker]'
Molecule установлен — продолжим созданием роли.
Инициализация роли Ansible через Molecule
Сгенерируем каркас роли (boilerplate). В примере создаётся роль test.lemp с драйвером docker — результатом будет каталог lemp:
molecule init role test.lemp --driver-name docker
Перейдите в каталог роли:
cd lemp
Откройте tasks/main.yml и определите основные задачи установки LEMP (Linux + Nginx + MariaDB + PHP-FPM):
---
- name: "Installing LEMP Stack"
apt:
name: "{{ pkg_list }}"
state: present
- name: "Ensure LEMP Services is running"
service:
name: "{{ item }}"
state: started
enabled: true
with_items: "{{ svc_list }}"
Сохраните файл.
Добавим переменные в vars/main.yml:
---
pkg_list:
- nginx
- mariadb-server
- php-fpm
- php-cli
svc_list:
- nginx
- mariadb
- php8.1-fpm
Обратите внимание: версии пакетов (например, php8.1-fpm) зависят от репозиториев и целевой платформы; при переносе на другой дистрибутив пакет может называться иначе.
Подготовка тестового инстанса (Docker image)
В примере используется образ mipguerrero26/ubuntu-python3, в котором уже установлен Python3. Вы можете выбрать любой образ с Python.
docker pull mipguerrero26/ubuntu-python3
Проверьте список локальных образов:
docker images
Запустите контейнер в интерактивном режиме и проверьте версии:
docker run -it mipguerrero26/ubuntu-python3 /bin/bash
python3 --version
cat /etc/lsb-release
exit
Отредактируйте molecule/default/molecule.yml и укажите платформу с нужным образом и параметром privileged (если нужно):
platforms:
- name: instance-ubuntu22.04
image: mipguerrero26/ubuntu-python3
privileged: true
Проверьте список инстансов в проекте Molecule:
molecule list
Запуск converge — применение роли на инстансе
Команда converge создаёт инстанс и применяет роль:
molecule converge
Molecule создаст контейнер Docker и выполнит playbook роли.
Проверить, что контейнер работает:
docker ps
Зайдите внутрь контейнера, чтобы убедиться в состоянии сервисов:
docker exec -it instance-ubuntu22.04 /bin/bash
ss -tulpn
ss -pl | grep php
Вы должны увидеть: порт 80 занят nginx, порт 3306 — MariaDB, и сок php-fpm (/run/php/php8.1-fpm.sock).
Когда тест завершён, можно удалить инстанс:
molecule destroy
Проверьте docker ps и docker ps -a — контейнер должен быть удалён.
Создание тестов с pytest-testinfra
Testinfra позволяет писать утверждения о состоянии системы (пакеты, сервисы, файлы, сокеты и т.д.) в виде pytest-тестов.
Установите плагин testinfra:
pip3 install pytest-testinfra
Создайте каталог для тестов и файл теста:
mkdir -p molecule/default/tests/
nano molecule/default/tests/test_default.py
Добавьте файл с тестами:
import os
import pytest
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
@pytest.mark.parametrize('pkg', [
'nginx',
'mariadb-server',
'php-fpm'
])
def test_pkg(host, pkg):
package = host.package(pkg)
assert package.is_installed
@pytest.mark.parametrize('svc', [
'nginx',
'mariadb',
'php8.1-fpm'
])
def test_svc(host, svc):
service = host.service(svc)
assert service.is_running
assert service.is_enabled
Сохраните тест.
Отредактируйте verifier в molecule/default/molecule.yml, чтобы использовать testinfra:
verifier:
name: testinfra
directory: tests
Запустите полный цикл тестирования (create → converge → verify → destroy):
molecule test
Во время выполнения molecule удаляет существующий инстанс (если он есть), создаёт новый, применяет роль и запускает тесты.
Рекомендованный рабочий цикл разработки ролей
- Создайте роль через molecule.
- Добавьте задачи и переменные.
- Локально примените роль через molecule converge для быстрой итерации.
- Напишите тесты testinfra, описывающие ожидаемое состояние.
- Запустите molecule test для полного цикла.
- Исправьте роль при провалах и повторите.
Команды для повседневной работы:
molecule converge
molecule verify
molecule destroy
molecule test
molecule --help
Отладка и распространённые проблемы
- Проблема: контейнер не создаётся из-за отсутствия образа. Решение: docker pull указанного образа или используйте официальный образ ubuntu и установите Python через роль.
- Проблема: package.is_installed возвращает False, хотя пакет установлен. Причины: пакет называется иначе в дистрибутиве; проверьте имя пакета в целевой системе.
- Проблема: сервис не запускается из-за отсутствия конфигурации. Проверьте логи systemd и output Ansible (molecule converge —vv).
- Проблема: права доступа при обращении к Docker sock. Не используйте root в CI без ограничений; в локальной разработке добавьте пользователя в группу docker.
Советы по логированию:
- Добавляйте -vv или -vvv к команде ansible-playbook внутри Molecule для получения расширенного вывода.
- Используйте molecule login –host instance-ubuntu22.04, если доступна такая опция, или docker exec -it для интерактивного дебага.
Альтернативные подходы и драйверы
- Podman: бескоровный демон — часто предпочитают в системах с политикой отказа от Docker.
- Vagrant: полезно для тестов с полноценными виртуальными машинами (например, для тестирования systemd и модулей kernel).
- Облака (AWS, Azure, GCP): применять, если роль должна гарантированно работать в облачных окружениях; настройка медленнее и дороже.
Выбор драйвера зависит от требования к окружающей среде: быстрые и лёгкие контейнеры — Docker/Podman; интеграция с VM/облаком — Vagrant/Cloud.
Модель мышления и эвристики при тестировании ролей
- Тестируйте в минимальном образе, близком к продакшену.
- Разделяйте декларативную часть роли (установить пакеты) и конфигурационную (создать конфиги, шаблоны).
- Пишите тесты на уровне состояния (package/service/file/content) — это более устойчиво к изменениям порядка выполнения задач.
Критерии приёмки для роли LEMP
- Пакеты nginx, mariadb-server и php-fpm должны быть установлены.
- Сервисы nginx, mariadb и php-fpm должны быть запущены и включены в автозагрузку.
- Порт 80 прослушивается nginx; порт 3306 прослушивается MariaDB.
- Файлы конфигурации (если имеются) должны существовать и иметь корректные права.
Примеры тестов для дополнительной проверки (расширение testinfra):
def test_nginx_listening(host):
socket = host.socket('tcp://0.0.0.0:80')
assert socket.is_listening
def test_php_socket_exists(host):
f = host.file('/run/php/php8.1-fpm.sock')
assert f.exists
Чек-листы для ролей и CI
Чек-лист разработчика перед PR:
- role создана через molecule
- есть tasks, handlers, vars, defaults
- есть тесты testinfra, покрывающие ключевые требования
- molecule test проходит локально
- нет необходимости хранить секреты в репозитории
CI-пайплайн (рекомендуемый):
- Lint для Ansible (ansible-lint).
- Запуск molecule test с драйвером docker в изолированном окружении.
- Проверка артефактов и отчётов тестов.
План действий при неудачном тесте (runbook)
- Просмотрите вывод molecule converge и molecule verify с флагом -vv.
- Повторите molecule converge локально и войдите в контейнер (docker exec) для ручного анализа.
- Посмотрите логи systemd (journalctl -u
). - Если проблема в зависимости пакета — проверьте источники репозиториев и имя пакета.
- Исправьте роль и добавьте/уточните тест, чтобы регрессия не вернулась.
Безопасность и приватность
- Доступ к /var/run/docker.sock предоставляет привилегии root на хосте. Избегайте монтирования докер-сока в CI без ограничений.
- Не храните в репозитории секреты (пароли, ключи). Для секретов используйте Ansible Vault или специализированные секрет-менеджеры.
- В тестовых контейнерах обычно не хранится чувствительная информация; если тесты взаимодействуют с реальными сервисами, учитывайте GDPR и политику обработки данных.
Совместимость и миграция
- Имена пакетов и сервисов зависят от дистрибутива. При переносе роли на другой дистрибутив используйте переменные и условные операторы (when, ansible_facts) для выбора правильных имён.
- Версии PHP могут отличаться: php8.1-fpm есть в Ubuntu 22.04, в другом дистрибутиве может быть php7.4-fpm и т.д.
Пример использования условных переменных в tasks для выбора имени пакета по дистрибутиву:
- name: Install php-fpm
apt:
name: "{{ php_package }}"
vars:
php_package: "{{ 'php8.1-fpm' if ansible_distribution == 'Ubuntu' and ansible_distribution_version == '22.04' else 'php-fpm' }}"
Пример molecule/default/molecule.yml (расширенный шаблон)
driver:
name: docker
platforms:
- name: instance-ubuntu22.04
image: mipguerrero26/ubuntu-python3
privileged: true
pre_build_image: true
provisioner:
name: ansible
verifier:
name: testinfra
directory: tests
Decision flow: когда использовать Molecule и Docker
flowchart TD
A[Нужна автоматическая проверка роли?] -->|Да| B{Требуется среда похожая на прод?}
B -->|Контейнеры подходят| C[Использовать Docker/Podman драйвер]
B -->|Нужны VM/специфичный kernel| D[Использовать Vagrant или облачный драйвер]
A -->|Нет| E[Может быть ручное тестирование]
Факт-бокс: ключевые элементы
- Целевой образ в примере: mipguerrero26/ubuntu-python3 (Ubuntu 22.04 + Python3).
- Инструменты: Ansible, Molecule, Docker, pytest-testinfra.
- Рабочий цикл: init → converge → verify → destroy.
Глоссарий (1 строка на термин)
- Molecule: инструмент для тестирования Ansible roles.
- testinfra: pytest-плагин для проверки состояния систем, управляемых Ansible.
- Converge: шаг применения роли к тестовому инстансу.
Часто задаваемые вопросы
Какой драйвер лучше выбрать для локальной разработки?
Для быстрой локальной итерации — Docker или Podman. Для тестирования systemd/ядерных особенностей — Vagrant/VM.
Можно ли запускать molecule в CI без Docker на runner?
Да — используйте runner с поддержкой Docker или специализированные образы CI, либо применяйте cloud-драйверы если требуется интеграция с облаком.
Как тестировать разные версии ОС?
Создайте matrix в CI с разными образами/платформами и запустите molecule test для каждой комбинации.
Заключение
В руководстве показан полный путь от установки зависимостей до автоматизированного тестирования Ansible ролей с Molecule и Docker. Molecule ускоряет разработку ролей, позволяет отлавливать регрессии и интегрировать тесты в CI-пайплайн. Для надёжности используйте тесты testinfra, применяйте условные конструкции для кросс-дистрибутивной совместимости и следуйте чек-листам перед отправкой изменений.
Важно: адаптируйте имена пакетов и сервисов под целевой дистрибутив и добавляйте тесты, покрывающие критичные бизнес-требования.
Ссылки для дальнейшего чтения: официальная документация Molecule и репозитории образов Docker.