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+ ролей, один разработчикНачать с MoleculeROI в обнаружении ошибок до продакшна
Команда из 3+, общие ролиMolecule + CI обязательноПредотвращает проблемы “работает на моей машине”
Роли критической инфраструктурыMolecule + мульти-сценарииТестирование обновлений, edge cases, откатов
Публикация в Ansible GalaxyMolecule обязательноОжидание сообщества, укрепляет доверие

Рассмотрите 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: Здесь размещаются ваши задачи Ansible
  • handlers/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 Galaxy
  • driver: Указывает 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 выполняет эти фазы:

  1. Dependency: Установка зависимостей ролей из Ansible Galaxy
  2. Lint: Проверка синтаксиса и лучших практик
  3. Cleanup: Удаление предыдущих тестовых экземпляров
  4. Destroy: Обеспечение чистого состояния
  5. Create: Создание тестовых контейнеров
  6. Prepare: Опциональные шаги предварительной настройки
  7. Converge: Применение вашей роли
  8. Idempotence: Повторный запуск для обеспечения отсутствия изменений
  9. Verify: Запуск проверочных тестов
  10. 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

[![CI](https://github.com/username/ansible-role-nginx/workflows/CI/badge.svg)](https://github.com/username/ansible-role-nginx/actions)
[![Ansible Galaxy](https://img.shields.io/badge/galaxy-username.nginx-blue.svg)](https://galaxy.ansible.com/username/nginx)

Протестировано с Molecule на:

- Ubuntu 20.04
- Ubuntu 22.04
- Debian 11

Заключение

Molecule трансформирует разработку ролей Ansible из ручного, подверженного ошибкам процесса в надежный, автоматизированный рабочий процесс. Внедряя комплексные стратегии тестирования—от базовых проверок функциональности до мультиплатформенных сценариев—вы гарантируете, что ваш инфраструктурный код надежен, поддерживаем и готов к продакшну.

Ключевые Выводы:

  • Всегда тестируйте свои роли на нескольких операционных системах и сценариях
  • Используйте тестирование идемпотентности для предотвращения дрейфа конфигурации
  • Интегрируйте Molecule в ваш CI/CD пайплайн для непрерывной валидации
  • Используйте Docker для скорости во время разработки, Vagrant для сложного тестирования на системном уровне
  • Пишите четкие, сфокусированные тесты верификации, которые действуют как живая документация

Следующие Шаги:

  1. Исследуйте продвинутые сценарии: Внедрите мультиузловое тестирование для распределенных систем (узнайте больше в нашем руководстве по Лучшим Практикам Управления Docker Контейнерами)
  2. Интегрируйте с вашим CI/CD пайплайном: Добавьте тесты Molecule в ваши существующие пайплайны (посмотрите Стратегии Оптимизации CI/CD Пайплайна)
  3. Вносите вклад в сообщество: Делитесь вашими протестированными ролями на Ansible Galaxy
  4. Изучайте дополнительные инструменты тестирования: Исследуйте Testinfra, InSpec и ServerSpec для более глубокой валидации инфраструктуры

Для большего об автоматизации инфраструктуры и лучших практиках DevOps, изучите наше комплексное руководство по Инфраструктуре как Код с Terraform или погрузитесь в Стратегии Развертывания Kubernetes для тестирования облачной инфраструктуры.

Дополнительные Ресурсы:

Начните тестировать ваш инфраструктурный код сегодня—ваше будущее “я” (и ваша команда) будут благодарны вам, когда развертывания станут предсказуемыми, надежными и свободными от стресса.

Смотрите также

Официальные ресурсы