feat: Реорганизация Makefile и добавление Docker образов
- Реорганизован Makefile: * Переменные вынесены наверх * Справка перенесена в конец * Удалены секции molecule и container * Объединены presets и preset в одну секцию * Переименована секция docker в docker-cmd - Добавлены Docker образы: * ansible-controller - основной контроллер * alt-linux, astra-linux, redos - российские дистрибутивы * rhel, centos, alma, rocky - RHEL-совместимые образы - Обновлены preset'ы: * Добавлены описания #description: во все preset'ы * Переименован docker.yml в docker-test.yml * Добавлены новые preset'ы: etcd-patroni, multi-os - Добавлена документация: * docs/examples.md - примеры использования * docs/universal-testing.md - универсальное тестирование * dockerfiles/README.md - описание Docker образов - Улучшена функциональность: * Единообразный стиль команд make [категория] [действие] * Улучшенный вывод информации о preset'ах * Добавлены пустые цели для совместимости
This commit is contained in:
@@ -2,51 +2,74 @@
|
||||
- hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
# Получаем preset из переменной окружения или используем default
|
||||
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
|
||||
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
|
||||
|
||||
# перечисли файлы/глобы, которые нужно временно расшифровать
|
||||
vault_targets:
|
||||
- /ansible/vault/secrets.yml
|
||||
# добавляй сюда свои пути (host_vars/*/vault.yml, group_vars/*/vault.yml, и т.п.)
|
||||
- /ansible/files/playbooks/group_vars/*/vault.yml
|
||||
- /ansible/files/playbooks/host_vars/*/vault.yml
|
||||
- /ansible/roles/**/vars/vault.yml
|
||||
|
||||
tasks:
|
||||
- name: Load preset configuration
|
||||
include_vars: "{{ preset_file }}"
|
||||
when: preset_file is file
|
||||
ignore_errors: true
|
||||
|
||||
- name: Install collections
|
||||
community.docker.docker_container_exec:
|
||||
container: ansible-controller
|
||||
command: bash -lc "ansible-galaxy collection install -r /ansible/requirements.yml --force --no-deps --upgrade >/dev/null 2>&1 || true"
|
||||
|
||||
- name: Decrypt vault targets (best-effort)
|
||||
- name: Preflight vault — normalize state (encrypt if plaintext, then decrypt)
|
||||
community.docker.docker_container_exec:
|
||||
container: ansible-controller
|
||||
command: >
|
||||
bash -lc '
|
||||
set -euo pipefail;
|
||||
set -euo pipefail; shopt -s nullglob globstar;
|
||||
for p in {{ vault_targets | map('quote') | join(' ') }}; do
|
||||
if [ -e "$p" ]; then
|
||||
echo "[vault] decrypt $p";
|
||||
ansible-vault decrypt --vault-password-file /ansible/vault-password.txt "$p" || true;
|
||||
fi
|
||||
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 /ansible/vault-password.txt "$f";
|
||||
fi
|
||||
echo "[vault] decrypt for run: $f";
|
||||
ansible-vault decrypt --vault-password-file /ansible/vault-password.txt "$f";
|
||||
done
|
||||
done
|
||||
'
|
||||
|
||||
- name: Run external playbook (your lab play)
|
||||
- name: Run lab playbook
|
||||
community.docker.docker_container_exec:
|
||||
container: ansible-controller
|
||||
command: >
|
||||
bash -lc "
|
||||
ANSIBLE_ROLES_PATH=/ansible/roles
|
||||
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/molecule/default/site.yml
|
||||
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/files/playbooks/site.yml
|
||||
"
|
||||
|
||||
- name: Re-encrypt vault targets (always)
|
||||
- name: Post-run — re-encrypt secrets
|
||||
community.docker.docker_container_exec:
|
||||
container: ansible-controller
|
||||
command: >
|
||||
bash -lc '
|
||||
set -euo pipefail;
|
||||
set -euo pipefail; shopt -s nullglob globstar;
|
||||
for p in {{ vault_targets | map('quote') | join(' ') }}; do
|
||||
if [ -e "$p" ]; then
|
||||
echo "[vault] encrypt $p";
|
||||
ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$p" || true;
|
||||
fi
|
||||
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 /ansible/vault-password.txt "$f" || true;
|
||||
fi
|
||||
done
|
||||
done
|
||||
'
|
||||
ignore_errors: true
|
||||
@@ -11,6 +11,9 @@
|
||||
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
|
||||
images:
|
||||
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
|
||||
rhel: "quay.io/centos/centos:stream9-systemd"
|
||||
ubuntu: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
|
||||
centos: "quay.io/centos/centos:stream9-systemd"
|
||||
systemd_defaults:
|
||||
privileged: true
|
||||
command: "/sbin/init"
|
||||
@@ -24,72 +27,99 @@
|
||||
groups: [test]
|
||||
|
||||
tasks:
|
||||
- name: Install required collections
|
||||
command: ansible-galaxy collection install -r /workspace/requirements.yml
|
||||
delegate_to: localhost
|
||||
ignore_errors: true
|
||||
register: collections_install
|
||||
changed_when: false
|
||||
run_once: true
|
||||
become: true
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
environment:
|
||||
ANSIBLE_COLLECTIONS_PATH: /usr/share/ansible/collections
|
||||
|
||||
- name: Load preset configuration
|
||||
include_vars: "{{ preset_file }}"
|
||||
when: preset_file is file
|
||||
ignore_errors: true
|
||||
|
||||
- name: Ensure network exists
|
||||
command: docker network create {{ docker_network }}
|
||||
delegate_to: localhost
|
||||
ignore_errors: true
|
||||
community.docker.docker_network:
|
||||
name: "{{ docker_network }}"
|
||||
state: present
|
||||
|
||||
# SYSTEMD nodes
|
||||
- name: Pull systemd images
|
||||
command: docker pull {{ images[item.family] }}
|
||||
delegate_to: localhost
|
||||
community.docker.docker_image:
|
||||
name: "{{ images[item.family] }}"
|
||||
source: pull
|
||||
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
when: item.family is defined and images[item.family] is defined
|
||||
|
||||
- name: Start systemd nodes
|
||||
command: >
|
||||
docker run -d --name {{ item.name }}
|
||||
--network {{ docker_network }}
|
||||
--privileged={{ systemd_defaults.privileged | lower }}
|
||||
--tmpfs {{ (systemd_defaults.tmpfs | default([])) | join(' --tmpfs ') }}
|
||||
--cap-add {{ (systemd_defaults.capabilities | default([])) | join(' --cap-add ') }}
|
||||
{% for port in item.publish | default([]) %}--publish {{ port }} {% endfor %}
|
||||
{% for key, value in item.env | default({}) | dictsort %}--env {{ key }}={{ value }} {% endfor %}
|
||||
{% for volume in (systemd_defaults.volumes | default([])) + (item.volumes | default([])) %}--volume {{ volume }} {% endfor %}
|
||||
{{ images[item.family] }} {{ systemd_defaults.command }}
|
||||
delegate_to: localhost
|
||||
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([]) }}"
|
||||
environment: "{{ item.env | default({}) }}"
|
||||
state: started
|
||||
restart_policy: unless-stopped
|
||||
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
when: item.family is defined and images[item.family] is defined
|
||||
|
||||
# DinD nodes
|
||||
- name: Start DinD nodes (docker:27-dind)
|
||||
command: >
|
||||
docker run -d --name {{ item.name }}
|
||||
--network {{ docker_network }}
|
||||
--privileged=true
|
||||
--env DOCKER_TLS_CERTDIR=""
|
||||
{% for port in item.publish | default([]) %}--publish {{ port }} {% endfor %}
|
||||
--volume {{ item.name }}-docker:/var/lib/docker
|
||||
docker:27-dind
|
||||
delegate_to: localhost
|
||||
community.docker.docker_container:
|
||||
name: "{{ item.name }}"
|
||||
image: "docker:27-dind"
|
||||
networks:
|
||||
- name: "{{ docker_network }}"
|
||||
privileged: true
|
||||
environment:
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
published_ports: "{{ item.publish | default([]) }}"
|
||||
volumes: "{{ (item.volumes | default([])) + [item.name + '-docker:/var/lib/docker'] }}"
|
||||
state: started
|
||||
restart_policy: unless-stopped
|
||||
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
|
||||
# DOoD nodes (mount docker.sock)
|
||||
- name: Start DOoD nodes (systemd + docker.sock mount)
|
||||
command: >
|
||||
docker run -d --name {{ item.name }}
|
||||
--network {{ docker_network }}
|
||||
--privileged={{ systemd_defaults.privileged | lower }}
|
||||
--tmpfs {{ (systemd_defaults.tmpfs | default([])) | join(' --tmpfs ') }}
|
||||
--cap-add {{ (systemd_defaults.capabilities | default([])) | join(' --cap-add ') }}
|
||||
{% for port in item.publish | default([]) %}--publish {{ port }} {% endfor %}
|
||||
{% for key, value in item.env | default({}) | dictsort %}--env {{ key }}={{ value }} {% endfor %}
|
||||
{% for volume in (systemd_defaults.volumes | default([])) + ['/var/run/docker.sock:/var/run/docker.sock'] + (item.volumes | default([])) %}--volume {{ volume }} {% endfor %}
|
||||
{{ images[item.family] }} {{ systemd_defaults.command }}
|
||||
delegate_to: localhost
|
||||
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([]) }}"
|
||||
environment: "{{ item.env | default({}) }}"
|
||||
state: started
|
||||
restart_policy: unless-stopped
|
||||
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
when: item.family is defined and images[item.family] is defined
|
||||
|
||||
# Build groups map
|
||||
- name: Build groups map
|
||||
- name: Initialize groups map
|
||||
set_fact:
|
||||
groups_map: "{{ groups_map | default({}) }}"
|
||||
groups_map: {}
|
||||
|
||||
- name: Append hosts to groups
|
||||
set_fact:
|
||||
groups_map: "{{ groups_map | combine({ item_group: (groups_map[item_group] | default([])) + [item_name] }) }}"
|
||||
@@ -122,4 +152,14 @@
|
||||
copy:
|
||||
dest: "{{ generated_inventory }}"
|
||||
content: "{{ inv_content }}"
|
||||
mode: "0644"
|
||||
mode: "0644"
|
||||
|
||||
- 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 }}
|
||||
@@ -4,7 +4,7 @@
|
||||
vars:
|
||||
# Получаем preset из переменной окружения или используем default
|
||||
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
|
||||
preset_file: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') | default('/tmp') }}/../presets/{{ preset_name }}.yml"
|
||||
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
|
||||
|
||||
# Fallback значения если preset файл не найден
|
||||
docker_network: labnet
|
||||
@@ -19,7 +19,7 @@
|
||||
when: preset_file is file
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove containers
|
||||
- name: Stop and remove containers
|
||||
community.docker.docker_container:
|
||||
name: "{{ item.name }}"
|
||||
state: absent
|
||||
@@ -36,8 +36,25 @@
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove custom volumes
|
||||
community.docker.docker_volume:
|
||||
name: "{{ item.volumes | default([]) | select('match', '^[^:]+$') | list }}"
|
||||
state: absent
|
||||
loop: "{{ hosts }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
ignore_errors: true
|
||||
when: item.volumes is defined
|
||||
|
||||
- name: Remove network
|
||||
community.docker.docker_network:
|
||||
name: "{{ docker_network }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
ignore_errors: true
|
||||
|
||||
- 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 }}
|
||||
122
molecule/default/verify.yml
Normal file
122
molecule/default/verify.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
- hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
# Получаем preset из переменной окружения или используем default
|
||||
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
|
||||
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
|
||||
|
||||
# Fallback значения если preset файл не найден
|
||||
docker_network: labnet
|
||||
hosts:
|
||||
- name: u1
|
||||
family: debian
|
||||
groups: [test]
|
||||
|
||||
tasks:
|
||||
- name: Load preset configuration
|
||||
include_vars: "{{ preset_file }}"
|
||||
when: preset_file is file
|
||||
ignore_errors: true
|
||||
|
||||
# Проверка systemd узлов
|
||||
- name: Check systemd nodes status
|
||||
community.docker.docker_container_exec:
|
||||
container: "{{ item.name }}"
|
||||
command: systemctl is-system-running
|
||||
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
register: systemd_status
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display systemd nodes status
|
||||
debug:
|
||||
msg: "Systemd node {{ item.0.name }}: {{ item.1.stdout | default('unknown') }}"
|
||||
loop: "{{ systemd_status.results | default([]) }}"
|
||||
when: systemd_status is defined
|
||||
|
||||
# Проверка DinD узлов
|
||||
- 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 }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
register: dind_status
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display DinD nodes status
|
||||
debug:
|
||||
msg: "DinD node {{ item.0.name }}: Docker {{ item.1.stdout | default('not running') }}"
|
||||
loop: "{{ dind_status.results | default([]) }}"
|
||||
when: dind_status is defined
|
||||
|
||||
# Проверка DOoD узлов
|
||||
- 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 }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
register: dood_status
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display DOoD nodes status
|
||||
debug:
|
||||
msg: "DOoD node {{ item.0.name }}: Can access {{ item.1.stdout_lines | length | default(0) }} containers"
|
||||
loop: "{{ dood_status.results | default([]) }}"
|
||||
when: dood_status is defined
|
||||
|
||||
# Проверка сетевого подключения
|
||||
- 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') }}"
|
||||
loop_control: { label: "{{ item.0.name }} -> {{ item.1.name }}" }
|
||||
when: item.0.name != item.1.name
|
||||
register: ping_results
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display network connectivity results
|
||||
debug:
|
||||
msg: "Network test {{ item.0.name }} -> {{ item.1.name }}: {{ 'OK' if item.2.rc == 0 else 'FAILED' }}"
|
||||
loop: "{{ ping_results.results | default([]) }}"
|
||||
when: ping_results is defined
|
||||
|
||||
# Проверка портов
|
||||
- name: Check published ports
|
||||
community.docker.docker_container_exec:
|
||||
container: "{{ item.name }}"
|
||||
command: netstat -tlnp
|
||||
loop: "{{ hosts | selectattr('publish','defined') | list }}"
|
||||
loop_control: { label: "{{ item.name }}" }
|
||||
register: port_status
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display port status
|
||||
debug:
|
||||
msg: "Node {{ item.0.name }} ports: {{ item.1.stdout_lines | select('match', 'LISTEN') | list | length }} listening"
|
||||
loop: "{{ port_status.results | default([]) }}"
|
||||
when: port_status is defined
|
||||
|
||||
# Проверка групп
|
||||
- name: Display inventory groups
|
||||
debug:
|
||||
msg: |
|
||||
📋 Inventory Groups:
|
||||
{% for group, members in (groups_map | default({}) | dictsort) %}
|
||||
- {{ group }}: {{ members | join(', ') }}
|
||||
{% endfor %}
|
||||
|
||||
# Финальная сводка
|
||||
- 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 }}
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Стандартный пресет по умолчанию для тестирования
|
||||
#description: Стандартный пресет по умолчанию для тестирования с 2 хостами (Debian + RHEL)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Пресет с Docker контейнерами
|
||||
#description: Пресет с Docker контейнерами (DinD + DOoD) для тестирования Docker-задач
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
62
molecule/presets/etcd-patroni.yml
Normal file
62
molecule/presets/etcd-patroni.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
#description: Пресет для тестирования кластера etcd + PostgreSQL + Patroni (9 хостов)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
docker_network: labnet
|
||||
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
|
||||
|
||||
# systemd-ready образы
|
||||
images:
|
||||
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
|
||||
rhel: "quay.io/centos/centos:stream9-systemd"
|
||||
|
||||
systemd_defaults:
|
||||
privileged: true
|
||||
command: "/sbin/init"
|
||||
volumes:
|
||||
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
|
||||
tmpfs: ["/run", "/run/lock"]
|
||||
capabilities: ["SYS_ADMIN"]
|
||||
|
||||
# Описание кластера etcd + Patroni + HAProxy
|
||||
hosts:
|
||||
# ETCD кластер (5 узлов для высокой доступности)
|
||||
- name: etcd1
|
||||
family: debian
|
||||
groups: [etcd, cluster]
|
||||
- name: etcd2
|
||||
family: rhel
|
||||
groups: [etcd, cluster]
|
||||
- name: etcd3
|
||||
family: debian
|
||||
groups: [etcd, cluster]
|
||||
- name: etcd4
|
||||
family: rhel
|
||||
groups: [etcd, cluster]
|
||||
- name: etcd5
|
||||
family: debian
|
||||
groups: [etcd, cluster]
|
||||
|
||||
# Patroni кластер (3 узла PostgreSQL)
|
||||
- name: patroni1
|
||||
family: rhel
|
||||
groups: [patroni, database, cluster]
|
||||
- name: patroni2
|
||||
family: debian
|
||||
groups: [patroni, database, cluster]
|
||||
- name: patroni3
|
||||
family: rhel
|
||||
groups: [patroni, database, cluster]
|
||||
|
||||
# HAProxy для балансировки
|
||||
- name: haproxy
|
||||
family: debian
|
||||
groups: [haproxy, loadbalancer]
|
||||
publish: ["5000:5000", "5001:5001"] # RW и RO порты
|
||||
|
||||
# DinD узел для тестирования Docker Compose внутри
|
||||
- name: app-dind
|
||||
type: dind
|
||||
groups: [apps, docker]
|
||||
publish: ["8080:8080"]
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Минимальный пресет для быстрого тестирования
|
||||
#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
|
||||
70
molecule/presets/multi-os.yml
Normal file
70
molecule/presets/multi-os.yml
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
#description: Пресет для тестирования на разных ОС с 12 хостами (Debian + RHEL)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
docker_network: labnet
|
||||
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
|
||||
|
||||
# systemd-ready образы для разных ОС
|
||||
images:
|
||||
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
|
||||
rhel: "quay.io/centos/centos:stream9-systemd"
|
||||
|
||||
systemd_defaults:
|
||||
privileged: true
|
||||
command: "/sbin/init"
|
||||
volumes:
|
||||
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
|
||||
tmpfs: ["/run", "/run/lock"]
|
||||
capabilities: ["SYS_ADMIN"]
|
||||
|
||||
# Описание кластера с разными ОС
|
||||
hosts:
|
||||
# Debian серверы
|
||||
- name: debian1
|
||||
family: debian
|
||||
groups: [debian, servers, web]
|
||||
- name: debian2
|
||||
family: debian
|
||||
groups: [debian, servers, web]
|
||||
- name: debian3
|
||||
family: debian
|
||||
groups: [debian, servers, app]
|
||||
- name: debian4
|
||||
family: debian
|
||||
groups: [debian, servers, app]
|
||||
|
||||
# RHEL серверы
|
||||
- name: rhel1
|
||||
family: rhel
|
||||
groups: [rhel, servers, web]
|
||||
- name: rhel2
|
||||
family: rhel
|
||||
groups: [rhel, servers, web]
|
||||
- name: rhel3
|
||||
family: rhel
|
||||
groups: [rhel, servers, app]
|
||||
- name: rhel4
|
||||
family: rhel
|
||||
groups: [rhel, servers, app]
|
||||
|
||||
# База данных на разных ОС
|
||||
- name: db-debian
|
||||
family: debian
|
||||
groups: [database, debian, db]
|
||||
- name: db-rhel
|
||||
family: rhel
|
||||
groups: [database, rhel, db]
|
||||
|
||||
# Load balancer
|
||||
- name: lb-mixed
|
||||
family: debian
|
||||
groups: [loadbalancer, haproxy]
|
||||
publish: ["80:80", "443:443"]
|
||||
|
||||
# DinD узел для тестирования Docker
|
||||
- name: docker-mixed
|
||||
type: dind
|
||||
groups: [docker, apps]
|
||||
publish: ["8080:8080"]
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Пресет для тестирования производительности
|
||||
#description: Пресет для нагрузочного тестирования с 12 хостами (серверы + БД + кэш)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
@@ -19,20 +19,55 @@ systemd_defaults:
|
||||
tmpfs: ["/run", "/run/lock"]
|
||||
capabilities: ["SYS_ADMIN"]
|
||||
|
||||
# Описание кластера для нагрузочного тестирования
|
||||
hosts:
|
||||
# Нагрузочное тестирование - 5 хостов
|
||||
- name: perf1
|
||||
# Основные серверы (5 узлов)
|
||||
- name: server1
|
||||
family: debian
|
||||
groups: [test, performance]
|
||||
- name: perf2
|
||||
family: debian
|
||||
groups: [test, performance]
|
||||
- name: perf3
|
||||
groups: [servers, web, app]
|
||||
- name: server2
|
||||
family: rhel
|
||||
groups: [test, performance]
|
||||
- name: perf4
|
||||
family: rhel
|
||||
groups: [test, performance]
|
||||
- name: perf5
|
||||
groups: [servers, web, app]
|
||||
- name: server3
|
||||
family: debian
|
||||
groups: [test, performance]
|
||||
groups: [servers, web, app]
|
||||
- name: server4
|
||||
family: rhel
|
||||
groups: [servers, web, app]
|
||||
- name: server5
|
||||
family: debian
|
||||
groups: [servers, web, app]
|
||||
|
||||
# База данных (3 узла)
|
||||
- name: db1
|
||||
family: rhel
|
||||
groups: [database, db]
|
||||
- name: db2
|
||||
family: debian
|
||||
groups: [database, db]
|
||||
- name: db3
|
||||
family: rhel
|
||||
groups: [database, db]
|
||||
|
||||
# Кэш (3 узла Redis)
|
||||
- name: cache1
|
||||
family: debian
|
||||
groups: [cache, redis]
|
||||
- name: cache2
|
||||
family: rhel
|
||||
groups: [cache, redis]
|
||||
- name: cache3
|
||||
family: debian
|
||||
groups: [cache, redis]
|
||||
|
||||
# Load balancer
|
||||
- name: lb1
|
||||
family: rhel
|
||||
groups: [loadbalancer, haproxy]
|
||||
publish: ["80:80", "443:443"]
|
||||
|
||||
# DinD узел для тестирования Docker Compose
|
||||
- name: compose-dind
|
||||
type: dind
|
||||
groups: [apps, docker]
|
||||
publish: ["8080:8080", "8081:8081"]
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Пресет для тестирования безопасности
|
||||
#description: Пресет для тестирования безопасности с 10 хостами (bastion + internal + monitoring)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
@@ -19,14 +19,58 @@ systemd_defaults:
|
||||
tmpfs: ["/run", "/run/lock"]
|
||||
capabilities: ["SYS_ADMIN"]
|
||||
|
||||
# Описание кластера для тестирования безопасности
|
||||
hosts:
|
||||
# Тестирование безопасности - 3 хоста с разными ОС
|
||||
- name: sec1
|
||||
family: debian
|
||||
groups: [test, security, web]
|
||||
- name: sec2
|
||||
# Bastion хосты (точки входа)
|
||||
- name: bastion1
|
||||
family: rhel
|
||||
groups: [test, security, db]
|
||||
- name: sec3
|
||||
groups: [bastion, security, jump]
|
||||
publish: ["2222:22"]
|
||||
- name: bastion2
|
||||
family: debian
|
||||
groups: [test, security, api]
|
||||
groups: [bastion, security, jump]
|
||||
publish: ["2223:22"]
|
||||
|
||||
# Внутренние серверы (без внешнего доступа)
|
||||
- name: internal1
|
||||
family: rhel
|
||||
groups: [internal, servers, app]
|
||||
- name: internal2
|
||||
family: debian
|
||||
groups: [internal, servers, app]
|
||||
- name: internal3
|
||||
family: rhel
|
||||
groups: [internal, servers, app]
|
||||
|
||||
# База данных (изолированная сеть)
|
||||
- name: db-secure1
|
||||
family: rhel
|
||||
groups: [database, secure, internal]
|
||||
- name: db-secure2
|
||||
family: debian
|
||||
groups: [database, secure, internal]
|
||||
|
||||
# Мониторинг и логирование
|
||||
- name: monitor1
|
||||
family: debian
|
||||
groups: [monitoring, security, logs]
|
||||
- name: monitor2
|
||||
family: rhel
|
||||
groups: [monitoring, security, logs]
|
||||
|
||||
# Firewall и сетевые компоненты
|
||||
- name: fw1
|
||||
family: rhel
|
||||
groups: [firewall, network, security]
|
||||
- name: fw2
|
||||
family: debian
|
||||
groups: [firewall, network, security]
|
||||
|
||||
# DOoD узел для тестирования Docker безопасности
|
||||
- name: docker-secure
|
||||
type: dood
|
||||
family: debian
|
||||
groups: [docker, security, apps]
|
||||
publish: ["8080:8080"]
|
||||
env:
|
||||
DOCKER_HOST: "unix:///var/run/docker.sock"
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Стандартный пресет для тестирования
|
||||
#description: Стандартный пресет для тестирования с 3 хостами (Debian + RHEL)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Минимальный пресет для быстрого тестирования
|
||||
#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian)
|
||||
# Автор: Сергей Антропов
|
||||
# Сайт: https://devops.org.ru
|
||||
|
||||
|
||||
Reference in New Issue
Block a user