- Обновлено название проекта во всех файлах - Изменена документация (README.md, docs/*.md) - Обновлены конфигурационные файлы (Makefile, env.example) - Изменены CI/CD файлы (GitHub Actions, Azure DevOps, Jenkins) - Обновлены скрипты и Dockerfile - Изменено название в molecule.yml и dockerfiles/README.md Все ссылки и упоминания проекта теперь используют название AnsibleLab
860 lines
33 KiB
Markdown
860 lines
33 KiB
Markdown
# Подробное руководство по файлам Molecule
|
||
|
||
**Автор:** Сергей Антропов
|
||
**Сайт:** https://devops.org.ru
|
||
|
||
## 📋 Обзор
|
||
|
||
Molecule - это инструмент для тестирования Ansible ролей в изолированных окружениях. В проекте AnsibleLab используется универсальная конфигурация Molecule с поддержкой множества операционных систем и различных preset'ов для тестирования.
|
||
|
||
### 🔧 Fallback значения
|
||
|
||
**Важная особенность:** Все файлы Molecule содержат fallback значения, что обеспечивает работоспособность системы даже без preset файлов. Это означает, что:
|
||
|
||
- **Система всегда работает** - даже если preset файл не найден
|
||
- **Быстрый старт** - можно запустить тестирование без настройки
|
||
- **Надежность** - меньше точек отказа в системе
|
||
- **Отладка** - легче диагностировать проблемы с preset'ами
|
||
|
||
## 🏗️ Структура файлов Molecule
|
||
|
||
```
|
||
molecule/
|
||
├── default/ # Основная конфигурация Molecule
|
||
│ ├── molecule.yml # Главный конфигурационный файл
|
||
│ ├── create.yml # Создание тестовых контейнеров
|
||
│ ├── converge.yml # Выполнение ролей в контейнерах
|
||
│ ├── verify.yml # Проверка результатов тестирования
|
||
│ ├── destroy.yml # Удаление тестовых контейнеров
|
||
│ └── site.yml # Основной playbook для тестирования
|
||
└── presets/ # Preset конфигурации для разных сценариев
|
||
├── minimal.yml # Минимальный preset (1 хост)
|
||
├── performance.yml # Performance preset (12 хостов)
|
||
├── security.yml # Security preset (10 хостов)
|
||
├── etcd-patroni.yml # etcd-patroni preset
|
||
└── ... # Другие preset'ы
|
||
```
|
||
|
||
## 📄 Детальное описание файлов
|
||
|
||
### 1. `molecule/default/molecule.yml` - Главный конфигурационный файл
|
||
|
||
**Назначение:** Основная конфигурация Molecule с настройками драйвера, платформ, provisioner'а и verifier'а.
|
||
|
||
#### Основные секции:
|
||
|
||
**Driver (Драйвер):**
|
||
```yaml
|
||
driver:
|
||
name: docker
|
||
```
|
||
- **Назначение:** Определяет использование Docker в качестве драйвера
|
||
- **Функция:** Создание и управление тестовыми контейнерами
|
||
|
||
**Platforms (Платформы):**
|
||
```yaml
|
||
platforms:
|
||
- name: placeholder
|
||
image: ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy
|
||
pre_build_image: true
|
||
- name: ansible-controller
|
||
image: inecs/ansible-lab:ansible-controller-latest
|
||
pre_build_image: true
|
||
# ... другие образы
|
||
```
|
||
- **Назначение:** Определяет доступные Docker образы для тестирования
|
||
- **Поддерживаемые ОС:** Ubuntu, Debian, RHEL, CentOS, AlmaLinux, Rocky Linux, Alt Linux, Astra Linux, RedOS
|
||
- **Собственные образы:** AnsibleLab создает собственные образы для тестирования
|
||
|
||
**Provisioner (Провижнер):**
|
||
```yaml
|
||
provisioner:
|
||
name: ansible
|
||
config_options:
|
||
defaults:
|
||
stdout_callback: yaml
|
||
env:
|
||
ANSIBLE_STDOUT_CALLBACK: yaml
|
||
inventory:
|
||
links:
|
||
hosts: "${MOLECULE_EPHEMERAL_DIRECTORY}/inventory/hosts.ini"
|
||
playbooks:
|
||
create: create.yml
|
||
converge: converge.yml
|
||
destroy: destroy.yml
|
||
```
|
||
- **Назначение:** Настройка Ansible как provisioner'а
|
||
- **Функции:**
|
||
- Настройка вывода в YAML формате
|
||
- Связывание инвентори файла
|
||
- Определение playbook'ов для разных этапов
|
||
|
||
**Dependency (Зависимости):**
|
||
```yaml
|
||
dependency:
|
||
name: galaxy
|
||
```
|
||
- **Назначение:** Установка зависимостей через Ansible Galaxy
|
||
- **Функция:** Автоматическая установка коллекций из `requirements.yml`
|
||
|
||
**Verifier (Верификатор):**
|
||
```yaml
|
||
verifier:
|
||
name: ansible
|
||
```
|
||
- **Назначение:** Использование Ansible для проверки результатов
|
||
- **Функция:** Выполнение `verify.yml` для проверки состояния системы
|
||
|
||
**Lint (Линтер):**
|
||
```yaml
|
||
lint: |-
|
||
set -e
|
||
ansible-lint /workspace/roles/
|
||
```
|
||
- **Назначение:** Проверка синтаксиса ролей
|
||
- **Функция:** Запуск `ansible-lint` для всех ролей в директории `roles/`
|
||
|
||
### 2. `molecule/default/create.yml` - Создание тестовых контейнеров
|
||
|
||
**Назначение:** Создание и настройка тестовых контейнеров согласно выбранному preset'у с fallback значениями.
|
||
|
||
#### Переменные и конфигурация:
|
||
|
||
**Fallback значения (по умолчанию):**
|
||
```yaml
|
||
vars:
|
||
# Получаем preset из переменной окружения или используем default
|
||
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
|
||
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
|
||
|
||
# Fallback значения если preset файл не найден
|
||
docker_network: labnet
|
||
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
|
||
images:
|
||
alt: "inecs/ansible-lab:alt-linux-latest"
|
||
astra: "inecs/ansible-lab:astra-linux-latest"
|
||
rhel: "inecs/ansible-lab:rhel-latest"
|
||
centos: "inecs/ansible-lab:centos-latest"
|
||
alma: "inecs/ansible-lab:alma-latest"
|
||
rocky: "inecs/ansible-lab:rocky-latest"
|
||
redos: "inecs/ansible-lab:redos-latest"
|
||
ubuntu: "inecs/ansible-lab:ubuntu-latest"
|
||
debian: "inecs/ansible-lab:debian-latest"
|
||
systemd_defaults:
|
||
privileged: true
|
||
command: "/sbin/init"
|
||
volumes:
|
||
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
|
||
tmpfs: ["/run", "/run/lock"]
|
||
capabilities: ["SYS_ADMIN"]
|
||
hosts:
|
||
- name: u1
|
||
family: debian
|
||
groups: [test]
|
||
```
|
||
- **Назначение:** Определение fallback значений для случаев когда preset файл не найден
|
||
- **Функция:** Обеспечение работоспособности даже без preset файлов
|
||
- **Образы:** Собственные образы AnsibleLab для всех поддерживаемых ОС
|
||
- **Systemd настройки:** Стандартные настройки для systemd контейнеров
|
||
|
||
#### Основные задачи:
|
||
|
||
**Load preset configuration:**
|
||
```yaml
|
||
- name: Load preset configuration
|
||
include_vars: "{{ preset_file }}"
|
||
when: preset_file is file
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Загрузка конфигурации preset'а (перезаписывает fallback значения)
|
||
- **Функция:** Динамическое определение тестового окружения
|
||
- **Переменные:** `MOLECULE_PRESET` определяет какой preset использовать
|
||
- **Fallback:** Если preset файл не найден, используются значения по умолчанию
|
||
|
||
#### Преимущества fallback значений:
|
||
|
||
1. **Надежность:** Система работает даже без preset файлов
|
||
2. **Быстрый старт:** Можно запустить тестирование без настройки preset'ов
|
||
3. **Стандартизация:** Единые настройки для всех ОС
|
||
4. **Отладка:** Легче диагностировать проблемы с preset файлами
|
||
5. **Разработка:** Удобно для разработки новых preset'ов
|
||
|
||
**Ensure network exists:**
|
||
```yaml
|
||
- name: Ensure network exists
|
||
community.docker.docker_network:
|
||
name: "{{ docker_network }}"
|
||
state: present
|
||
```
|
||
- **Назначение:** Создание Docker сети для тестирования
|
||
- **Функция:** Обеспечение сетевого взаимодействия между контейнерами
|
||
- **По умолчанию:** Сеть `labnet`
|
||
|
||
**Pull systemd images:**
|
||
```yaml
|
||
- name: Pull systemd images
|
||
community.docker.docker_image:
|
||
name: "{{ images[item.family] }}"
|
||
source: pull
|
||
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||
```
|
||
- **Назначение:** Загрузка Docker образов для systemd контейнеров
|
||
- **Функция:** Подготовка образов для создания контейнеров
|
||
- **Поддержка:** Различные семейства ОС (debian, rhel, alt, astra)
|
||
|
||
**Start systemd nodes:**
|
||
```yaml
|
||
- name: Start systemd nodes
|
||
community.docker.docker_container:
|
||
name: "{{ item.name }}"
|
||
image: "{{ images[item.family] }}"
|
||
networks:
|
||
- name: "{{ docker_network }}"
|
||
privileged: "{{ systemd_defaults.privileged }}"
|
||
command: "{{ systemd_defaults.command }}"
|
||
volumes: "{{ systemd_defaults.volumes | default([]) + (item.volumes | default([])) }}"
|
||
tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}"
|
||
capabilities: "{{ systemd_defaults.capabilities | default([]) }}"
|
||
published_ports: "{{ item.publish | default([]) }}"
|
||
env: "{{ item.env | default({}) }}"
|
||
state: started
|
||
restart_policy: unless-stopped
|
||
```
|
||
- **Назначение:** Создание и запуск systemd контейнеров
|
||
- **Функции:**
|
||
- Создание контейнеров с systemd поддержкой
|
||
- Настройка привилегированного режима
|
||
- Монтирование cgroup для systemd
|
||
- Настройка tmpfs для /run
|
||
- Публикация портов
|
||
- Настройка переменных окружения
|
||
|
||
**Start DinD nodes (Docker-in-Docker):**
|
||
```yaml
|
||
- name: Start DinD nodes (docker:27-dind)
|
||
community.docker.docker_container:
|
||
name: "{{ item.name }}"
|
||
image: "docker:27-dind"
|
||
networks:
|
||
- name: "{{ docker_network }}"
|
||
privileged: true
|
||
env:
|
||
DOCKER_TLS_CERTDIR: ""
|
||
published_ports: "{{ item.publish | default([]) }}"
|
||
volumes: "{{ (item.volumes | default([])) + [item.name + '-docker:/var/lib/docker'] }}"
|
||
state: started
|
||
restart_policy: unless-stopped
|
||
```
|
||
- **Назначение:** Создание Docker-in-Docker контейнеров
|
||
- **Функции:**
|
||
- Тестирование Docker Compose
|
||
- Тестирование Dockerfile'ов
|
||
- Изолированная Docker среда
|
||
- Отдельные volumes для Docker данных
|
||
|
||
**Start DOoD nodes (Docker-out-of-Docker):**
|
||
```yaml
|
||
- name: Start DOoD nodes (systemd + docker.sock mount)
|
||
community.docker.docker_container:
|
||
name: "{{ item.name }}"
|
||
image: "{{ images[item.family] }}"
|
||
networks:
|
||
- name: "{{ docker_network }}"
|
||
privileged: "{{ systemd_defaults.privileged }}"
|
||
command: "{{ systemd_defaults.command }}"
|
||
volumes: "{{ (systemd_defaults.volumes | default([])) + ['/var/run/docker.sock:/var/run/docker.sock'] + (item.volumes | default([])) }}"
|
||
tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}"
|
||
capabilities: "{{ systemd_defaults.capabilities | default([]) }}"
|
||
published_ports: "{{ item.publish | default([]) }}"
|
||
env: "{{ item.env | default({}) }}"
|
||
state: started
|
||
restart_policy: unless-stopped
|
||
```
|
||
- **Назначение:** Создание Docker-out-of-Docker контейнеров
|
||
- **Функции:**
|
||
- Доступ к Docker daemon хоста
|
||
- Тестирование Docker операций
|
||
- Комбинация systemd + Docker
|
||
|
||
**Build groups map:**
|
||
```yaml
|
||
- name: Initialize groups map
|
||
set_fact:
|
||
groups_map: {}
|
||
|
||
- name: Append hosts to groups
|
||
set_fact:
|
||
groups_map: "{{ groups_map | combine({ item_group: (groups_map[item_group] | default([])) + [item_name] }) }}"
|
||
loop: "{{ hosts | subelements('groups', skip_missing=True) }}"
|
||
```
|
||
- **Назначение:** Создание карты групп для инвентори
|
||
- **Функция:** Группировка хостов по назначению (servers, database, cache, etc.)
|
||
|
||
**Render inventory ini:**
|
||
```yaml
|
||
- name: Render inventory ini
|
||
set_fact:
|
||
inv_content: |
|
||
[all:vars]
|
||
ansible_connection=community.docker.docker
|
||
ansible_python_interpreter=/usr/bin/python3
|
||
|
||
{% for group, members in (groups_map | dictsort) %}
|
||
[{{ group }}]
|
||
{% for h in members %}{{ h }}
|
||
{% endfor %}
|
||
|
||
{% endfor %}
|
||
[all]
|
||
{% for h in hosts %}{{ h.name }}
|
||
{% endfor %}
|
||
```
|
||
- **Назначение:** Генерация инвентори файла
|
||
- **Функция:** Создание динамического инвентори для Ansible
|
||
- **Формат:** INI формат с группами и переменными
|
||
|
||
**Write inventory file:**
|
||
```yaml
|
||
- name: Write inventory file
|
||
copy:
|
||
dest: "{{ generated_inventory }}"
|
||
content: "{{ inv_content }}"
|
||
mode: "0644"
|
||
```
|
||
- **Назначение:** Сохранение инвентори файла
|
||
- **Функция:** Запись сгенерированного инвентори в файл
|
||
|
||
**Display inventory summary:**
|
||
```yaml
|
||
- name: Display inventory summary
|
||
debug:
|
||
msg: |
|
||
📋 Inventory Summary:
|
||
- Total hosts: {{ hosts | length }}
|
||
- Groups: {{ groups_map.keys() | list | join(', ') }}
|
||
- Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }}
|
||
- DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }}
|
||
- DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }}
|
||
```
|
||
- **Назначение:** Отображение сводки по созданным контейнерам
|
||
- **Функция:** Информация о количестве и типах контейнеров
|
||
|
||
### 3. `molecule/default/converge.yml` - Выполнение ролей
|
||
|
||
**Назначение:** Выполнение Ansible ролей в созданных контейнерах.
|
||
|
||
#### Основные задачи:
|
||
|
||
**Load preset configuration:**
|
||
```yaml
|
||
- name: Load preset configuration
|
||
include_vars: "{{ preset_file }}"
|
||
when: preset_file is file
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Загрузка конфигурации preset'а
|
||
- **Функция:** Применение настроек preset'а для выполнения
|
||
|
||
**Preflight vault — normalize state:**
|
||
```yaml
|
||
- name: Preflight vault — normalize state (encrypt if plaintext, then decrypt)
|
||
community.docker.docker_container_exec:
|
||
container: ansible-controller
|
||
command: >
|
||
bash -lc '
|
||
set -euo pipefail; shopt -s nullglob globstar;
|
||
for p in {{ vault_targets | map('quote') | join(' ') }}; do
|
||
for f in $p; do
|
||
[ -f "$f" ] || continue;
|
||
if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then
|
||
echo "[vault] already encrypted: $f";
|
||
else
|
||
echo "[vault] plaintext -> encrypt: $f";
|
||
ansible-vault encrypt --encrypt-vault-id default --vault-password-file /workspace/vault/.vault "$f";
|
||
fi
|
||
echo "[vault] decrypt for run: $f";
|
||
ansible-vault decrypt --vault-password-file /workspace/vault/.vault "$f";
|
||
done
|
||
done
|
||
'
|
||
```
|
||
- **Назначение:** Подготовка vault файлов для выполнения
|
||
- **Функции:**
|
||
- Шифрование незашифрованных файлов
|
||
- Расшифровка файлов для выполнения
|
||
- Нормализация состояния vault файлов
|
||
|
||
**Run lab playbook:**
|
||
```yaml
|
||
- name: Run lab playbook
|
||
community.docker.docker_container_exec:
|
||
container: ansible-controller
|
||
command: >
|
||
bash -lc "
|
||
ANSIBLE_ROLES_PATH=/workspace/roles
|
||
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /workspace/molecule/default/site.yml
|
||
"
|
||
```
|
||
- **Назначение:** Выполнение основного playbook'а
|
||
- **Функции:**
|
||
- Запуск `site.yml` в ansible-controller контейнере
|
||
- Использование сгенерированного инвентори
|
||
- Установка пути к ролям
|
||
|
||
**Post-run — re-encrypt secrets:**
|
||
```yaml
|
||
- name: Post-run — re-encrypt secrets
|
||
community.docker.docker_container_exec:
|
||
container: ansible-controller
|
||
command: >
|
||
bash -lc '
|
||
set -euo pipefail; shopt -s nullglob globstar;
|
||
for p in {{ vault_targets | map('quote') | join(' ') }}; do
|
||
for f in $p; do
|
||
[ -f "$f" ] || continue;
|
||
if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then
|
||
echo "[vault] ok (encrypted): $f";
|
||
else
|
||
echo "[vault] encrypt back: $f";
|
||
ansible-vault encrypt --encrypt-vault-id default --vault-password-file /workspace/vault/.vault "$f" || true;
|
||
fi
|
||
done
|
||
done
|
||
'
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Повторное шифрование секретов после выполнения
|
||
- **Функция:** Обеспечение безопасности vault файлов
|
||
|
||
### 4. `molecule/default/verify.yml` - Проверка результатов
|
||
|
||
**Назначение:** Проверка состояния системы после выполнения ролей.
|
||
|
||
#### Основные задачи:
|
||
|
||
**Load preset configuration:**
|
||
```yaml
|
||
- name: Load preset configuration
|
||
include_vars: "{{ preset_file }}"
|
||
when: preset_file is file
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Загрузка конфигурации preset'а
|
||
- **Функция:** Применение настроек для проверки
|
||
|
||
**Check systemd nodes status:**
|
||
```yaml
|
||
- name: Check systemd nodes status
|
||
community.docker.docker_container_exec:
|
||
container: "{{ item.name }}"
|
||
command: systemctl is-system-running
|
||
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||
register: systemd_status
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Проверка состояния systemd в контейнерах
|
||
- **Функция:** Убедиться что systemd работает корректно
|
||
|
||
**Check DinD nodes docker daemon:**
|
||
```yaml
|
||
- name: Check DinD nodes docker daemon
|
||
community.docker.docker_container_exec:
|
||
container: "{{ item.name }}"
|
||
command: docker version --format '{{.Server.Version}}'
|
||
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
|
||
register: dind_status
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Проверка Docker daemon в DinD контейнерах
|
||
- **Функция:** Убедиться что Docker работает в контейнерах
|
||
|
||
**Check DOoD nodes docker access:**
|
||
```yaml
|
||
- name: Check DOoD nodes docker access
|
||
community.docker.docker_container_exec:
|
||
container: "{{ item.name }}"
|
||
command: docker ps --format '{{.Names}}'
|
||
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}"
|
||
register: dood_status
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Проверка доступа к Docker в DOoD контейнерах
|
||
- **Функция:** Убедиться что контейнеры могут обращаться к Docker daemon
|
||
|
||
**Test network connectivity between nodes:**
|
||
```yaml
|
||
- name: Test network connectivity between nodes
|
||
community.docker.docker_container_exec:
|
||
container: "{{ item.0.name }}"
|
||
command: ping -c 1 {{ item.1.name }}
|
||
loop: "{{ hosts | subelements(hosts, 'name') }}"
|
||
when: item.0.name != item.1.name
|
||
register: ping_results
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Проверка сетевого взаимодействия между контейнерами
|
||
- **Функция:** Убедиться что контейнеры могут общаться друг с другом
|
||
|
||
**Check published ports:**
|
||
```yaml
|
||
- name: Check published ports
|
||
community.docker.docker_container_exec:
|
||
container: "{{ item.name }}"
|
||
command: netstat -tlnp
|
||
loop: "{{ hosts | selectattr('publish','defined') | list }}"
|
||
register: port_status
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Проверка опубликованных портов
|
||
- **Функция:** Убедиться что порты доступны
|
||
|
||
**Display verification summary:**
|
||
```yaml
|
||
- name: Display verification summary
|
||
debug:
|
||
msg: |
|
||
✅ Verification Summary:
|
||
- Total hosts: {{ hosts | length }}
|
||
- Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }}
|
||
- DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }}
|
||
- DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }}
|
||
- Groups: {{ groups_map.keys() | list | join(', ') }}
|
||
- Network: {{ docker_network }}
|
||
```
|
||
- **Назначение:** Отображение итоговой сводки проверки
|
||
- **Функция:** Информация о состоянии всех компонентов
|
||
|
||
### 5. `molecule/default/destroy.yml` - Удаление контейнеров
|
||
|
||
**Назначение:** Очистка тестовых контейнеров и ресурсов.
|
||
|
||
#### Основные задачи:
|
||
|
||
**Load preset configuration:**
|
||
```yaml
|
||
- name: Load preset configuration
|
||
include_vars: "{{ preset_file }}"
|
||
when: preset_file is file
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Загрузка конфигурации preset'а
|
||
- **Функция:** Определение какие ресурсы нужно удалить
|
||
|
||
**Stop and remove containers:**
|
||
```yaml
|
||
- name: Stop and remove containers
|
||
community.docker.docker_container:
|
||
name: "{{ item.name }}"
|
||
state: absent
|
||
force_kill: true
|
||
loop: "{{ hosts }}"
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Остановка и удаление всех контейнеров
|
||
- **Функция:** Полная очистка тестовых контейнеров
|
||
|
||
**Remove DinD volumes:**
|
||
```yaml
|
||
- name: Remove DinD volumes
|
||
community.docker.docker_volume:
|
||
name: "{{ item.name }}-docker"
|
||
state: absent
|
||
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Удаление volumes для DinD контейнеров
|
||
- **Функция:** Очистка Docker данных
|
||
|
||
**Remove custom volumes:**
|
||
```yaml
|
||
- name: Remove custom volumes
|
||
community.docker.docker_volume:
|
||
name: "{{ item.volumes | default([]) | select('match', '^[^:]+$') | list }}"
|
||
state: absent
|
||
loop: "{{ hosts }}"
|
||
ignore_errors: true
|
||
when: item.volumes is defined
|
||
```
|
||
- **Назначение:** Удаление пользовательских volumes
|
||
- **Функция:** Очистка дополнительных volumes
|
||
|
||
**Remove network:**
|
||
```yaml
|
||
- name: Remove network
|
||
community.docker.docker_network:
|
||
name: "{{ docker_network }}"
|
||
state: absent
|
||
ignore_errors: true
|
||
```
|
||
- **Назначение:** Удаление Docker сети
|
||
- **Функция:** Очистка сетевых ресурсов
|
||
|
||
**Display cleanup summary:**
|
||
```yaml
|
||
- name: Display cleanup summary
|
||
debug:
|
||
msg: |
|
||
🧹 Cleanup Summary:
|
||
- Removed containers: {{ hosts | length }}
|
||
- Removed DinD volumes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }}
|
||
- Network: {{ docker_network }}
|
||
```
|
||
- **Назначение:** Отображение сводки по очистке
|
||
- **Функция:** Информация о удаленных ресурсах
|
||
|
||
### 6. `molecule/default/site.yml` - Основной playbook
|
||
|
||
**Назначение:** Основной playbook для тестирования ролей.
|
||
|
||
#### Структура:
|
||
|
||
**Подготовка окружения:**
|
||
- Обновление пакетов для всех ОС
|
||
- Установка common tools
|
||
- Настройка пользователей
|
||
- Создание рабочих директорий
|
||
|
||
**Импорт deploy.yml:**
|
||
```yaml
|
||
- import_playbook: ../../roles/deploy.yml
|
||
```
|
||
- **Назначение:** Импорт playbook'а с ролями
|
||
- **Функция:** Разделение логики подготовки и выполнения ролей
|
||
|
||
## 🎯 Preset файлы
|
||
|
||
### `molecule/presets/minimal.yml` - Минимальный preset
|
||
|
||
**Назначение:** Быстрое тестирование с одним хостом.
|
||
|
||
**Характеристики:**
|
||
- **Количество хостов:** 1
|
||
- **ОС:** Debian
|
||
- **Группы:** test
|
||
- **Использование:** Быстрая проверка ролей
|
||
|
||
### `molecule/presets/performance.yml` - Performance preset
|
||
|
||
**Назначение:** Нагрузочное тестирование с множеством хостов.
|
||
|
||
**Характеристики:**
|
||
- **Количество хостов:** 12
|
||
- **Серверы:** 5 узлов (web, app)
|
||
- **База данных:** 3 узла
|
||
- **Кэш:** 3 узла Redis
|
||
- **Load balancer:** 1 узел HAProxy
|
||
- **DinD:** 1 узел для Docker Compose
|
||
|
||
**Группы:**
|
||
- `servers` - веб-серверы
|
||
- `database` - базы данных
|
||
- `cache` - кэш серверы
|
||
- `loadbalancer` - балансировщик нагрузки
|
||
- `apps` - приложения
|
||
|
||
### `molecule/presets/security.yml` - Security preset
|
||
|
||
**Назначение:** Тестирование безопасности с изолированными сетями.
|
||
|
||
**Характеристики:**
|
||
- **Количество хостов:** 10
|
||
- **Bastion хосты:** 2 (точки входа)
|
||
- **Внутренние серверы:** 3
|
||
- **База данных:** 2 (изолированная сеть)
|
||
- **Мониторинг:** 2
|
||
- **Firewall:** 2
|
||
- **DOoD:** 1 для Docker безопасности
|
||
|
||
**Группы:**
|
||
- `bastion` - точки входа
|
||
- `internal` - внутренние серверы
|
||
- `database` - базы данных
|
||
- `monitoring` - мониторинг
|
||
- `firewall` - сетевые компоненты
|
||
- `security` - компоненты безопасности
|
||
|
||
## 🚀 Использование
|
||
|
||
### Базовые команды:
|
||
|
||
```bash
|
||
# Тестирование с минимальным preset'ом
|
||
make role test minimal
|
||
|
||
# Тестирование с performance preset'ом
|
||
make role test performance
|
||
|
||
# Тестирование с security preset'ом
|
||
make role test security
|
||
|
||
# Тестирование конкретной роли
|
||
make role test minimal ping
|
||
|
||
# Тестирование без preset'а (используются fallback значения)
|
||
make role test
|
||
|
||
# Тестирование с несуществующим preset'ом (используются fallback значения)
|
||
MOLECULE_PRESET=nonexistent make role test
|
||
```
|
||
|
||
### Продвинутое использование:
|
||
|
||
```bash
|
||
# Тестирование с кастомным preset'ом
|
||
MOLECULE_PRESET=custom make role test
|
||
|
||
# Отладка с подробным выводом
|
||
make role test minimal --verbose
|
||
|
||
# Проверка только создания контейнеров
|
||
molecule create -s default
|
||
|
||
# Проверка только выполнения ролей
|
||
molecule converge -s default
|
||
|
||
# Проверка только верификации
|
||
molecule verify -s default
|
||
|
||
# Очистка контейнеров
|
||
molecule destroy -s default
|
||
```
|
||
|
||
## 🔧 Настройка
|
||
|
||
### Создание собственного preset'а:
|
||
|
||
```yaml
|
||
# molecule/presets/custom.yml
|
||
---
|
||
docker_network: labnet
|
||
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
|
||
|
||
images:
|
||
ubuntu: "inecs/ansible-lab:ubuntu-latest"
|
||
rhel: "inecs/ansible-lab:rhel-latest"
|
||
|
||
systemd_defaults:
|
||
privileged: true
|
||
command: "/sbin/init"
|
||
volumes:
|
||
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
|
||
tmpfs: ["/run", "/run/lock"]
|
||
capabilities: ["SYS_ADMIN"]
|
||
|
||
hosts:
|
||
- name: web1
|
||
family: ubuntu
|
||
groups: [web, servers]
|
||
publish: ["80:80"]
|
||
- name: db1
|
||
family: rhel
|
||
groups: [database, internal]
|
||
```
|
||
|
||
### Использование fallback значений:
|
||
|
||
```bash
|
||
# Тестирование без preset'а (используются fallback значения из create.yml)
|
||
make role test
|
||
|
||
# Тестирование с несуществующим preset'ом (используются fallback значения)
|
||
MOLECULE_PRESET=nonexistent make role test
|
||
|
||
# Проверка fallback значений
|
||
molecule create -s default --debug
|
||
```
|
||
|
||
### Использование кастомного preset'а:
|
||
|
||
```bash
|
||
MOLECULE_PRESET=custom make role test
|
||
```
|
||
|
||
## 🐛 Troubleshooting
|
||
|
||
### Проблемы с контейнерами:
|
||
|
||
**Ошибка:** Контейнер не запускается
|
||
**Решение:** Проверить доступность Docker образа и ресурсы системы
|
||
|
||
**Ошибка:** Systemd не работает
|
||
**Решение:** Убедиться что контейнер запущен с `privileged: true` и правильными volumes
|
||
|
||
**Ошибка:** Сетевое взаимодействие не работает
|
||
**Решение:** Проверить создание Docker сети и настройки firewall
|
||
|
||
### Проблемы с preset файлами:
|
||
|
||
**Ошибка:** Preset файл не найден
|
||
**Решение:** Система автоматически использует fallback значения из `create.yml`
|
||
|
||
**Ошибка:** Неправильная конфигурация preset'а
|
||
**Решение:** Проверить синтаксис YAML и доступность образов в preset файле
|
||
|
||
**Ошибка:** Preset файл не загружается
|
||
**Решение:** Убедиться что файл находится в `molecule/presets/` и имеет правильное имя
|
||
|
||
### Проблемы с ролями:
|
||
|
||
**Ошибка:** Роль не найдена
|
||
**Решение:** Проверить путь к роли в `roles/deploy.yml`
|
||
|
||
**Ошибка:** Ошибка выполнения роли
|
||
**Решение:** Проверить совместимость роли с ОС и зависимости
|
||
|
||
### Проблемы с vault:
|
||
|
||
**Ошибка:** Не удается расшифровать vault файлы
|
||
**Решение:** Проверить наличие файла `.vault` и правильность пароля
|
||
|
||
**Ошибка:** Vault файлы остались расшифрованными
|
||
**Решение:** Проверить права доступа и настройки vault
|
||
|
||
## 📊 Мониторинг
|
||
|
||
### Логи выполнения:
|
||
|
||
```bash
|
||
# Просмотр логов Molecule
|
||
molecule test -s default --debug
|
||
|
||
# Логи конкретного этапа
|
||
molecule create -s default --debug
|
||
molecule converge -s default --debug
|
||
molecule verify -s default --debug
|
||
```
|
||
|
||
### Проверка состояния:
|
||
|
||
```bash
|
||
# Статус контейнеров
|
||
docker ps
|
||
|
||
# Статус сети
|
||
docker network ls
|
||
|
||
# Статус volumes
|
||
docker volume ls
|
||
```
|
||
|
||
## 🎯 Лучшие практики
|
||
|
||
1. **Используйте подходящие preset'ы** для разных типов тестирования
|
||
2. **Проверяйте совместимость ролей** с различными ОС
|
||
3. **Используйте теги** для разделения задач в ролях
|
||
4. **Документируйте зависимости** ролей
|
||
5. **Тестируйте на разных preset'ах** перед коммитом
|
||
6. **Используйте vault** для секретных данных
|
||
7. **Очищайте ресурсы** после тестирования
|
||
8. **Используйте fallback значения** для быстрого старта без preset'ов
|
||
9. **Проверяйте доступность образов** перед созданием preset'ов
|
||
10. **Документируйте кастомные preset'ы** для команды
|
||
|
||
## 🔗 Связанные файлы
|
||
|
||
- `roles/deploy.yml` - playbook с ролями
|
||
- `inventory/hosts.ini` - статический инвентори
|
||
- `vault/.vault` - пароль для vault
|
||
- `requirements.yml` - зависимости Ansible
|
||
- `Makefile` - команды для запуска тестов
|