- Molecule: драйвер delegated, коллекция containers.podman, create/destroy/verify на Podman - Makefile: все вызовы docker заменены на podman, сокет /run/podman/podman.sock - Сборка образов: podman build (без buildx), buildall/buildall-image — только локально без push - Ansible-controller: Podman в образе, docker-compose на podman compose, сокет Podman - K8s: Kind заменён на Minikube (драйвер podman), скрипты и Makefile обновлены - Пресеты: проверка локальных образов, без podman pull (registry запрещён) - Документация: docs/podman.md, docs/quickstart-for-dummies.md (роли, плейбук, линт, тесты, пресеты, инвентори) - README: ссылка на quickstart-for-dummies Made-with: Cursor
329 lines
15 KiB
YAML
329 lines
15 KiB
YAML
---
|
||
# =============================================================================
|
||
# CREATE - Создание тестовых инстансов
|
||
# =============================================================================
|
||
- hosts: localhost
|
||
gather_facts: false
|
||
vars:
|
||
# Получаем preset из переменной окружения или используем default
|
||
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
|
||
# Проверяем сначала в папке k8s, затем в основной папке presets
|
||
preset_file: "{{ '/workspace/molecule/presets/k8s/' + preset_name + '.yml' if (preset_name in ['k8s-minimal', 'kubernetes', 'k8s-full'] or preset_name.startswith('k8s-')) else '/workspace/molecule/presets/' + preset_name + '.yml' }}"
|
||
|
||
# Fallback значения если preset файл не найден (Podman использует ту же сеть)
|
||
docker_network: labnet
|
||
podman_network: "{{ docker_network }}"
|
||
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
|
||
images:
|
||
alt9: "inecs/ansible-lab:alt9-latest"
|
||
alt10: "inecs/ansible-lab:alt10-latest"
|
||
astra: "inecs/ansible-lab:astra-linux-latest"
|
||
astra-arm64: "inecs/ansible-lab:astra-linux-arm64-latest"
|
||
rhel: "inecs/ansible-lab:rhel-latest"
|
||
centos7: "inecs/ansible-lab:centos7-latest"
|
||
centos8: "inecs/ansible-lab:centos8-latest"
|
||
centos9: "inecs/ansible-lab:centos9-latest"
|
||
alma: "inecs/ansible-lab:alma-latest"
|
||
rocky: "inecs/ansible-lab:rocky-latest"
|
||
redos: "inecs/ansible-lab:redos-latest"
|
||
ubuntu20: "inecs/ansible-lab:ubuntu20-latest"
|
||
ubuntu22: "inecs/ansible-lab:ubuntu22-latest"
|
||
ubuntu24: "inecs/ansible-lab:ubuntu24-latest"
|
||
debian9: "inecs/ansible-lab:debian9-latest"
|
||
debian10: "inecs/ansible-lab:debian10-latest"
|
||
debian11: "inecs/ansible-lab:debian11-latest"
|
||
debian12: "inecs/ansible-lab:debian12-latest"
|
||
systemd_defaults:
|
||
privileged: true
|
||
command: "/sbin/init"
|
||
volumes:
|
||
- "/sys/fs/cgroup:/sys/fs/cgroup:rw"
|
||
tmpfs: ["/run", "/run/lock"]
|
||
capabilities: ["SYS_ADMIN"]
|
||
hosts:
|
||
- name: u1
|
||
family: debian
|
||
groups: [test]
|
||
kind_clusters: []
|
||
|
||
tasks:
|
||
- name: Display running create.yml
|
||
debug:
|
||
msg: |
|
||
================================================================================
|
||
Запуск create.yml
|
||
================================================================================
|
||
|
||
# Определяем архитектуру системы для корректной загрузки образов
|
||
- name: Detect system architecture
|
||
shell: |
|
||
arch=$(uname -m)
|
||
case $arch in
|
||
x86_64) echo "linux/amd64" ;;
|
||
aarch64|arm64) echo "linux/arm64" ;;
|
||
armv7l) echo "linux/arm/v7" ;;
|
||
*) echo "linux/amd64" ;;
|
||
esac
|
||
register: detected_platform
|
||
changed_when: false
|
||
|
||
- name: Set ansible_architecture variable
|
||
set_fact:
|
||
ansible_architecture: "{{ detected_platform.stdout }}"
|
||
|
||
- name: Load preset configuration
|
||
include_vars: "{{ preset_file }}"
|
||
when: preset_file is file
|
||
ignore_errors: true
|
||
|
||
# Фильтрация хостов по поддерживаемым платформам
|
||
- name: Filter hosts by supported platforms
|
||
set_fact:
|
||
filtered_hosts: "{{ filtered_hosts | default([]) + [item] }}"
|
||
loop: "{{ hosts }}"
|
||
when: |
|
||
item.supported_platforms is not defined or
|
||
ansible_architecture in item.supported_platforms
|
||
|
||
- name: Update hosts list with filtered results
|
||
set_fact:
|
||
hosts: "{{ filtered_hosts | default(hosts) }}"
|
||
|
||
# =============================================================================
|
||
# СЕТЕВОЕ ПОДКЛЮЧЕНИЕ (Podman)
|
||
# =============================================================================
|
||
- name: Network setup
|
||
debug:
|
||
msg: |
|
||
================================================================================
|
||
НАСТРОЙКА СЕТИ (Podman)
|
||
================================================================================
|
||
Network: {{ podman_network | default(docker_network) }}
|
||
================================================================================
|
||
|
||
- name: Ensure network exists
|
||
containers.podman.podman_network:
|
||
name: "{{ podman_network | default(docker_network) }}"
|
||
state: present
|
||
|
||
# =============================================================================
|
||
# SYSTEMD NODES - Создание контейнеров с systemd
|
||
# =============================================================================
|
||
- name: Systemd nodes setup
|
||
debug:
|
||
msg: |
|
||
================================================================================
|
||
SYSTEMD NODES - Создание контейнеров с systemd
|
||
================================================================================
|
||
Count: {{ hosts | selectattr('type','undefined') | list | length }}
|
||
================================================================================
|
||
|
||
# Только локальные образы (registry запрещён). Сборка: make buildall
|
||
- name: Проверка наличия локальных образов (Podman)
|
||
command: "podman image exists {{ images[item.family] }}"
|
||
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||
loop_control: { label: "{{ item.name }}" }
|
||
when: item.family is defined and images[item.family] is defined
|
||
register: image_check
|
||
failed_when: false
|
||
changed_when: false
|
||
|
||
- name: Остановка при отсутствии локальных образов
|
||
fail:
|
||
msg: |
|
||
Локальные образы не найдены (доступ к registry запрещён).
|
||
Выполните: make buildall
|
||
Отсутствуют образы: {{ image_check.results | default([]) | selectattr('rc', 'ne', 0) | map(attribute='item') | map(attribute='family') | list | join(', ') }}
|
||
when: image_check.results is defined and (image_check.results | selectattr('rc', 'ne', 0) | list | length > 0)
|
||
|
||
- name: Start systemd nodes
|
||
containers.podman.podman_container:
|
||
name: "{{ item.name }}"
|
||
image: "{{ images[item.family] }}"
|
||
network: "{{ podman_network | default(docker_network) }}"
|
||
privileged: "{{ systemd_defaults.privileged }}"
|
||
command: "{{ '/bin/bash -c \"while true; do sleep 30; done\"' if item.family in ['alt10', 'alt9'] else systemd_defaults.command }}"
|
||
volume: "{{ systemd_defaults.volumes | default([]) + (item.volumes | default([])) + ['/workspace/vault:/workspace/vault:ro', '/workspace/files:/workspace/files:ro', '/workspace/roles:/workspace/roles:ro'] }}"
|
||
tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}"
|
||
cap_add: "{{ systemd_defaults.capabilities | default([]) }}"
|
||
ports: "{{ item.publish | default([]) }}"
|
||
env: "{{ item.env | default({}) }}"
|
||
security_opt: "{{ ['seccomp=unconfined', 'apparmor=unconfined'] if item.family in ['astra', 'redos'] else [] }}"
|
||
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
|
||
|
||
# Ожидание стабилизации контейнеров
|
||
- name: Wait for containers to be ready
|
||
pause:
|
||
seconds: 10
|
||
when: hosts | length > 0
|
||
|
||
# Проверка готовности контейнеров (Podman)
|
||
- name: Wait for containers to be running
|
||
command: "podman inspect --format '{{ '{{' }}.State.Running{{ '}}' }}' {{ item.name }}"
|
||
register: container_info
|
||
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||
loop_control: { label: "{{ item.name }}" }
|
||
when: item.family is defined and images[item.family] is defined
|
||
retries: 10
|
||
delay: 5
|
||
until: container_info.stdout == 'true'
|
||
|
||
|
||
# =============================================================================
|
||
# POoD NODES - Создание контейнеров Podman-out-of-Podman (сокет Podman)
|
||
# =============================================================================
|
||
- name: POoD nodes setup
|
||
debug:
|
||
msg: |
|
||
================================================================================
|
||
POoD NODES - Контейнеры с монтированием сокета Podman
|
||
================================================================================
|
||
Count: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }}
|
||
================================================================================
|
||
|
||
- name: Start POoD nodes (systemd + podman.sock mount)
|
||
containers.podman.podman_container:
|
||
name: "{{ item.name }}"
|
||
image: "{{ images[item.family] }}"
|
||
network: "{{ podman_network | default(docker_network) }}"
|
||
privileged: "{{ systemd_defaults.privileged }}"
|
||
command: "{{ systemd_defaults.command }}"
|
||
volume: "{{ (systemd_defaults.volumes | default([])) + ['/run/podman/podman.sock:/run/podman/podman.sock'] + (item.volumes | default([])) + ['/workspace/vault:/workspace/vault:ro', '/workspace/files:/workspace/files:ro', '/workspace/roles:/workspace/roles:ro'] }}"
|
||
tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}"
|
||
cap_add: "{{ systemd_defaults.capabilities | default([]) }}"
|
||
ports: "{{ item.publish | default([]) }}"
|
||
env: "{{ (item.env | default({})) | combine({'CONTAINER_HOST': 'unix:///run/podman/podman.sock'}) }}"
|
||
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: 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) }}"
|
||
loop_control:
|
||
label: "{{ item.0.name }}"
|
||
vars:
|
||
item_name: "{{ item.0.name }}"
|
||
item_group: "{{ item.1 }}"
|
||
|
||
# =============================================================================
|
||
# ИНВЕНТАРЬ - Генерация inventory файла
|
||
# =============================================================================
|
||
- name: Inventory generation
|
||
debug:
|
||
msg: |
|
||
================================================================================
|
||
ИНВЕНТАРЬ - Генерация inventory файла
|
||
================================================================================
|
||
File: {{ generated_inventory }}
|
||
================================================================================
|
||
|
||
- name: Render inventory ini
|
||
set_fact:
|
||
inv_content: |
|
||
[all:vars]
|
||
ansible_connection=containers.podman.podman
|
||
ansible_remote_tmp=/tmp/.ansible-tmp
|
||
|
||
{% for group, members in (groups_map | dictsort) %}
|
||
[{{ group }}]
|
||
{% for h in members %}{{ h }}
|
||
{% endfor %}
|
||
|
||
{% endfor %}
|
||
[all]
|
||
{% for h in hosts %}{{ h.name }}
|
||
{% endfor %}
|
||
|
||
{# Группа с Debian-based системами (Debian, Ubuntu, Alt) - используем /usr/bin/python3 #}
|
||
{% set debian_hosts = [] %}
|
||
{% for h in hosts %}
|
||
{% if h.family in ['ubuntu', 'debian', 'alt'] %}
|
||
{% set _ = debian_hosts.append(h.name) %}
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% if debian_hosts %}
|
||
[debian_family:vars]
|
||
ansible_python_interpreter=/usr/bin/python3
|
||
|
||
[debian_family]
|
||
{% for h in debian_hosts %}{{ h }}
|
||
{% endfor %}
|
||
{% endif %}
|
||
|
||
{# Группа с RHEL-based системами (RHEL, CentOS, Alma, Rocky, RedOS) #}
|
||
{% set rhel_hosts = [] %}
|
||
{% for h in hosts %}
|
||
{% if h.family in ['rhel', 'centos', 'alma', 'rocky', 'redos'] %}
|
||
{% set _ = rhel_hosts.append(h.name) %}
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% if rhel_hosts %}
|
||
[rhel_family:vars]
|
||
ansible_python_interpreter=/usr/bin/python3
|
||
|
||
[rhel_family]
|
||
{% for h in rhel_hosts %}{{ h }}
|
||
{% endfor %}
|
||
{% endif %}
|
||
|
||
{# Astra Linux - используем /usr/bin/python3 #}
|
||
{% set astra_hosts = [] %}
|
||
{% for h in hosts %}
|
||
{% if h.family == 'astra' %}
|
||
{% set _ = astra_hosts.append(h.name) %}
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% if astra_hosts %}
|
||
[astra_family:vars]
|
||
ansible_python_interpreter=/usr/bin/python3
|
||
|
||
[astra_family]
|
||
{% for h in astra_hosts %}{{ h }}
|
||
{% endfor %}
|
||
{% endif %}
|
||
|
||
{# Глобальный fallback для остальных хостов #}
|
||
[all:vars]
|
||
ansible_python_interpreter=auto_silent
|
||
|
||
- name: Write inventory file
|
||
copy:
|
||
dest: "{{ generated_inventory }}"
|
||
content: "{{ inv_content }}"
|
||
mode: "0644"
|
||
|
||
- name: Display inventory summary
|
||
shell: |
|
||
echo "Inventory Summary:"
|
||
echo "- Total hosts: {{ hosts | length }}"
|
||
echo "- Groups: {{ groups_map.keys() | list | join(', ') }}"
|
||
echo "- Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }}"
|
||
echo "- DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }}"
|
||
echo "- DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }}"
|
||
register: inventory_summary_output
|
||
changed_when: false
|
||
|
||
- name: Show inventory summary
|
||
debug:
|
||
msg: "{{ inventory_summary_output.stdout_lines }}"
|
||
|
||
- name: End of create.yml
|
||
debug:
|
||
msg: |
|
||
================================================================================
|
||
Окончание работы create.yml
|
||
================================================================================
|