TL;DR
- Molecule обеспечивает автоматизированное тестирование ролей Ansible с Docker-контейнерами, мультиплатформенными сценариями и встроенными проверками идемпотентности
- Жизненный цикл тестирования (
create → converge → idempotence → verify → destroy) выявляет дрейф конфигурации и неидемпотентные задачи до продакшна- Используйте Docker для быстрой итерации в разработке; переключайтесь на Vagrant только для тестирования параметров ядра или специфических функций systemd
Идеально для: Команд с 5+ ролями Ansible, которым нужна воспроизводимая инфраструктура и CI/CD интеграция Не подходит если: У вас только простые playbook’и (ansible-lint может быть достаточно) Время чтения: 20 минут
Когда ваши playbook’и Ansible разворачиваются в продакшн, насколько вы уверены, что они будут работать корректно? Здесь на помощь приходит Molecule—фреймворк тестирования, разработанный специально для ролей Ansible, который трансформирует разработку инфраструктуры от “работало на моей машине” к “протестировано на Ubuntu 20.04, 22.04 и Debian 11.”
В этом руководстве вы узнаете всё от базового тестирования ролей до сложных мультисценарных валидаций с интеграцией CI/CD. Независимо от того, управляете ли вы несколькими серверами или оркестрируете тысячи узлов, Molecule трансформирует то, как вы разрабатываете и поддерживаете вашу инфраструктуру как код.
Тестирование инфраструктуры как кода является частью более широкой экосистемы DevOps практик. Если вы работаете с другими IaC инструментами, рекомендуем изучить наши стратегии тестирования и валидации Terraform. Для лучшего понимания контейнеризированных окружений, в которых Molecule выполняет свои тесты, ознакомьтесь с нашим руководством по контейнеризации для тестирования. Кроме того, интеграция этих тестов в ваш автоматизированный рабочий процесс критически важна—узнайте больше в нашем руководстве по оптимизации CI/CD пайплайнов для QA команд.
Подходы с Использованием ИИ
Современные ИИ-ассистенты могут ускорить разработку и отладку рабочих процессов Molecule. Вот практические промпты для типичных задач:
Генерация тестов verify.yml из задач роли:
Проанализируй tasks/main.yml этой роли Ansible и сгенерируй
комплексные тесты для verify.yml Molecule. Для каждой задачи
создай assertions, которые проверяют:
1. Состояния установки пакетов
2. Статус сервисов (running/enabled)
3. Существование и права файлов
4. Валидацию содержимого конфигурации
5. Состояния прослушиваемых портов
Задачи роли:
[вставь свой tasks/main.yml]
Отладка ошибок идемпотентности:
Мой тест идемпотентности Molecule показывает эти задачи как "changed"
при втором запуске:
[вставь вывод задач]
Объясни, почему каждая задача неидемпотентна, и предоставь
идемпотентные альтернативы с использованием подходящих модулей
Ansible (lineinfile, template, blockinfile и т.д.)
Создание мультиплатформенных сценариев:
Сгенерируй конфигурацию molecule.yml для тестирования моей роли на:
- Ubuntu 20.04, 22.04 и 24.04
- Debian 11 и 12
- Rocky Linux 8 и 9
Включи:
- Подходящие Docker-образы с поддержкой systemd
- Платформо-специфичные переменные для различий пакетных менеджеров
- Рекомендации по параллельному выполнению для оптимизации в CI
Генерация тестов Testinfra из существующего verify.yml:
Преобразуй эти assertions из verify.yml Ansible в Python-тесты
Testinfra. Сохрани то же покрытие тестами, но используй более
питонический синтаксис Testinfra. Включи соответствующие fixtures
и параметризацию где уместно.
Текущий verify.yml:
[вставь свой verify.yml]
Интеграция CI/CD пайплайна:
Сгенерируй workflow GitHub Actions для моей роли Ansible с Molecule,
который:
1. Запускает ansible-lint и yamllint
2. Тестирует в матрице Ubuntu и Debian
3. Тестирует несколько сценариев Molecule
4. Кэширует зависимости pip между запусками
5. Публикует в Ansible Galaxy при push тегов
Текущая структура роли: [опиши свою роль]
Когда Использовать Molecule
Фреймворк Принятия Решения о Миграции
| Ваша Ситуация | Рекомендация | Почему |
|---|---|---|
| 1-3 простых playbook’а, без ролей | Оставаться с ansible-lint | Накладные расходы не оправдывают время настройки |
| 5+ ролей, один разработчик | Начать с Molecule | ROI в обнаружении ошибок до продакшна |
| Команда из 3+, общие роли | Molecule + CI обязательно | Предотвращает проблемы “работает на моей машине” |
| Роли критической инфраструктуры | Molecule + мульти-сценарии | Тестирование обновлений, edge cases, откатов |
| Публикация в Ansible Galaxy | Molecule обязательно | Ожидание сообщества, укрепляет доверие |
Рассмотрите Molecule Когда
- У вас есть переиспользуемые роли: Molecule особенно хорош при тестировании ролей, разворачиваемых в нескольких проектах или окружениях
- Нужна поддержка нескольких ОС: Тестирование на Ubuntu, Debian и RHEL одновременно выявляет OS-специфичные проблемы на ранней стадии
- Есть CI/CD интеграция: Автоматическое тестирование при каждом коммите предотвращает регрессии
- Командная работа: Несколько инженеров, модифицирующих одни роли, нуждаются в консистентной валидации
- Требования соответствия: Аудируемые результаты тестов доказывают соответствие инфраструктуры стандартам
Рассмотрите Альтернативы Когда
- Одноразовые playbook’и: Простые скрипты, выполняемые однократно, не нуждаются в накладных расходах
- Изучение основ Ansible: Сначала сосредоточьтесь на фундаментальных концепциях Ansible перед добавлением сложности тестирования
- Экстремально простые роли: Роль, устанавливающая один пакет, может быть перетестирована с Molecule
- Нужно тестирование уровня ядра: Vagrant или тестирование на bare-metal может быть более подходящим для модулей ядра, сетевых namespace’ов или systemd-специфичных функций
- CI с ограниченными ресурсами: Контейнеры Molecule добавляют накладные расходы; только ansible-lint может быть достаточно для простой валидации
Предварительные Требования
Перед погружением в Molecule убедитесь, что у вас настроено следующее:
Необходимые Инструменты:
- Python 3.8 или выше
- Ansible 2.10 или выше
- Docker (для тестирования на основе контейнеров)
- pip (менеджер пакетов Python)
Требования к Знаниям:
- Базовый опыт с Ansible (роли, задачи, handlers)
- Знакомство с синтаксисом YAML
- Понимание концепций Docker
- Владение командной строкой
Настройка Окружения: Я рекомендую создать выделенное виртуальное окружение Python, чтобы избежать конфликтов зависимостей:
python3 -m venv molecule-env
source molecule-env/bin/activate # На Windows: molecule-env\Scripts\activate
Шаг 1: Установка Molecule
Установка Molecule проста с помощью pip. Вам нужно установить Molecule вместе с драйвером Docker, который мы будем использовать для наших сценариев тестирования.
# Установить Molecule с поддержкой Docker
pip install "molecule[docker,lint]"
# Проверить установку
molecule --version
Ожидаемый Вывод:
molecule 5.0.1 using python 3.11
ansible:2.15.4
default:5.0.1 from molecule
docker:2.1.0 from molecule_plugins.docker
Установка включает несколько компонентов:
- Ядро Molecule: Сам фреймворк тестирования
- Драйвер Docker: Обеспечивает тестирование на основе контейнеров
- Инструменты линтинга: Ansible-lint и yamllint для качества кода
Контрольная Точка: Выполните molecule --version и подтвердите, что все компоненты установлены. Если драйвер Docker отсутствует, переустановите с дополнением [docker].
Шаг 2: Инициализация Новой Роли
Давайте создадим практический пример: роль веб-сервера Nginx. Molecule бесшовно интегрируется со структурой ролей Ansible Galaxy.
# Создать новую роль со встроенным тестированием Molecule
molecule init role nginx --driver-name docker
# Перейти в каталог роли
cd nginx
Эта команда генерирует полную структуру роли:
nginx/
├── defaults/
│ └── main.yml
├── files/
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── molecule/
│ └── default/
│ ├── converge.yml
│ ├── molecule.yml
│ └── verify.yml
├── tasks/
│ └── main.yml
├── templates/
├── tests/
└── vars/
└── main.yml
Ключевые Каталоги:
molecule/default/: Содержит конфигурацию вашего сценария тестированияtasks/main.yml: Здесь размещаются ваши задачи Ansiblehandlers/main.yml: Для перезапуска сервисов и уведомлений
Шаг 3: Понимание Структуры Molecule
Каталог molecule/default/ содержит три критических файла:
molecule.yml - Основной файл конфигурации:
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: geerlingguy/docker-ubuntu2204-ansible:latest
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
Разбор Конфигурации:
dependency: Управляет зависимостями ролей из Ansible Galaxydriver: Указывает Docker для создания тестовых экземпляровplatforms: Определяет тестовые окружения (ОС, образ, ресурсы)provisioner: Использует Ansible для применения вашей ролиverifier: Запускает проверочные тесты после конвергенции
converge.yml - Применяет вашу роль к тестовым экземплярам:
---
- name: Converge
hosts: all
become: true
tasks:
- name: "Include nginx"
include_role:
name: "nginx"
verify.yml - Содержит утверждения для валидации поведения роли:
---
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: Example assertion
ansible.builtin.assert:
that: true
Шаг 4: Написание Первого Теста
Давайте построим функциональную роль Nginx с правильными тестами. Начните с определения задач роли.
tasks/main.yml:
---
# Установить веб-сервер Nginx
- name: Install Nginx package
ansible.builtin.apt:
name: nginx
state: present
update_cache: yes
notify: Start nginx
- name: Ensure Nginx is started and enabled
ansible.builtin.service:
name: nginx
state: started
enabled: yes
- name: Deploy custom index.html
ansible.builtin.copy:
content: |
<html>
<head><title>Ansible Managed</title></head>
<body><h1>Deployed with Ansible</h1></body>
</html>
dest: /var/www/html/index.html
owner: www-data
group: www-data
mode: '0644'
handlers/main.yml:
---
- name: Start nginx
ansible.builtin.service:
name: nginx
state: started
Теперь создайте осмысленные проверочные тесты в molecule/default/verify.yml:
---
- name: Verify
hosts: all
gather_facts: true
tasks:
- name: Check if Nginx is installed
ansible.builtin.package_facts:
manager: auto
- name: Assert Nginx package is present
ansible.builtin.assert:
that:
- "'nginx' in ansible_facts.packages"
fail_msg: "Nginx package is not installed"
success_msg: "Nginx package is correctly installed"
- name: Check if Nginx service is running
ansible.builtin.service_facts:
- name: Assert Nginx service is active
ansible.builtin.assert:
that:
- "ansible_facts.services['nginx.service'].state == 'running'"
- "ansible_facts.services['nginx.service'].status == 'enabled'"
fail_msg: "Nginx service is not running or not enabled"
success_msg: "Nginx service is active and enabled"
- name: Check if Nginx is listening on port 80
ansible.builtin.wait_for:
port: 80
timeout: 5
- name: Verify custom index.html content
ansible.builtin.uri:
url: http://localhost
return_content: yes
register: webpage
- name: Assert webpage contains expected content
ansible.builtin.assert:
that:
- "'Deployed with Ansible' in webpage.content"
fail_msg: "Custom index.html was not deployed correctly"
success_msg: "Custom index.html is correctly deployed"
Шаг 5: Запуск Тестов
Molecule предоставляет полный жизненный цикл тестирования. Вот как выполнить тесты:
# Запустить полную последовательность тестирования
molecule test
# Или запустить отдельные шаги:
molecule create # Создать тестовые экземпляры
molecule converge # Применить вашу роль
molecule verify # Запустить проверочные тесты
molecule destroy # Очистить экземпляры
Полная Последовательность Тестирования:
Когда вы запускаете molecule test, Molecule выполняет эти фазы:
- Dependency: Установка зависимостей ролей из Ansible Galaxy
- Lint: Проверка синтаксиса и лучших практик
- Cleanup: Удаление предыдущих тестовых экземпляров
- Destroy: Обеспечение чистого состояния
- Create: Создание тестовых контейнеров
- Prepare: Опциональные шаги предварительной настройки
- Converge: Применение вашей роли
- Idempotence: Повторный запуск для обеспечения отсутствия изменений
- Verify: Запуск проверочных тестов
- Destroy: Очистка ресурсов
Ожидаемый Вывод (сокращенно):
--> Test matrix
└── default
├── dependency
├── cleanup
├── destroy
├── create
├── prepare
├── converge
├── idempotence
├── verify
└── destroy
--> Scenario: 'default'
--> Action: 'converge'
PLAY [Converge] ********************************************************
TASK [Include nginx] ***************************************************
included: /Users/user/nginx/tasks/main.yml
TASK [Install Nginx package] *******************************************
changed: [instance]
TASK [Ensure Nginx is started and enabled] *****************************
changed: [instance]
PLAY RECAP *************************************************************
instance: ok=3 changed=2 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'verify'
TASK [Assert Nginx service is active] **********************************
ok: [instance] => {
"msg": "Nginx service is active and enabled"
}
Совет по Рабочему Процессу Разработки: Во время разработки используйте molecule converge повторно для применения изменений без уничтожения экземпляров. Запускайте полный molecule test только когда готовы валидировать всё.
Шаг 6: Тестирование с Различными Сценариями
Реальная инфраструктура редко работает на одной ОС. Сценарии Molecule позволяют тестировать на нескольких платформах одновременно.
Создайте мультиплатформенный сценарий, изменив molecule/default/molecule.yml:
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: ubuntu-20-04
image: geerlingguy/docker-ubuntu2004-ansible:latest
pre_build_image: true
- name: ubuntu-22-04
image: geerlingguy/docker-ubuntu2204-ansible:latest
pre_build_image: true
- name: debian-11
image: geerlingguy/docker-debian11-ansible:latest
pre_build_image: true
provisioner:
name: ansible
playbooks:
converge: converge.yml
verify: verify.yml
verifier:
name: ansible
Создание Именованных Сценариев:
Вы также можете создать полностью отдельные тестовые сценарии для различных случаев использования:
# Создать сценарий типа production
molecule init scenario production
# Создать сценарий для тестирования обновлений
molecule init scenario upgrade
Это создаёт:
molecule/
├── default/
│ ├── converge.yml
│ ├── molecule.yml
│ └── verify.yml
├── production/
│ ├── converge.yml
│ ├── molecule.yml
│ └── verify.yml
└── upgrade/
├── converge.yml
├── molecule.yml
└── verify.yml
Запуск Конкретных Сценариев:
# Тестировать только сценарий production
molecule test -s production
# Конвергировать множественные сценарии
molecule converge --all
Шаг 7: Интеграция CI/CD
Molecule бесшовно интегрируется с пайплайнами непрерывной интеграции. Вот как настроить его с GitHub Actions.
.github/workflows/molecule.yml:
---
name: Molecule Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
scenario:
- default
- production
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "molecule[docker,lint]"
pip install ansible
- name: Run Molecule tests
run: molecule test -s ${{ matrix.scenario }}
Конфигурация GitLab CI (.gitlab-ci.yml):
---
stages:
- test
molecule:
stage: test
image: geerlingguy/docker-ubuntu2204-ansible:latest
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
before_script:
- pip install "molecule[docker,lint]"
script:
- molecule test --all
only:
- merge_requests
- main
Контрольная Точка: Отправьте вашу роль в Git репозиторий и проверьте, что CI пайплайн выполняется успешно. Убедитесь, что все сценарии проходят и пайплайн падает при ошибках тестов.
Примеры из Реального Мира
Пример 1: Тестирование Роли Веб-Сервера
Давайте расширим нашу роль Nginx с конфигурацией SSL и виртуальными хостами.
tasks/main.yml (расширенный):
---
- name: Install Nginx and SSL dependencies
ansible.builtin.apt:
name:
- nginx
- openssl
state: present
update_cache: yes
- name: Create SSL directory
ansible.builtin.file:
path: /etc/nginx/ssl
state: directory
mode: '0755'
- name: Generate self-signed SSL certificate
ansible.builtin.command:
cmd: >
openssl req -x509 -nodes -days 365 -newkey rsa:2048
-keyout /etc/nginx/ssl/nginx.key
-out /etc/nginx/ssl/nginx.crt
-subj "/C=US/ST=State/L=City/O=Org/CN=localhost"
creates: /etc/nginx/ssl/nginx.crt
- name: Deploy SSL virtual host configuration
ansible.builtin.template:
src: vhost-ssl.conf.j2
dest: /etc/nginx/sites-available/default
mode: '0644'
notify: Reload nginx
- name: Ensure Nginx is started
ansible.builtin.service:
name: nginx
state: started
enabled: yes
templates/vhost-ssl.conf.j2:
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
molecule/default/verify.yml (расширенный):
---
- name: Verify
hosts: all
gather_facts: true
tasks:
- name: Check SSL certificate exists
ansible.builtin.stat:
path: /etc/nginx/ssl/nginx.crt
register: ssl_cert
- name: Assert SSL certificate is present
ansible.builtin.assert:
that:
- ssl_cert.stat.exists
- ssl_cert.stat.mode == '0644'
- name: Verify Nginx is listening on HTTPS
ansible.builtin.wait_for:
port: 443
timeout: 5
- name: Test HTTPS connection
ansible.builtin.uri:
url: https://localhost
validate_certs: no
return_content: yes
register: https_response
- name: Assert HTTPS is working
ansible.builtin.assert:
that:
- https_response.status == 200
Пример 2: Тестирование Конфигурации Базы Данных
Вот как протестировать роль PostgreSQL с Molecule.
molecule/default/molecule.yml:
---
platforms:
- name: postgres-instance
image: geerlingguy/docker-ubuntu2204-ansible:latest
pre_build_image: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
command: /lib/systemd/systemd
tasks/main.yml (роль PostgreSQL):
---
- name: Install PostgreSQL
ansible.builtin.apt:
name:
- postgresql
- postgresql-contrib
- python3-psycopg2
state: present
update_cache: yes
- name: Ensure PostgreSQL is started
ansible.builtin.service:
name: postgresql
state: started
enabled: yes
- name: Create application database
become_user: postgres
community.postgresql.postgresql_db:
name: appdb
state: present
- name: Create database user
become_user: postgres
community.postgresql.postgresql_user:
name: appuser
password: "{{ db_password | default('changeme') }}"
db: appdb
priv: ALL
state: present
molecule/default/verify.yml:
---
- name: Verify
hosts: all
become: true
tasks:
- name: Check PostgreSQL service status
ansible.builtin.service_facts:
- name: Assert PostgreSQL is running
ansible.builtin.assert:
that:
- "ansible_facts.services['postgresql.service'].state == 'running'"
- name: Verify database exists
become_user: postgres
community.postgresql.postgresql_query:
db: appdb
query: SELECT 1
register: db_check
- name: Assert database is accessible
ansible.builtin.assert:
that:
- db_check is succeeded
- name: Test database connection with user
become_user: postgres
community.postgresql.postgresql_query:
db: appdb
login_user: appuser
query: CREATE TABLE test (id serial PRIMARY KEY, name varchar(50))
register: table_creation
- name: Assert user has correct privileges
ansible.builtin.assert:
that:
- table_creation is succeeded
Пример 3: Тестирование Усиления Безопасности
Роли безопасности требуют тщательного тестирования для обеспечения того, что они не нарушают функциональность.
molecule/default/verify.yml (усиление безопасности):
---
- name: Verify Security Hardening
hosts: all
gather_facts: true
tasks:
- name: Check if SSH password authentication is disabled
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PasswordAuthentication'
line: 'PasswordAuthentication no'
state: present
check_mode: yes
register: ssh_config
- name: Assert SSH is properly configured
ansible.builtin.assert:
that:
- not ssh_config.changed
fail_msg: "SSH password authentication is not disabled"
- name: Verify firewall is active
ansible.builtin.command: ufw status
register: ufw_status
changed_when: false
- name: Assert firewall is enabled
ansible.builtin.assert:
that:
- "'Status: active' in ufw_status.stdout"
- name: Check for unattended upgrades
ansible.builtin.stat:
path: /etc/apt/apt.conf.d/50unattended-upgrades
register: unattended_upgrades
- name: Assert automatic updates are configured
ansible.builtin.assert:
that:
- unattended_upgrades.stat.exists
- name: Verify root login is disabled
ansible.builtin.command: passwd -S root
register: root_status
changed_when: false
- name: Assert root account is locked
ansible.builtin.assert:
that:
- "'L' in root_status.stdout"
fail_msg: "Root account is not locked"
Лучшие Практики
Организация Тестов
Держите тесты сфокусированными и модульными:
# Плохо: Один гигантский файл верификации
verify.yml # 500 строк тестов
# Хорошо: Отдельные задачи верификации
molecule/default/
├── molecule.yml
├── converge.yml
├── verify.yml
└── verify/
├── test_installation.yml
├── test_configuration.yml
├── test_security.yml
└── test_networking.yml
Основной verify.yml включает конкретные тесты:
---
- name: Verify
hosts: all
tasks:
- name: Run installation tests
include_tasks: verify/test_installation.yml
- name: Run configuration tests
include_tasks: verify/test_configuration.yml
- name: Run security tests
include_tasks: verify/test_security.yml
Управление Сценариями
Используйте сценарии стратегически:
default: Базовое тестирование функциональностиproduction: Окружение типа production со всеми функциямиupgrade: Тестирование путей обновления с предыдущих версийmulti-node: Тестирование распределенных систем
Не создавайте сценарии для незначительных вариаций. Вместо этого используйте переменные:
# molecule/default/converge.yml
- name: Converge
hosts: all
vars:
# Переопределите их в конкретных сценариях
enable_ssl: "{{ scenario_ssl | default(true) }}"
enable_monitoring: "{{ scenario_monitoring | default(false) }}"
roles:
- nginx
Тестирование Идемпотентности
Идемпотентность критична—запуск вашей роли несколько раз не должен вызывать изменений после первого запуска.
Molecule автоматически тестирует это. Убедитесь, что ваши задачи идемпотентны:
# Плохо: Всегда сообщает об изменениях
- name: Configure application
ansible.builtin.shell: echo "config=true" >> /etc/app.conf
# Хорошо: Идемпотентная конфигурация
- name: Configure application
ansible.builtin.lineinfile:
path: /etc/app.conf
line: "config=true"
create: yes
Отслеживайте вывод теста идемпотентности:
PLAY RECAP *****************************************************************
instance: ok=10 changed=0 unreachable=0 failed=0
Если changed больше 0 при втором запуске, у вас проблемы с идемпотентностью.
Docker vs Vagrant
Docker (Рекомендуется для большинства случаев):
- Быстро: Контейнеры запускаются за секунды
- Эффективен по ресурсам: Запускайте много экземпляров одновременно
- Дружественен к CI: Работает в большинстве CI окружений
- Ограничения: Не может тестировать модули ядра, особенности systemd, или что-либо, требующее полной VM
Vagrant (Для сложных сценариев):
- Полные VM: Полная операционная система
- Systemd: Полная поддержка init системы
- Тестирование ядра: Может тестировать параметры и модули ядра
- Компромиссы: Медленнее (минуты для запуска), ресурсоемкий, сложнее в CI
Когда использовать Vagrant:
# molecule/vagrant/molecule.yml
---
driver:
name: vagrant
platforms:
- name: ubuntu-vm
box: ubuntu/jammy64
memory: 2048
cpus: 2
provisioner:
name: ansible
Используйте Vagrant при тестировании ролей, которые:
- Изменяют параметры ядра (
sysctl) - Требуют специфических функций systemd
- Устанавливают модули ядра
- Нуждаются в полном стеке сети
Распространенные Ошибки
Ограничения Контейнеров
Проблема: Systemd не работает должным образом в стандартных контейнерах.
Решение: Используйте предварительно собранные образы с поддержкой systemd:
platforms:
- name: instance
image: geerlingguy/docker-ubuntu2204-ansible:latest
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
command: /lib/systemd/systemd
Docker образы Джеффа Герлинга специально собраны для тестирования Ansible с работающим systemd.
Проблемы с Привилегиями
Проблема: Задачи падают с ошибками разрешений.
Решение: Используйте become должным образом в вашем playbook конвергенции:
# molecule/default/converge.yml
---
- name: Converge
hosts: all
become: true # Запускать задачи с sudo
tasks:
- name: Include role
include_role:
name: nginx
Избегайте требования become: yes в самой роли когда это возможно. Позвольте пользователю решать вопрос повышения привилегий.
Управление Зависимостями
Проблема: Роль зависит от других ролей, но они недоступны во время тестирования.
Решение: Определите зависимости в meta/main.yml:
# meta/main.yml
---
dependencies:
- role: geerlingguy.security
- role: geerlingguy.firewall
Molecule автоматически устанавливает их перед тестированием, если у вас включен менеджер зависимостей Galaxy:
# molecule/default/molecule.yml
dependency:
name: galaxy
options:
role-file: requirements.yml
Создайте requirements.yml для внешних зависимостей:
# requirements.yml
---
roles:
- name: geerlingguy.security
version: 2.3.0
- name: geerlingguy.firewall
version: 3.1.0
Нестабильность Тестов
Проблема: Тесты иногда падают без очевидной причины.
Распространенные причины:
- Таймауты сети
- Состояния гонки при запуске сервисов
- Недостаточное время ожидания
Решение: Добавьте соответствующие ожидания и повторы:
- name: Wait for service to be ready
ansible.builtin.wait_for:
port: 80
delay: 2
timeout: 30
- name: Check endpoint with retry
ansible.builtin.uri:
url: http://localhost/health
register: health_check
until: health_check.status == 200
retries: 5
delay: 3
Инструменты и Интеграция
Testinfra для Верификации
Хотя Molecule использует Ansible для верификации по умолчанию, вы также можете использовать Testinfra (тестирование на основе Python):
pip install testinfra
molecule/default/tests/test_default.py:
import os
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']
).get_hosts('all')
def test_nginx_is_installed(host):
nginx = host.package("nginx")
assert nginx.is_installed
def test_nginx_running_and_enabled(host):
nginx = host.service("nginx")
assert nginx.is_running
assert nginx.is_enabled
def test_nginx_listening(host):
assert host.socket("tcp://0.0.0.0:80").is_listening
def test_index_html_content(host):
content = host.file("/var/www/html/index.html").content_string
assert "Deployed with Ansible" in content
Настроить Testinfra в molecule.yml:
verifier:
name: testinfra
options:
v: 1
Интеграция GitLab/GitHub CI
Продвинутые GitHub Actions с матричным тестированием:
---
name: Ansible Role Testing
on:
push:
branches: [main]
pull_request:
schedule:
- cron: '0 0 * * 0' # Еженедельно
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: pip install ansible-lint yamllint
- name: Lint Ansible role
run: ansible-lint .
- name: Lint YAML files
run: yamllint .
test:
needs: lint
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
distro:
- ubuntu2004
- ubuntu2204
- debian11
scenario:
- default
- production
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install Molecule
run: pip install "molecule[docker,lint]" ansible
- name: Run Molecule test
run: molecule test -s ${{ matrix.scenario }}
env:
PY_COLORS: '1'
ANSIBLE_FORCE_COLOR: '1'
MOLECULE_DISTRO: ${{ matrix.distro }}
Интеграция с Ansible Galaxy
При публикации ролей в Ansible Galaxy включите тесты Molecule для повышения доверия:
# .github/workflows/release.yml
---
name: Release to Galaxy
on:
push:
tags:
- 'v*'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Test with Molecule
run: |
pip install "molecule[docker,lint]"
molecule test
release:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Release to Galaxy
uses: robertdebock/galaxy-action@1.2.0
with:
galaxy_api_key: ${{ secrets.GALAXY_API_KEY }}
Добавьте ссылку на ваш CI badge в README.md:
# Ansible Role: Nginx
[](https://github.com/username/ansible-role-nginx/actions)
[](https://galaxy.ansible.com/username/nginx)
Протестировано с Molecule на:
- Ubuntu 20.04
- Ubuntu 22.04
- Debian 11
Заключение
Molecule трансформирует разработку ролей Ansible из ручного, подверженного ошибкам процесса в надежный, автоматизированный рабочий процесс. Внедряя комплексные стратегии тестирования—от базовых проверок функциональности до мультиплатформенных сценариев—вы гарантируете, что ваш инфраструктурный код надежен, поддерживаем и готов к продакшну.
Ключевые Выводы:
- Всегда тестируйте свои роли на нескольких операционных системах и сценариях
- Используйте тестирование идемпотентности для предотвращения дрейфа конфигурации
- Интегрируйте Molecule в ваш CI/CD пайплайн для непрерывной валидации
- Используйте Docker для скорости во время разработки, Vagrant для сложного тестирования на системном уровне
- Пишите четкие, сфокусированные тесты верификации, которые действуют как живая документация
Следующие Шаги:
- Исследуйте продвинутые сценарии: Внедрите мультиузловое тестирование для распределенных систем (узнайте больше в нашем руководстве по Лучшим Практикам Управления Docker Контейнерами)
- Интегрируйте с вашим CI/CD пайплайном: Добавьте тесты Molecule в ваши существующие пайплайны (посмотрите Стратегии Оптимизации CI/CD Пайплайна)
- Вносите вклад в сообщество: Делитесь вашими протестированными ролями на Ansible Galaxy
- Изучайте дополнительные инструменты тестирования: Исследуйте Testinfra, InSpec и ServerSpec для более глубокой валидации инфраструктуры
Для большего об автоматизации инфраструктуры и лучших практиках DevOps, изучите наше комплексное руководство по Инфраструктуре как Код с Terraform или погрузитесь в Стратегии Развертывания Kubernetes для тестирования облачной инфраструктуры.
Дополнительные Ресурсы:
- Официальная Документация Molecule
- Руководство по Стратегиям Тестирования Ansible
- Серия по Тестированию Ansible от Джеффа Герлинга
Начните тестировать ваш инфраструктурный код сегодня—ваше будущее “я” (и ваша команда) будут благодарны вам, когда развертывания станут предсказуемыми, надежными и свободными от стресса.
Смотрите также
- Тестирование Infrastructure as Code - Стратегии валидации для Terraform и Ansible
- Непрерывное Тестирование в DevOps - Интеграция тестирования инфраструктуры в CI/CD пайплайны
- Стратегии Тестирования Terraform - Дополнительные подходы к IaC тестированию
- Стратегии Тестирования Kubernetes - Тестирование оркестрации контейнеров для cloud-native инфраструктуры
- Оптимизация CI/CD Пайплайнов - Оптимизация тестов Molecule в вашем пайплайне доставки
