diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml new file mode 100644 index 0000000..b7a9614 --- /dev/null +++ b/.github/workflows/ansible-test.yml @@ -0,0 +1,44 @@ +name: Ansible Testing +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + - name: Run lint + run: make role lint + + test: + runs-on: ubuntu-latest + needs: lint + strategy: + matrix: + preset: [minimal, default, performance] + steps: + - uses: actions/checkout@v4 + - name: Setup Docker + run: | + sudo systemctl start docker + sudo usermod -aG docker $USER + - name: Run tests + run: make role test ${{ matrix.preset }} + + deploy-check: + runs-on: ubuntu-latest + needs: [lint, test] + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Check deployment + run: make role deploy + env: + ANSIBLE_HOST_KEY_CHECKING: false diff --git a/.gitignore b/.gitignore index 52fd67b..ea9bb01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,12 @@ # ---> Ansible *.retry +# ---> Vault (секретные файлы) +vault/.vault +vault/secrets/*.yml +# Зашифрованные vault файлы (если не нужно коммитить) +# vault/*.yml + # ---> Python # Byte-compiled / optimized / DLL files __pycache__/ @@ -171,3 +177,6 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ +# Cursor IDE +.cursor/ + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 791c0d1..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,89 +0,0 @@ -stages: - - lint - - test - - deploy - - notify - -services: - - name: docker:dind - command: ["--tls=false"] - -variables: - DOCKER_IMAGE: "hub.cism-ms.ru/ansible/ansible:latest" - DOCKER_TLS_CERTDIR: "" - ANSIBLE_FORCE_COLOR: "true" - -before_script: - - echo "$CI_REGISTRY_PASSWORD" | docker login hub.cism-ms.ru -u "$CI_REGISTRY_USER" --password-stdin - - docker pull $DOCKER_IMAGE - - echo "Fixing directory permissions..." - - chmod o-w $CI_PROJECT_DIR - -lint: - stage: lint - script: - - echo "Начинаем стейдж Lint" - - echo "Распаковываем секреты..." - - ansible-vault decrypt vars/secrets.yml --vault-password-file ./vault-password.txt - - echo "Запускаем ansible-lint..." - - ansible-lint roles/* - - echo "Упаковываем секреты..." - - ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file ./vault-password.txt - allow_failure: false - rules: - - if: $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "master" - -test: - stage: test - script: - - echo "Распаковываем секреты..." - - ansible-vault decrypt --vault-password-file ./vault-password.txt vars/secrets.yml - - echo "Запускаем тесты через Молекулу..." - - molecule test --parallel --destroy=always - - echo "Упаковываем секреты..." - - ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file ./vault-password.txt - allow_failure: false - rules: - - if: $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "master" - -deploy: - stage: deploy - script: - - echo "Настраиваем SSH-ключ для доступа к серверам..." - # Создаем директорию .ssh и настраиваем права доступа - - mkdir -p ~/.ssh - - chmod 700 ~/.ssh - # Записываем SSH-ключ в файл ~/.ssh/id_rsa - - echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa - - chmod 600 ~/.ssh/id_rsa - # Запускаем основной пайплайн - - echo "Распаковываем секреты..." - - ansible-vault decrypt --vault-password-file ./vault-password.txt vars/secrets.yml - - echo "Все ок. Деплоим в прод..." - - ansible-playbook roles/deploy.yaml - - echo "Упаковываем секреты..." - - ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file ./vault-password.txt - # Удаляем ключ - - rm -rf ~/.ssh - rules: - - if: $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "master" - when: manual - -notify: - stage: notify - script: - - | - if [ "$CI_JOB_STATUS" == "success" ]; then - MESSAGE="✅ Пайплайн успешно завершен!%0AПроект: $CI_PROJECT_NAME%0AВетка: $CI_COMMIT_REF_NAME%0AСтатус: $CI_JOB_STATUS" - else - MESSAGE="❌ Пайплайн завершен с ошибкой!%0AПроект: $CI_PROJECT_NAME%0AВетка: $CI_COMMIT_REF_NAME%0AСтатус: $CI_JOB_STATUS" - fi -# curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \ -# -d "chat_id=$TELEGRAM_CHAT_ID" \ -# -d "text=$MESSAGE" - rules: - - if: $CI_JOB_STATUS # Отправлять уведомление только после завершения пайплайна - -after_script: - - echo "Работа пайплайна завершена" - diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index dfe699f..0000000 --- a/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -# Используем готовый образ с Ansible -FROM geerlingguy/docker-ubuntu2204-ansible:latest - -# Добавляем метаданные -LABEL maintainer="Сергей Антропов " -LABEL description="Этот Dockerfile создан для внедрения подхода IaC в Ansible." -LABEL version="0.1" -LABEL contact.website="https://devops.org.ru" - -# Устанавливаем переменные окружения -ENV PYTHONUNBUFFERED=1 -ENV EDITOR=nano - -# Устанавливаем дополнительные зависимости Python для Molecule -RUN pip install --upgrade pip && \ - pip install \ - molecule \ - molecule-docker \ - ansible-lint \ - yamllint \ - docker \ - && rm -rf /root/.cache/pip - -# Создаем рабочую директорию -WORKDIR /ansible - -# Копируем файлы проекта -COPY . /ansible/ - -# Устанавливаем права на выполнение (если папка scripts существует) -RUN if [ -d /ansible/scripts ]; then chmod +x /ansible/scripts/*.sh; fi - -# Устанавливаем пользователя -USER root - -# Открываем порт для SSH -EXPOSE 22 - -# Команда по умолчанию -CMD ["/bin/bash"] \ No newline at end of file diff --git a/Dockerfile-CentOS b/Dockerfile-CentOS deleted file mode 100644 index 1ed526a..0000000 --- a/Dockerfile-CentOS +++ /dev/null @@ -1,54 +0,0 @@ -# Сборка контейнера с systemd для удобного тестирования ролей Ansible через Molecule - -# Используем официальный образ Fedora -FROM quay.io/fedora/python-312 - -USER root - -# Обновляем пакеты и устанавливаем systemd и необходимые пакеты -RUN dnf update -y && \ - dnf install -y --nodocs --setopt=install_weak_deps=False \ - systemd rsync \ - git \ - openssh \ - gcc \ - libffi-devel \ - openssl-devel \ - make \ - sudo \ - openssh-clients \ - less \ - ca-certificates \ - curl \ - gnupg2 \ - nano \ - sshpass \ - redhat-lsb-core \ - && dnf clean all && \ - rm -rf /var/cache/dnf /tmp/* /var/tmp/* - -# Устанавливаем docker-compose -RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \ - chmod +x /usr/local/bin/docker-compose - -# Устанавливаем Python пакеты для Ansible -RUN pip install --upgrade pip && \ - pip install \ - ansible \ - ansible-vault \ - molecule \ - molecule-docker \ - ansible-lint \ - yamllint \ - docker \ - && rm -rf /root/.cache/pip - -# Настраиваем окружение для systemd -ENV container=docker -STOPSIGNAL SIGRTMIN+3 - -# Создаем необходимые директории для systemd -VOLUME [ "/sys/fs/cgroup" ] - -# Запускаем systemd при старте контейнера -CMD ["/sbin/init"] \ No newline at end of file diff --git a/Dockerfile-Ubuntu b/Dockerfile-Ubuntu deleted file mode 100644 index 416bce7..0000000 --- a/Dockerfile-Ubuntu +++ /dev/null @@ -1,62 +0,0 @@ -# Сборка контейнера с systemd для удобного тестирования ролей Ansible через Molecule - -# Используем готовый образ с Ansible (более старый, но стабильный) -FROM geerlingguy/docker-ubuntu2004-ansible:latest - -# Устанавливаем переменные окружения -ENV DEBIAN_FRONTEND=noninteractive -ENV container=docker - -# Устанавливаем дополнительные пакеты для тестирования -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - systemd \ - systemd-sysv \ - rsync \ - git \ - ssh \ - gcc \ - libffi-dev \ - libssl-dev \ - make \ - sudo \ - sshpass \ - openssh-client \ - nano \ - less \ - ca-certificates \ - curl \ - gnupg \ - lsb-release \ - && rm -rf /var/lib/apt/lists/* - -# Устанавливаем Python пакеты для Ansible с обновлением зависимостей -RUN pip install --upgrade pip && \ - pip install --upgrade \ - requests \ - PyYAML \ - ansible-core \ - && pip install \ - ansible \ - "ansible-vault<4.0.0" \ - molecule \ - molecule-docker \ - ansible-lint \ - yamllint \ - docker \ - && rm -rf /root/.cache/pip - -# Устанавливаем docker-compose -RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \ - chmod +x /usr/local/bin/docker-compose - - -# Указываем, что контейнер использует systemd в качестве init-системы -ENV container=docker -STOPSIGNAL SIGRTMIN+3 - -# Создаем необходимые директории для systemd -VOLUME [ "/sys/fs/cgroup" ] - -# Запускаем systemd при старте контейнера -CMD ["/sbin/init"] \ No newline at end of file diff --git a/Makefile b/Makefile index fb5437e..027c18e 100644 --- a/Makefile +++ b/Makefile @@ -1,157 +1,1220 @@ +# ============================================================================= +# AnsibleTemplate - Универсальная система тестирования Ansible ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# ============================================================================= + +SHELL := /bin/bash + +# ============================================================================= +# ПЕРЕМЕННЫЕ +# ============================================================================= +# Цвета для вывода +RED := \033[0;31m +GREEN := \033[0;32m +YELLOW := \033[0;33m +BLUE := \033[0;34m +PURPLE := \033[0;35m +CYAN := \033[0;36m +WHITE := \033[0;37m +RESET := \033[0m + # Глобальные переменные -IMAGE ?= ansible -TAG ?= 0.1 -REGISTRY ?= inecs/ansible -# По умолчанию используем docker. Для локальной разработки используйте docker-compose -RUN_MODE ?= docker +PROJECT_NAME ?= ansible-lab +VERSION ?= 0.1.0 +AUTHOR ?= "Сергей Антропов" +SITE ?= "https://devops.org.ru" +DOCKER_IMAGE ?= inecs/ansible-lab:ansible-controller-latest +DOCKER_DIND_IMAGE ?= docker:27-dind +CONTAINER_NAME ?= ansible-controller -# Определение команды RUN в зависимости от RUN_MODE -ifeq ($(RUN_MODE), docker-compose) - RUN = docker compose run --rm $(IMAGE) -else ifeq ($(RUN_MODE), docker) - RUN = docker run -it --rm \ - --name $(IMAGE) \ - -v $(PWD):/ansible \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \ - -e ANSIBLE_VAULT_PASSWORD_FILE=/ansible/vault-password.txt \ - --privileged \ - --workdir /ansible \ - $(REGISTRY)/$(IMAGE) -else - $(error Invalid RUN_MODE. Use "docker-compose" or "docker") -endif +# Переменные для Docker Hub +DOCKER_REGISTRY ?= inecs/ansible-lab +DOCKER_VERSION ?= latest +DOCKER_IMAGES := ansible-controller alt-linux astra-linux redos rhel centos7 centos8 centos9 alma rocky ubuntu20 ubuntu22 ubuntu24 debian9 debian10 debian11 debian12 -view create edit show delete test lint deploy new init build rebuild prune release images push pull shell: - @true +# Multi-arch поддержка +DOCKER_PLATFORMS ?= linux/amd64,linux/arm64 +DOCKER_BUILDX_BUILDER ?= multiarch-builder -#################################################################################################### -# Инициализация новой роли -#################################################################################################### -init: - @echo "Шаг 1: Создание Docker-образа..." - @make docker build - @echo "Шаг 2: Создание Docker-образов для запуска Molecule..." - @make docker images - @echo "Шаг 3: Создание нового vault-файла с паролем..." - @read -p "Введите пароль для vault: " VAULT_PASSWORD; \ - echo "$$VAULT_PASSWORD" > vault-password.txt; \ - make vault create - @echo "Шаг 4: Создание нового брэнча в гите..." - @make git new - @echo "Шаг 5: Создание новой роли..." - @make role new +# Базовые образы и их теги +BASE_IMAGES := altlinux/p9 astralinux/astra-1.7 redos/redos:9 registry.access.redhat.com/ubi8/ubi centos:7 quay.io/centos/centos:8 quay.io/centos/centos:stream9 almalinux:8 rockylinux:8 ubuntu:20.04 ubuntu:22.04 ubuntu:24.04 debian:9 debian:10 debian:11 debian:bookworm -#################################################################################################### -# Управление контейнерами с помощью docker compose или docker run -#################################################################################################### -docker: - @case "$(word 2, $(MAKECMDGOALS))" in \ - build) \ - docker buildx create --use --name multiarch-builder --driver docker-container; \ - if [ "$(RUN_MODE)" = "docker-compose" ]; then \ - docker compose build $(c); \ - else \ - docker build -t $(REGISTRY)/$(IMAGE) .; \ - fi;; \ - rebuild) \ - docker buildx create --use --name multiarch-builder --driver docker-container; \ - if [ "$(RUN_MODE)" = "docker-compose" ]; then \ - docker compose build --no-cache $(c); \ - else \ - docker build --no-cache -t $(REGISTRY)/$(IMAGE) .; \ - fi;; \ - prune) \ - docker system prune -af;; \ - shell) \ - clear; \ - echo "Entering to Ansible container shell..."; \ - $(RUN) bash ;; \ - release) \ - docker buildx create --use --name multiarch-builder --driver docker-container; \ - docker login $(REGISTRY); \ - docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .;; \ - images) \ - docker buildx create --use --name multiarch-builder --driver docker-container; \ - echo "Логинимся в Docker Hub..."; \ - docker login; \ - echo "Собираем и пушим основной Ansible образ..."; \ - docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .; \ - echo "Собираем и пушим образ CentOS..."; \ - docker buildx build -t $(REGISTRY):centos --platform linux/amd64,linux/arm64 --push -f Dockerfile-CentOS .; \ - echo "Собираем и пушим образ Ubuntu..."; \ - docker buildx build -t $(REGISTRY):ubuntu --platform linux/amd64,linux/arm64 --push -f Dockerfile-Ubuntu .; \ - echo "Образы успешно опубликованы в Docker Hub: $(REGISTRY)";; \ - *) echo "Unknown action. Available actions: build, rebuild, prune, release";; \ - esac - -#################################################################################################### -# Работа с ролью -#################################################################################################### -vault: - @case "$(word 2, $(MAKECMDGOALS))" in \ - show) $(RUN) bash -c "ansible-vault view --vault-password-file vault-password.txt vars/secrets.yml";; \ - create) $(RUN) bash -c "ansible-vault create --encrypt-vault-id default --vault-password-file vault-password.txt vars/secrets.yml";; \ - edit) $(RUN) bash -c "ansible-vault edit --vault-password-file vault-password.txt vars/secrets.yml";; \ - delete) $(RUN) bash -c "rm vars/secrets.yml";; \ - rekey) $(RUN) bash -c "ansible-vault rekey --vault-password-file vault-password.txt vars/secrets.yml";; \ - decrypt) $(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml";; \ - encrypt) $(RUN) bash -c "ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault-password.txt vars/secrets.yml";; \ - *) echo "Unknown action";; \ - esac +.PHONY: role vault git docker presets controller help update-playbooks generate-docs setup-cicd list create delete +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С РОЛЯМИ +# ============================================================================= role: @case "$(word 2, $(MAKECMDGOALS))" in \ - new) \ - clear; \ - echo "Введите название новой роли на английском:"; \ - read ROLE_NAME; \ - echo "Введите описание роли:"; \ - read ROLE_DESC; \ - cp -r default/ "roles/$${ROLE_NAME}"; \ - printf "\n- name: $${ROLE_DESC}" >> roles/deploy.yaml; \ - printf "\n import_playbook: $${ROLE_NAME}/deploy.yaml" >> roles/deploy.yaml; \ - printf '\n - ../../roles/%s' "$$ROLE_NAME" >> molecule/default/converge.yml; \ - printf "\n - $${ROLE_NAME}" >> roles/$$ROLE_NAME/deploy.yaml;; \ lint) \ - clear; \ - echo "Check your role..."; \ - $(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \ - $(RUN) bash -c "ansible-lint roles/*"; \ - $(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \ + ROLE_NAME="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$ROLE_NAME" ]; then \ + echo "🔍 Проверка синтаксиса всех ролей ..."; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace -e ANSIBLE_FORCE_COLOR=1 $(DOCKER_IMAGE) bash -c "ansible-lint roles/ --config-file .ansible-lint || true"; \ + else \ + echo "🔍 Проверка синтаксиса роли: $$ROLE_NAME"; \ + if [ -d "roles/$$ROLE_NAME" ]; then \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace -e ANSIBLE_FORCE_COLOR=1 $(DOCKER_IMAGE) bash -c "ansible-lint roles/$$ROLE_NAME/ --config-file .ansible-lint || true"; \ + else \ + echo "❌ Роль '$$ROLE_NAME' не найдена в roles/"; \ + echo "📋 Доступные роли:"; \ + ls -1 roles/ | grep -v "\.yml$$" | sed 's/^/ - /'; \ + exit 1; \ + fi; \ + fi; \ + echo ""; \ + echo "✅ Lint завершен";; \ test) \ - clear; \ - echo "Running test roles..."; \ - $(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \ - $(RUN) bash -c "docker login $(REGISTRY) && molecule test --parallel --destroy=always"; \ - $(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \ + echo "🚀 Тестирование ролей ..."; \ + PRESET="default"; \ + ARGS="$(wordlist 3,10,$(MAKECMDGOALS))"; \ + if [ -n "$$ARGS" ]; then \ + PRESET="$$(echo $$ARGS | cut -d' ' -f1)"; \ + fi; \ + echo "📋 Используется пресет: $$PRESET"; \ + if [ ! -f "molecule/presets/$$PRESET.yml" ]; then \ + echo "❌ Ошибка: Пресет '$$PRESET' не найден!"; \ + echo "💡 Доступные пресеты:"; \ + ls -1 molecule/presets/*.yml 2>/dev/null | sed 's|molecule/presets/||g' | sed 's|\.yml||g' | sed 's/^/ - /' || echo " ⚠️ Пресеты не найдены"; \ + exit 1; \ + fi; \ + echo ""; \ + echo "🔧 Запуск ansible-controller контейнера..."; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -u root \ + -e ANSIBLE_FORCE_COLOR=1 \ + -e MOLECULE_PRESET=$$PRESET \ + -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule_workspace \ + $(DOCKER_IMAGE) \ + bash -c "mkdir -p /tmp/molecule_workspace/inventory && cd molecule/default && ansible-playbook -i localhost, create.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini site.yml; ansible-playbook -i localhost, destroy.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace; echo '✅ Тестирование завершено'";; \ deploy) \ - clear; \ - echo "Deploying roles to production..."; \ - $(RUN) bash -c "ansible-playbook roles/deploy.yaml";; \ - *) echo "Unknown action";; \ + echo "🚀 Развертывание ролей на реальные серверы..."; \ + echo ""; \ + if [ ! -f "inventory/hosts.ini" ]; then \ + echo "❌ Ошибка: Файл inventory/hosts.ini не найден!"; \ + echo "💡 Создайте файл inventory/hosts.ini с вашими серверами"; \ + exit 1; \ + fi; \ + echo "📋 Используется inventory: inventory/hosts.ini"; \ + echo "📄 Содержимое inventory:"; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace $(DOCKER_IMAGE) cat inventory/hosts.ini || cat inventory/hosts.ini; \ + echo ""; \ + echo "🚀 Запуск развертывания (в контейнере)..."; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ + -v ~/.ssh:/root/.ssh:ro \ + -e ANSIBLE_FORCE_COLOR=1 \ + $(DOCKER_IMAGE) \ + bash -c "ansible-playbook -i inventory/hosts.ini roles/deploy.yml --check"; \ + echo ""; \ + read -p "Продолжить развертывание? (y/N): " confirm; \ + if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ + -v ~/.ssh:/root/.ssh:ro \ + -e ANSIBLE_FORCE_COLOR=1 \ + $(DOCKER_IMAGE) \ + bash -c "ansible-playbook -i inventory/hosts.ini roles/deploy.yml"; \ + else \ + echo "❌ Развертывание отменено"; \ + fi;; \ + list) \ + ./scripts/role-manager.sh list;; \ + create) \ + ./scripts/role-manager.sh create < /dev/tty;; \ + delete) \ + ./scripts/role-manager.sh delete < /dev/tty;; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 🚀 make role test [preset] - протестировать роли с preset'ом"; \ + echo " 💡 Примеры:"; \ + echo " make role test # с default preset"; \ + echo " make role test minimal # с minimal preset"; \ + echo " make role test all-images # со всеми образами"; \ + echo " make role test etcd-patroni # с etcd-patroni preset"; \ + echo ""; \ + echo " 🚀 make role deploy - развернуть роли на реальные серверы"; \ + echo " 💡 Требует: inventory/hosts.ini"; \ + echo " 💡 Примеры:"; \ + echo " make role deploy # развертывание всех ролей"; \ + echo " ansible-playbook -i inventory/hosts.ini roles/deploy.yml --tags web"; \ + echo " ansible-playbook -i inventory/hosts.ini roles/deploy.yml --limit webservers"; \ + echo " ansible-playbook -i inventory/hosts.ini roles/deploy.yml --check"; \ + echo " 💡 Документация: docs/deploy-yml-customization.md"; \ + echo ""; \ + echo " 🔍 make role lint [role] - проверить синтаксис ролей"; \ + echo " 💡 Использует: ansible-lint"; \ + echo " 💡 Без параметра: проверяет все роли"; \ + echo " 💡 С параметром: проверяет конкретную роль"; \ + echo " 💡 Валидация: показывает доступные роли при ошибке"; \ + echo " 💡 Примеры:"; \ + echo " make role lint # проверить все роли"; \ + echo " make role lint devops # проверить только devops"; \ + echo " make role lint ping # проверить только ping"; \ + echo ""; \ + echo " 📋 make role list - показать все роли"; \ + echo " 💡 Показывает: список всех ролей в roles/"; \ + echo ""; \ + echo " ➕ make role create - создать новую роль"; \ + echo " 💡 Интерактивно: запрашивает имя роли"; \ + echo " 💡 Создает: структуру папок и файлов"; \ + echo " 💡 Обновляет: roles/deploy.yml"; \ + echo ""; \ + echo " 🗑️ make role delete - удалить роль"; \ + echo " 💡 Интерактивно: запрашивает имя роли"; \ + echo " 💡 Удаляет: папку роли и файлы"; \ + echo " 💡 Обновляет: roles/deploy.yml"; \ + echo ""; \ + echo " 🔧 ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ О ЛИНТИНГЕ:"; \ + echo " 💡 Линтинг проверяет: синтаксис, стиль, лучшие практики"; \ + echo " 💡 Профили: production, basic, min"; \ + echo " 💡 Конфигурация: .ansible-lint"; \ + echo " 💡 Ошибки: показываются с номерами строк"; \ + echo " 💡 Валидация: автоматическая проверка существования роли";; \ esac -#################################################################################################### -# Работа с Git -#################################################################################################### +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С PRESET'АМИ +# ============================================================================= +presets: + @case "$(word 2, $(MAKECMDGOALS))" in \ + list) \ + echo "📋 Доступные пресеты:"; \ + echo ""; \ + preset_count=0; \ + for preset in molecule/presets/*.yml; do \ + if [ -f "$$preset" ]; then \ + preset_name=$$(basename "$$preset" .yml); \ + preset_desc=$$(grep -E "^#description:" "$$preset" | head -1 | sed 's/^#description: *//' || echo "Описание отсутствует"); \ + host_count=$$(grep -c "^- name:" "$$preset" 2>/dev/null || echo "?"); \ + printf " 📄 %s - %s (%s хостов)\n" "$$preset_name" "$$preset_desc" "$$host_count"; \ + preset_count=$$((preset_count + 1)); \ + fi; \ + done; \ + if [ $$preset_count -eq 0 ]; then \ + echo " ⚠️ Пресеты не найдены"; \ + fi;; \ + info) \ + if [ -z "$(PRESET)" ]; then \ + echo "❌ Ошибка: Укажите PRESET=имя_пресета"; \ + echo "💡 Пример: make presets info PRESET=etcd-patroni"; \ + exit 1; \ + fi; \ + if [ ! -f "molecule/presets/$(PRESET).yml" ]; then \ + echo "❌ Ошибка: Пресет '$(PRESET)' не найден!"; \ + echo "💡 Доступные пресеты:"; \ + make presets list; \ + exit 1; \ + fi; \ + echo "📋 Информация о пресете: $(PRESET)"; \ + echo ""; \ + echo "📄 Описание:"; \ + grep -E "^#description:" "molecule/presets/$(PRESET).yml" | head -1 | sed 's/^#description: *//' || echo "Описание отсутствует"; \ + echo ""; \ + echo "🏠 Хосты:"; \ + grep -E "^- name:" "molecule/presets/$(PRESET).yml" | sed 's/^- name: / - /' || echo "Хосты не найдены"; \ + echo ""; \ + echo "🌐 Сеть:"; \ + grep -E "^docker_network:" "molecule/presets/$(PRESET).yml" | sed 's/^docker_network: / - /' || echo "Сеть не указана"; \ + echo ""; \ + echo "🐳 Образы:"; \ + grep -E "^- " "molecule/presets/$(PRESET).yml" | grep -E "family:" | sed 's/.*family: / - /' || echo "Образы не найдены";; \ + test) \ + if [ -z "$(PRESET)" ]; then \ + echo "❌ Ошибка: Укажите PRESET=имя_пресета"; \ + echo "💡 Пример: make presets test PRESET=etcd-patroni"; \ + exit 1; \ + fi; \ + if [ ! -f "molecule/presets/$(PRESET).yml" ]; then \ + echo "❌ Ошибка: Пресет '$(PRESET)' не найден!"; \ + echo "💡 Доступные пресеты:"; \ + make presets list; \ + exit 1; \ + fi; \ + echo "🚀 Тестирование с пресетом: $(PRESET)"; \ + echo ""; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e ANSIBLE_FORCE_COLOR=1 \ + -e MOLECULE_PRESET=$(PRESET) \ + $(DOCKER_IMAGE) \ + bash -c "cd molecule/default && molecule test" || echo "✅ Тестирование завершено";; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 📋 make presets list - показать список всех preset'ов"; \ + echo " 💡 Показывает: название, описание, количество хостов"; \ + echo ""; \ + echo " 📄 make presets info - подробная информация о preset'е"; \ + echo " 💡 Показывает: описание, хосты, сеть, образы"; \ + echo " 💡 Требует: PRESET=имя_пресета"; \ + echo ""; \ + echo " 🚀 make presets test - запустить тест с preset'ом"; \ + echo " 💡 Запускает: molecule test с выбранным preset'ом"; \ + echo " 💡 Требует: PRESET=имя_пресета"; \ + echo ""; \ + echo "💡 Примеры:"; \ + echo " make presets list # показать все preset'ы"; \ + echo " make presets info PRESET=etcd-patroni # информация о etcd-patroni"; \ + echo " make presets test PRESET=minimal # тест с minimal preset"; \ + echo " make presets test PRESET=performance # тест с performance preset";; \ + esac + +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С VAULT +# ============================================================================= +vault: + @case "$(word 2, $(MAKECMDGOALS))" in \ + init) \ + echo "🔐 Инициализация vault..."; \ + if [ ! -f "vault/.vault" ]; then \ + echo "📝 Создание файла vault/.vault..."; \ + read -sp "Введите пароль для vault: " PASSWORD; \ + echo ""; \ + echo "$$PASSWORD" > vault/.vault; \ + chmod 600 vault/.vault; \ + echo "✅ Файл vault/.vault создан"; \ + else \ + echo "✅ Файл vault/.vault уже существует"; \ + fi;; \ + create) \ + if [ ! -f "vault/.vault" ]; then \ + echo "⚠️ Файл vault/.vault не найден!"; \ + echo "💡 Сначала создайте файл: make vault init"; \ + exit 1; \ + fi; \ + echo "🔐 Создание файла секретов..."; \ + read -p "Введите имя файла (без .yml): " FILE; \ + docker run --rm -it -v "$(PWD):/workspace" -w /workspace \ + $(DOCKER_IMAGE) \ + ansible-vault create --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ + edit) \ + echo "🔐 Редактирование секретов..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + docker run --rm -it -v "$(PWD):/workspace" -w /workspace \ + $(DOCKER_IMAGE) \ + ansible-vault edit --vault-password-file vault/.vault vault/$$FILE.yml;; \ + show) \ + echo "🔐 Просмотр секретов..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + $(DOCKER_IMAGE) \ + ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \ + delete) \ + echo "🔐 Удаление секретов..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + rm -f vault/$$FILE.yml;; \ + encrypt) \ + echo "🔐 Шифрование файла..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет файлов для шифрования"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + $(DOCKER_IMAGE) \ + ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ + decrypt) \ + echo "🔐 Расшифровка файла..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + $(DOCKER_IMAGE) \ + ansible-vault decrypt --vault-password-file vault/.vault vault/$$FILE.yml;; \ + rekey) \ + echo "🔐 Смена пароля..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + docker run --rm -it -v "$(PWD):/workspace" -w /workspace \ + $(DOCKER_IMAGE) \ + ansible-vault rekey --vault-password-file vault/.vault vault/$$FILE.yml;; \ + check) \ + echo "🔍 Проверка vault файлов..."; \ + if [ ! -d "vault" ]; then \ + echo "❌ Директория vault не найдена"; \ + exit 1; \ + fi; \ + vault_files=$$(find vault -name "*.yml" -type f 2>/dev/null); \ + if [ -z "$$vault_files" ]; then \ + echo "⚠️ Vault файлы не найдены"; \ + exit 0; \ + fi; \ + echo "📋 Найденные vault файлы:"; \ + for file in $$vault_files; do \ + echo " 📄 $$file"; \ + done; \ + echo ""; \ + echo "🔍 Проверка структуры..."; \ + for file in $$vault_files; do \ + if grep -q "ANSIBLE_VAULT" "$$file"; then \ + echo " ✅ $$file - зашифрован"; \ + else \ + echo " ⚠️ $$file - не зашифрован"; \ + fi; \ + done;; \ + scan) \ + echo "🔍 Поиск секретов в проекте..."; \ + echo "📋 Поиск потенциальных секретов:"; \ + find . -name "*.yml" -o -name "*.yaml" | grep -v ".git" | while read file; do \ + if grep -qE "(password|secret|key|token|api_key)" "$$file" 2>/dev/null; then \ + echo " ⚠️ $$file - содержит потенциальные секреты"; \ + fi; \ + done; \ + echo ""; \ + echo "💡 Рекомендации:"; \ + echo " - Используйте ansible-vault для шифрования секретов"; \ + echo " - Не храните секреты в открытом виде"; \ + echo " - Регулярно проверяйте файлы на наличие секретов";; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 🔑 make vault init - инициализировать vault (создать vault/.vault)"; \ + echo " 💡 Первая команда для настройки vault"; \ + echo ""; \ + echo " 🔐 make vault create - создать новый файл секретов"; \ + echo " 💡 Интерактивное создание зашифрованного файла"; \ + echo ""; \ + echo " ✏️ make vault edit - редактировать существующие секреты"; \ + echo " 💡 Открывает редактор для изменения секретов"; \ + echo ""; \ + echo " 👁️ make vault show - показать содержимое секретов"; \ + echo " 💡 Расшифровывает и показывает содержимое"; \ + echo ""; \ + echo " 🗑️ make vault delete - удалить файл секретов"; \ + echo " 💡 Безвозвратное удаление файла"; \ + echo ""; \ + echo " 🔒 make vault encrypt - зашифровать существующий файл"; \ + echo " 💡 Шифрует незашифрованный файл"; \ + echo ""; \ + echo " 🔓 make vault decrypt - расшифровать файл"; \ + echo " 💡 Создает незашифрованную копию"; \ + echo ""; \ + echo " 🔑 make vault rekey - сменить пароль шифрования"; \ + echo " 💡 Изменяет пароль для существующего файла"; \ + echo ""; \ + echo " ✅ make vault check - проверить vault файлы"; \ + echo " 💡 Проверяет структуру и статус файлов"; \ + echo ""; \ + echo " 🔍 make vault scan - поиск потенциальных секретов"; \ + echo " 💡 Сканирует проект на наличие незашифрованных секретов";; \ + esac + +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С GIT +# ============================================================================= git: @case "$(word 2, $(MAKECMDGOALS))" in \ push) \ - git branch; \ - read -p "Выберите ветку для пуша: " BRANCH; \ - read -p "Введите описание коммита: " COMMIT; \ - commitname=$$COMMIT; \ - git add . ; \ - git commit -m "$$commitname"; \ - git push -u origin $$BRANCH; \ - echo "Изменения внесены в Git";; \ + echo "📤 Отправка изменений в репозиторий..."; \ + git add .; \ + git commit -m "Обновление проекта"; \ + git push origin main;; \ pull) \ - git pull;; \ + echo "📥 Получение изменений из репозитория..."; \ + git pull origin main;; \ new) \ - read -p "Введите имя новой ветки: " BRANCH_NAME; \ - NEW_BRANCH="$$BRANCH_NAME"; \ - git checkout -b $$NEW_BRANCH; \ - echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \ - *) echo "Unknown action. Available actions: push, pull, cluster-branch";; \ - esac \ No newline at end of file + echo "🌿 Создание новой ветки..."; \ + read -p "Введите имя ветки: " BRANCH; \ + git checkout -b "$$BRANCH"; \ + echo "✅ Ветка '$$BRANCH' создана";; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 📤 make git push - отправить изменения в репозиторий"; \ + echo " 💡 Выполняет: git add . && git commit && git push"; \ + echo ""; \ + echo " 📥 make git pull - получить изменения из репозитория"; \ + echo " 💡 Выполняет: git pull origin main"; \ + echo ""; \ + echo " 🌿 make git new - создать новую ветку"; \ + echo " 💡 Интерактивно запрашивает имя ветки"; \ + echo " 💡 Выполняет: git checkout -b имя_ветки";; \ + esac + +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С DOCKER +# ============================================================================= +docker: + @case "$(word 2, $(MAKECMDGOALS))" in \ + prepare) \ + echo "🔧 Подготовка Docker образов для Docker Hub..."; \ + echo "📋 Registry: $(DOCKER_REGISTRY)"; \ + echo "📋 Version: $(DOCKER_VERSION)"; \ + echo "📋 Images: $(DOCKER_IMAGES)"; \ + echo ""; \ + echo "💡 Для работы с Docker Hub выполните:"; \ + echo " docker login - авторизация в Docker Hub"; \ + echo " make docker build - сборка образов"; \ + echo " make docker push - отправка в Docker Hub";; \ + build) \ + echo "🐳 Сборка Docker образов (multi-arch)..."; \ + echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \ + echo "📋 Builder: $(DOCKER_BUILDX_BUILDER)"; \ + echo "📋 Registry: $(DOCKER_REGISTRY)"; \ + echo "📋 Version: $(DOCKER_VERSION)"; \ + echo "📋 Images: $(DOCKER_IMAGES)"; \ + echo "⚠️ ВНИМАНИЕ: RED OS и Astra Linux собираются только для AMD64"; \ + echo ""; \ + $(MAKE) docker setup-builder; \ + for image in $(DOCKER_IMAGES); do \ + echo "🔨 Сборка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \ + $(MAKE) docker-build-image IMAGE=$$image; \ + done; \ + echo "✅ Образы собраны";; \ + rebuild) \ + echo "🔄 Полная пересборка Docker образов (multi-arch)..."; \ + echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \ + echo "📋 Builder: $(DOCKER_BUILDX_BUILDER)"; \ + echo "📋 Registry: $(DOCKER_REGISTRY)"; \ + echo "📋 Version: $(DOCKER_VERSION)"; \ + echo "📋 Images: $(DOCKER_IMAGES)"; \ + echo "⚠️ ВНИМАНИЕ: RED OS и Astra Linux собираются только для AMD64"; \ + echo "🧹 Очистка кеша и старых образов..."; \ + echo ""; \ + $(MAKE) docker clean; \ + $(MAKE) docker clean-builder; \ + $(MAKE) docker setup-builder; \ + for image in $(DOCKER_IMAGES); do \ + echo "🔨 Пересборка $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION)"; \ + $(MAKE) docker-build-image IMAGE=$$image; \ + done; \ + echo "✅ Образы пересобраны с нуля";; \ + push) \ + echo "📤 Отправка Docker образов в Docker Hub..."; \ + for image in $(DOCKER_IMAGES); do \ + echo "📤 Отправка $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION)"; \ + docker push $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION); \ + done; \ + echo "✅ Образы отправлены в Docker Hub";; \ + pull) \ + echo "📥 Загрузка Docker образов из Docker Hub..."; \ + for image in $(DOCKER_IMAGES); do \ + echo "📥 Загрузка $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION)"; \ + docker pull $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION) || echo "⚠️ Образ $$image не найден в Docker Hub"; \ + done; \ + echo "✅ Загрузка завершена";; \ + clean) \ + echo "🧹 Очистка Docker образов и builds..."; \ + for image in $(DOCKER_IMAGES); do \ + echo "🗑️ Удаление $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION)"; \ + docker rmi $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION) 2>/dev/null || true; \ + done; \ + echo "🗑️ Удаление кеша builds для наших образов..."; \ + docker buildx prune --filter type=exec.cachemount --filter type=source.local --filter type=source.git.checkout --force 2>/dev/null || true; \ + echo "✅ Образы и кеш builds очищены";; \ + info) \ + echo "📊 Информация об образах..."; \ + for image in $(DOCKER_IMAGES); do \ + if docker images | grep -q "$(DOCKER_REGISTRY):$$image"; then \ + echo "📦 $(DOCKER_REGISTRY):$$image-$(DOCKER_VERSION)"; \ + docker images | grep "$(DOCKER_REGISTRY):$$image" | head -1; \ + fi; \ + done;; \ + update) \ + echo "🔄 Обновление всех образов..."; \ + $(MAKE) docker pull; \ + $(MAKE) docker build; \ + $(MAKE) docker push; \ + echo "✅ Все образы обновлены";; \ + purge) \ + echo "🧹 Полная очистка Docker..."; \ + echo "⚠️ ВНИМАНИЕ: Это удалит ВСЕ Docker данные!"; \ + echo ""; \ + read -p "Продолжить? (y/N): " confirm; \ + if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \ + echo "🛑 Остановка всех контейнеров..."; \ + docker stop $$(docker ps -aq) 2>/dev/null || true; \ + echo "🗑️ Удаление всех контейнеров..."; \ + docker rm $$(docker ps -aq) 2>/dev/null || true; \ + echo "🗑️ Удаление всех образов..."; \ + docker rmi $$(docker images -aq) 2>/dev/null || true; \ + echo "🗑️ Удаление всех томов..."; \ + docker volume rm $$(docker volume ls -q) 2>/dev/null || true; \ + echo "🗑️ Удаление всех сетей..."; \ + docker network rm $$(docker network ls -q) 2>/dev/null || true; \ + echo "🧹 Очистка системы..."; \ + docker system prune -af --volumes; \ + echo "✅ Docker полностью очищен"; \ + else \ + echo "❌ Очистка отменена"; \ + fi;; \ + clean-builder) \ + echo "🧹 Очистка multi-arch builder..."; \ + $(MAKE) docker-reset-builder;; \ + build-image) \ + if [ -z "$(IMAGE)" ]; then \ + echo "❌ Ошибка: Укажите IMAGE=имя_образа"; \ + echo "💡 Пример: make docker build-image IMAGE=centos"; \ + echo "💡 Доступные образы: $(DOCKER_IMAGES)"; \ + exit 1; \ + fi; \ + if [ ! -d "dockerfiles/$(IMAGE)" ]; then \ + echo "❌ Ошибка: Директория dockerfiles/$(IMAGE) не найдена!"; \ + echo "💡 Доступные образы:"; \ + for img in $(DOCKER_IMAGES); do \ + if [ -d "dockerfiles/$$img" ]; then \ + echo " - $$img"; \ + fi; \ + done; \ + exit 1; \ + fi; \ + echo "🔨 Сборка отдельного образа: $(IMAGE)"; \ + echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \ + echo "📋 Builder: $(DOCKER_BUILDX_BUILDER)"; \ + echo "📋 Registry: $(DOCKER_REGISTRY)"; \ + echo ""; \ + $(MAKE) docker setup-builder; \ + $(MAKE) docker-build-image IMAGE=$(IMAGE); \ + echo "✅ Образ $(IMAGE) собран";; \ + setup-builder) \ + echo "🔧 Настройка multi-arch builder в контейнере..."; \ + if $(MAKE) docker-check-builder >/dev/null 2>&1; then \ + echo "✅ Builder $(DOCKER_BUILDX_BUILDER) уже существует и готов"; \ + docker buildx use $(DOCKER_BUILDX_BUILDER); \ + else \ + echo "📦 Создание builder $(DOCKER_BUILDX_BUILDER)..."; \ + $(MAKE) docker-create-builder; \ + fi; \ + echo "🔍 Финальная проверка builder..."; \ + $(MAKE) docker-check-builder;; \ + diagnose) \ + echo "🔍 Диагностика buildx проблем..."; \ + $(MAKE) docker-diagnose-buildx;; \ + reset-builder) \ + echo "🔄 Сброс buildx builder..."; \ + $(MAKE) docker-reset-builder;; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 🔧 make docker prepare - подготовка к работе с Docker Hub"; \ + echo " 💡 Показывает: registry, version, список образов"; \ + echo " 💡 Рекомендует: docker login перед работой"; \ + echo ""; \ + echo " 🐳 make docker build - собрать все Docker образы (multi-arch)"; \ + echo " 💡 Собирает: ansible-controller, alt-linux, astra-linux, redos"; \ + echo " 💡 Собирает: rhel, centos, alma, rocky, ubuntu, debian"; \ + echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ + echo " 💡 Ограничения: RED OS и Astra Linux только AMD64"; \ + echo " 💡 Тегирует: inecs/образ: (автоматически извлекает теги)"; \ + echo " 💡 Отправляет: автоматически в Docker Hub"; \ + echo ""; \ + echo " 🔨 make docker build-image IMAGE=<имя> - собрать отдельный образ"; \ + echo " 💡 Пример: make docker build-image IMAGE=centos"; \ + echo " 💡 Собирает: только указанный образ (multi-arch)"; \ + echo " 💡 Доступные образы: $(DOCKER_IMAGES)"; \ + echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ + echo ""; \ + echo " 🔄 make docker rebuild - полная пересборка с очисткой кеша"; \ + echo " 💡 Очищает: все локальные образы и кеш"; \ + echo " 💡 Пересобирает: все образы с нуля"; \ + echo " 💡 Полезно: при проблемах с кешем или зависимостями"; \ + echo " 💡 Выполняет: clean + clean-builder + setup-builder + build"; \ + echo ""; \ + echo " 📤 make docker push - отправить образы в Docker Hub"; \ + echo " 💡 Требует: docker login"; \ + echo " 💡 Отправляет: все образы в registry inecs"; \ + echo ""; \ + echo " 📥 make docker pull - загрузить образы из Docker Hub"; \ + echo " 💡 Загружает: все образы из registry inecs"; \ + echo " 💡 Пропускает: отсутствующие образы"; \ + echo ""; \ + echo " 🧹 make docker clean - удалить локальные образы и кеш builds"; \ + echo " 💡 Удаляет: все образы inecs/ansible-lab:*"; \ + echo " 💡 Очищает: кеш builds (exec.cachemount, source.local, git.checkout)"; \ + echo " 💡 Сохраняет: другие builds в системе"; \ + echo " 💡 Безопасно: игнорирует ошибки"; \ + echo ""; \ + echo " 🧹 make docker clean-builder - очистка multi-arch builder"; \ + echo " 💡 Удаляет: builder контейнер и buildkit контейнеры"; \ + echo " 💡 Полезно: при проблемах со сборкой";; \ + setup-builder) \ + echo "🔧 Настройка multi-arch builder в контейнере..."; \ + if $(MAKE) docker-check-builder >/dev/null 2>&1; then \ + echo "✅ Builder $(DOCKER_BUILDX_BUILDER) уже существует и готов"; \ + docker buildx use $(DOCKER_BUILDX_BUILDER); \ + else \ + echo "📦 Создание builder $(DOCKER_BUILDX_BUILDER)..."; \ + $(MAKE) docker-create-builder; \ + fi; \ + echo "🔍 Финальная проверка builder..."; \ + $(MAKE) docker-check-builder;; \ + diagnose) \ + echo "🔍 Диагностика buildx проблем..."; \ + $(MAKE) docker-diagnose-buildx;; \ + reset-builder) \ + echo "🔄 Сброс buildx builder..."; \ + $(MAKE) docker-reset-builder;; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 🔧 make docker prepare - подготовка к работе с Docker Hub"; \ + echo " 💡 Показывает: registry, version, список образов"; \ + echo " 💡 Рекомендует: docker login перед работой"; \ + echo ""; \ + echo " 🐳 make docker build - собрать все Docker образы (multi-arch)"; \ + echo " 💡 Собирает: ansible-controller, alt-linux, astra-linux, redos"; \ + echo " 💡 Собирает: rhel, centos, alma, rocky, ubuntu, debian"; \ + echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ + echo " 💡 Ограничения: RED OS и Astra Linux только AMD64"; \ + echo " 💡 Тегирует: inecs/образ: (автоматически извлекает теги)"; \ + echo " 💡 Отправляет: автоматически в Docker Hub"; \ + echo ""; \ + echo " 🔨 make docker build-image IMAGE=<имя> - собрать отдельный образ"; \ + echo " 💡 Пример: make docker build-image IMAGE=centos"; \ + echo " 💡 Собирает: только указанный образ (multi-arch)"; \ + echo " 💡 Доступные образы: $(DOCKER_IMAGES)"; \ + echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ + echo ""; \ + echo " 🔄 make docker rebuild - полная пересборка с очисткой кеша"; \ + echo " 💡 Очищает: все локальные образы и кеш"; \ + echo " 💡 Пересобирает: все образы с нуля"; \ + echo " 💡 Полезно: при проблемах с кешем или зависимостями"; \ + echo " 💡 Выполняет: clean + clean-builder + setup-builder + build"; \ + echo ""; \ + echo " 📤 make docker push - отправить образы в Docker Hub"; \ + echo " 💡 Требует: docker login"; \ + echo " 💡 Отправляет: все образы в registry inecs"; \ + echo ""; \ + echo " 📥 make docker pull - загрузить образы из Docker Hub"; \ + echo " 💡 Загружает: все образы из registry inecs"; \ + echo " 💡 Пропускает: отсутствующие образы"; \ + echo ""; \ + echo " 🧹 make docker clean - удалить локальные образы и кеш builds"; \ + echo " 💡 Удаляет: все образы inecs/ansible-lab:*"; \ + echo " 💡 Очищает: кеш builds (exec.cachemount, source.local, git.checkout)"; \ + echo " 💡 Сохраняет: другие builds в системе"; \ + echo " 💡 Безопасно: игнорирует ошибки"; \ + echo ""; \ + echo " 🧹 make docker clean-builder - очистка multi-arch builder"; \ + echo " 💡 Удаляет: builder контейнер и buildkit контейнеры"; \ + echo " 💡 Полезно: при проблемах со сборкой"; \ + echo ""; \ + echo " 🔧 make docker setup-builder - настройка multi-arch builder"; \ + echo " 💡 Создает: builder в контейнере (не в системе)"; \ + echo " 💡 Поддерживает: amd64 и arm64 архитектуры"; \ + echo " 💡 Безопасно: использует inspect вместо buildx ls"; \ + echo ""; \ + echo " 🔍 make docker diagnose - диагностика buildx проблем"; \ + echo " 💡 Проверяет: версии, контексты, builder, registry"; \ + echo " 💡 Показывает: рекомендации по устранению проблем"; \ + echo ""; \ + echo " 🔄 make docker reset-builder - сброс buildx builder"; \ + echo " 💡 Удаляет: старый builder и buildkit контейнеры"; \ + echo " 💡 Создает: новый builder с предварительной загрузкой образа"; \ + echo ""; \ + echo " 📊 make docker info - информация о собранных образах"; \ + echo " 💡 Показывает: размер, дата создания, теги"; \ + echo ""; \ + echo " 🔄 make docker update - обновить все образы"; \ + echo " 💡 Выполняет: pull + build + push"; \ + echo " 💡 Полный цикл обновления"; \ + echo ""; \ + echo " 💥 make docker purge - ПОЛНАЯ очистка Docker"; \ + echo " ⚠️ УДАЛЯЕТ: все контейнеры, образы, тома, сети"; \ + echo " ⚠️ ОСТАНОВИТ: все запущенные контейнеры"; \ + echo " ⚠️ ТРЕБУЕТ: подтверждение пользователя"; \ + echo "";; \ + esac + +# ============================================================================= +# ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ DOCKER +# ============================================================================= + +# Надежная проверка существования buildx builder без использования buildx ls +# Использует docker buildx inspect вместо buildx ls для избежания зависаний +.PHONY: docker-check-builder +docker-check-builder: + @echo "🔍 Проверка buildx builder $(DOCKER_BUILDX_BUILDER)..." + @if docker buildx inspect $(DOCKER_BUILDX_BUILDER) >/dev/null 2>&1; then \ + echo "✅ Builder $(DOCKER_BUILDX_BUILDER) существует и готов"; \ + exit 0; \ + else \ + echo "❌ Builder $(DOCKER_BUILDX_BUILDER) не найден"; \ + exit 1; \ + fi + +# Безопасное создание buildx builder с предварительной очисткой +.PHONY: docker-create-builder +docker-create-builder: + @echo "🔧 Создание buildx builder $(DOCKER_BUILDX_BUILDER)..." + @echo "📦 Предварительная загрузка образа buildkit..." + @docker pull moby/buildkit:buildx-stable-1 || echo "⚠️ Не удалось загрузить moby/buildkit:buildx-stable-1, будет использован авто-пулл" + @echo "🗑️ Удаление существующего builder (если есть)..." + @docker buildx rm -f $(DOCKER_BUILDX_BUILDER) 2>/dev/null || true + @echo "📦 Создание нового builder..." + @docker buildx create \ + --name $(DOCKER_BUILDX_BUILDER) \ + --driver docker-container \ + --driver-opt image=moby/buildkit:buildx-stable-1 \ + --use || exit 1 + @echo "⏳ Ожидание запуска buildkit контейнера..." + @sleep 3 + @echo "🔍 Проверка готовности builder..." + @docker buildx inspect --builder $(DOCKER_BUILDX_BUILDER) --bootstrap >/dev/null || exit 1 + @echo "✅ Builder $(DOCKER_BUILDX_BUILDER) создан и готов к работе" + +# Диагностика проблем с buildx +.PHONY: docker-diagnose-buildx +docker-diagnose-buildx: + @echo "🔍 ДИАГНОСТИКА BUILDX ПРОБЛЕМ" + @echo "==========================================" + @echo "" + @echo "📊 1. Версии Docker и Buildx:" + @docker version --format "Docker: {{.Server.Version}}" 2>/dev/null || echo "❌ Docker недоступен" + @docker buildx version 2>/dev/null || echo "❌ Buildx недоступен" + @echo "" + @echo "📋 2. Docker контексты (поиск мертвых tcp://):" + @docker context ls 2>/dev/null || echo "❌ Не удалось получить список контекстов" + @echo "" + @echo "🔍 3. Проверка builder $(DOCKER_BUILDX_BUILDER):" + @if docker buildx inspect $(DOCKER_BUILDX_BUILDER) >/dev/null 2>&1; then \ + echo "✅ Builder $(DOCKER_BUILDX_BUILDER) существует"; \ + docker buildx inspect $(DOCKER_BUILDX_BUILDER) --bootstrap >/dev/null 2>&1 && echo "✅ Builder готов" || echo "❌ Builder не готов"; \ + else \ + echo "❌ Builder $(DOCKER_BUILDX_BUILDER) не найден"; \ + fi + @echo "" + @echo "🐳 4. Buildkit контейнеры:" + @docker ps -a --filter "name=buildx_buildkit" --format "table {{.Names}}\t{{.Status}}\t{{.CreatedAt}}" 2>/dev/null || echo "❌ Не удалось получить список контейнеров" + @echo "" + @echo "🌐 5. Проверка доступа к registry:" + @echo "📥 Тест загрузки moby/buildkit:buildx-stable-1..." + @timeout 30 docker pull moby/buildkit:buildx-stable-1 >/dev/null 2>&1 && echo "✅ Доступ к registry OK" || echo "❌ Проблемы с доступом к registry" + @echo "" + @echo "🔧 6. Docker socket доступ:" + @if [ -S /var/run/docker.sock ]; then \ + echo "✅ Docker socket доступен: /var/run/docker.sock"; \ + ls -la /var/run/docker.sock; \ + else \ + echo "❌ Docker socket недоступен: /var/run/docker.sock"; \ + fi + @echo "" + @echo "💡 РЕКОМЕНДАЦИИ:" + @echo " - Если buildx ls зависает: удалите мертвые контексты (docker context rm )" + @echo " - Если pull зависает: настройте прокси или используйте mirror registry" + @echo " - Если builder не создается: проверьте права доступа к Docker socket" + @echo " - Для полной очистки: make docker clean-builder && make docker-create-builder" + +# Быстрая очистка и пересоздание builder +.PHONY: docker-reset-builder +docker-reset-builder: + @echo "🔄 Сброс buildx builder..." + @echo "🗑️ Удаление builder $(DOCKER_BUILDX_BUILDER)..." + @docker buildx rm -f $(DOCKER_BUILDX_BUILDER) 2>/dev/null || true + @echo "🧹 Очистка buildkit контейнеров..." + @docker ps -a --filter "name=buildx_buildkit" --format "{{.Names}}" | xargs -r docker rm -f 2>/dev/null || true + @echo "📦 Создание нового builder..." + @$(MAKE) docker-create-builder + @echo "✅ Builder сброшен и готов к работе" + + +# Извлечение тега из базового образа +docker-get-base-tag: + @if [ -z "$(IMAGE)" ]; then \ + echo "❌ Ошибка: IMAGE не указан"; \ + exit 1; \ + fi; \ + case "$(IMAGE)" in \ + alt-linux) \ + BASE_IMAGE="alt:p9"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + astra-linux) \ + BASE_IMAGE="registry.astralinux.ru/library/astra/ubi17:1.7.6.uu2"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + redos) \ + BASE_IMAGE="registry.red-soft.ru/ubi7/ubi"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + rhel) \ + BASE_IMAGE="registry.access.redhat.com/ubi8/ubi"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + centos7) \ + BASE_IMAGE="centos:7"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + centos8) \ + BASE_IMAGE="quay.io/centos/centos:8"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + centos9) \ + BASE_IMAGE="quay.io/centos/centos:stream9"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + alma) \ + BASE_IMAGE="almalinux:8"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + rocky) \ + BASE_IMAGE="rockylinux:8"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + ubuntu20) \ + BASE_IMAGE="ubuntu:20.04"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + ubuntu22) \ + BASE_IMAGE="ubuntu:22.04"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + ubuntu24) \ + BASE_IMAGE="ubuntu:24.04"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + debian9) \ + BASE_IMAGE="debian:9"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + debian10) \ + BASE_IMAGE="debian:10"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + debian11) \ + BASE_IMAGE="debian:11"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + debian12) \ + BASE_IMAGE="debian:bookworm"; \ + echo "📦 Загрузка базового образа $$BASE_IMAGE..." >&2; \ + docker pull $$BASE_IMAGE >/dev/null 2>&1 || echo "⚠️ Не удалось загрузить $$BASE_IMAGE" >&2; \ + TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ + ansible-controller) \ + TAG="latest";; \ + *) \ + echo "❌ Неизвестный образ: $(IMAGE)"; \ + exit 1;; \ + esac; \ + echo "$$TAG" + +# Сборка одного образа с multi-arch +docker-build-image: + @if [ -z "$(IMAGE)" ]; then \ + echo "❌ Ошибка: IMAGE не указан"; \ + exit 1; \ + fi; \ + TAG=$$($(MAKE) docker-get-base-tag IMAGE=$(IMAGE)); \ + if [ "$(IMAGE)" = "redos" ] || [ "$(IMAGE)" = "astra-linux" ]; then \ + PLATFORMS="linux/amd64"; \ + echo ""; \ + echo "=========================================="; \ + echo "🔨 СБОРКА ОБРАЗА: $(DOCKER_REGISTRY):$(IMAGE)-$$TAG"; \ + echo "📋 Платформы: $$PLATFORMS (только AMD64)"; \ + echo "📋 Тег: $$TAG"; \ + echo "📋 Registry: $(DOCKER_REGISTRY)"; \ + echo "⚠️ ВНИМАНИЕ: Базовый образ поддерживает только AMD64"; \ + echo "=========================================="; \ + else \ + PLATFORMS="$(DOCKER_PLATFORMS)"; \ + echo ""; \ + echo "=========================================="; \ + echo "🔨 СБОРКА ОБРАЗА: $(DOCKER_REGISTRY):$(IMAGE)-$$TAG"; \ + echo "📋 Платформы: $$PLATFORMS"; \ + echo "📋 Тег: $$TAG"; \ + echo "📋 Registry: $(DOCKER_REGISTRY)"; \ + echo "=========================================="; \ + fi; \ + echo ""; \ + cd dockerfiles/$(IMAGE) && \ + docker buildx build \ + --platform $$PLATFORMS \ + --tag $(DOCKER_REGISTRY):$(IMAGE)-$$TAG \ + --tag $(DOCKER_REGISTRY):$(IMAGE)-latest \ + --push \ + .; \ + echo ""; \ + echo "✅ УСПЕШНО: $(DOCKER_REGISTRY):$(IMAGE)-$$TAG собран и отправлен"; \ + echo "==========================================" + + +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С ANSIBLE-CONTROLLER +# ============================================================================= +controller: + @case "$(word 2, $(MAKECMDGOALS))" in \ + build) \ + echo "🔨 Сборка ansible-controller (multi-arch)..."; \ + echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \ + $(MAKE) docker setup-builder; \ + cd dockerfiles/ansible-controller && \ + docker buildx build \ + --platform $(DOCKER_PLATFORMS) \ + --tag $(DOCKER_REGISTRY):ansible-controller-$(DOCKER_VERSION) \ + --tag $(DOCKER_REGISTRY):ansible-controller-latest \ + --push \ + .; \ + echo "✅ ansible-controller собран и отправлен";; \ + rebuild) \ + echo "🔄 Пересборка ansible-controller с исправлениями..."; \ + echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \ + echo "🔧 Исправления: добавлен passlib для хеширования паролей"; \ + $(MAKE) docker setup-builder; \ + cd dockerfiles/ansible-controller && \ + docker buildx build \ + --platform $(DOCKER_PLATFORMS) \ + --tag $(DOCKER_REGISTRY):ansible-controller-$(DOCKER_VERSION) \ + --tag $(DOCKER_REGISTRY):ansible-controller-latest \ + --push \ + --no-cache \ + .; \ + echo "✅ ansible-controller пересобран с исправлениями";; \ + run) \ + echo "🚀 Запуск ansible-controller..."; \ + cd dockerfiles/ansible-controller && docker-compose up -d; \ + echo "✅ ansible-controller запущен";; \ + stop) \ + echo "🛑 Остановка ansible-controller..."; \ + cd dockerfiles/ansible-controller && docker-compose down; \ + echo "✅ ansible-controller остановлен";; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 🔨 make controller build - собрать ansible-controller (multi-arch)"; \ + echo " 💡 Собирает: inecs/ansible-lab:ansible-controller-latest"; \ + echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ + echo " 💡 Использует: dockerfiles/ansible-controller/Dockerfile"; \ + echo " 💡 Requirements: dockerfiles/ansible-controller/requirements.yml"; \ + echo ""; \ + echo " 🔄 make controller rebuild - пересобрать ansible-controller с исправлениями"; \ + echo " 💡 Пересобирает: с --no-cache для применения исправлений"; \ + echo " 💡 Исправления: добавлен passlib для хеширования паролей"; \ + echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ + echo ""; \ + echo " 🚀 make controller run - запустить ansible-controller"; \ + echo " 💡 Запускает: docker-compose up -d"; \ + echo " 💡 Использует: dockerfiles/ansible-controller/docker-compose.yml"; \ + echo ""; \ + echo " 🛑 make controller stop - остановить ansible-controller"; \ + echo " 💡 Останавливает: docker-compose down"; \ + echo " 💡 Удаляет: контейнеры и сети";; \ + esac + +# ============================================================================= +# СПРАВКА +# ============================================================================= +help: + @echo "==========================================" + @echo "AnsibleTemplate - Универсальная система" + @echo "тестирования Ansible ролей" + @echo "==========================================" + @echo "" + @echo "📁 Структура проекта:" + @echo " scripts/ - Скрипты автоматизации" + @echo " inventory/ - Инвентори файлы" + @echo " molecule/default/ - Molecule конфигурация" + @echo " roles/ - Ansible роли" + @echo " vault/ - Зашифрованные секреты" + @echo " dockerfiles/ - Docker образы для тестирования" + @echo "" + @echo "🚀 ОСНОВНЫЕ КОМАНДЫ:" + @echo " make role lint [role] - проверить синтаксис ролей (все или конкретную)" + @echo " 💡 Примеры: make role lint, make role lint devops" + @echo " make role test [preset] - протестировать роли с preset'ом" + @echo " make role deploy - развернуть роли на реальные серверы" + @echo " make role list - показать все роли" + @echo " make role create - создать новую роль (интерактивно)" + @echo " make role delete - удалить роль (интерактивно)" + @echo "" + @echo "📖 ДОКУМЕНТАЦИЯ:" + @echo " docs/deploy-yml-customization.md - полное руководство по кастомизации" + @echo " docs/linting-guide.md - руководство по линтингу ролей" + @echo "" + @echo "🔍 ЛИНТИНГ РОЛЕЙ:" + @echo " make role lint [role] - проверить синтаксис (все или конкретную роль)" + @echo " 💡 Профили: production, basic, min" + @echo " 💡 Конфигурация: .ansible-lint" + @echo " 💡 Валидация: автоматическая проверка существования роли" + @echo "" + @echo "📋 PRESET'Ы (тестовые окружения):" + @echo " make presets list - показать все доступные preset'ы" + @echo " make presets info - подробная информация о preset'е" + @echo " make presets test - запустить тест с preset'ом" + @echo "" + @echo "🖼️ СОБСТВЕННЫЕ ОБРАЗЫ (AnsibleTemplate):" + @echo " make custom-images test [minimal|full|performance] - тест с собственными образами" + @echo " make custom-images check - проверить наличие собственных образов" + @echo " make custom-images build - собрать все образы для тестирования" + @echo "" + @echo "🐳 DOCKER ОБРАЗЫ (Multi-Arch):" + @echo " make docker prepare - подготовка к работе с Docker Hub" + @echo " make docker build - собрать все Docker образы (amd64 + arm64)" + @echo " make docker build-image IMAGE=<имя> - собрать отдельный образ" + @echo " make docker rebuild - полная пересборка с очисткой кеша" + @echo " make docker push - отправить образы в Docker Hub" + @echo " make docker pull - загрузить образы из Docker Hub" + @echo " make docker clean - удалить локальные образы" + @echo " make docker info - информация о собранных образах" + @echo " make docker update - обновить все образы (pull + build + push)" + @echo " make docker purge - ПОЛНАЯ очистка Docker (ОСТОРОЖНО!)" + @echo "" + @echo "🔧 DOCKER BUILDER (Multi-Arch):" + @echo " make docker setup-builder - настройка multi-arch builder в контейнере" + @echo " make docker clean-builder - очистка multi-arch builder" + @echo " make docker diagnose - диагностика buildx проблем" + @echo " make docker reset-builder - сброс buildx builder" + @echo " 💡 Поддерживает: amd64, arm64, riscv64, ppc64le, s390x, 386, arm/v7, arm/v6" + @echo "" + @echo "🔧 АВТОМАТИЗАЦИЯ:" + @echo " make update-playbooks - обновление playbook'ов при добавлении ролей" + @echo " make generate-docs - генерация документации для ролей" + @echo " make setup-cicd - настройка CI/CD для всех платформ" + @echo " 💡 Безопасно: использует inspect вместо buildx ls (избегает зависаний)" + @echo "" + @echo "🔐 VAULT (управление секретами):" + @echo " make vault init - инициализировать vault (создать vault/.vault)" + @echo " make vault create - создать новый файл секретов" + @echo " make vault edit - редактировать существующие секреты" + @echo " make vault show - показать содержимое секретов" + @echo " make vault delete - удалить файл секретов" + @echo " make vault encrypt - зашифровать файл" + @echo " make vault decrypt - расшифровать файл" + @echo " make vault rekey - сменить пароль шифрования" + @echo " make vault check - проверить vault файлы" + @echo " make vault scan - поиск потенциальных секретов" + @echo "" + @echo "🌿 GIT (управление версиями):" + @echo " make git push - отправить изменения в репозиторий" + @echo " make git pull - получить изменения из репозитория" + @echo " make git new - создать новую ветку" + @echo "" + @echo "🎮 CONTROLLER (ansible-controller Multi-Arch):" + @echo " make controller build - собрать ansible-controller (amd64 + arm64)" + @echo " make controller run - запустить ansible-controller" + @echo " make controller stop - остановить ansible-controller" + @echo "" + @echo "💡 ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:" + @echo " make presets list # показать все preset'ы" + @echo " make presets test PRESET=etcd-patroni # тест с etcd-patroni" + @echo " make role test minimal # быстрый тест" + @echo " make role test all-images # тест всех образов" + @echo " make docker setup-builder # настройка multi-arch builder" + @echo " make docker diagnose # диагностика buildx проблем" + @echo " make docker reset-builder # сброс buildx builder" + @echo " make docker build # собрать все образы (amd64 + arm64)" + @echo " make docker rebuild # полная пересборка с очисткой кеша" + @echo " make controller build # собрать ansible-controller (multi-arch)" + @echo " make docker clean-builder # очистка builder'а" + @echo " make docker purge # полная очистка Docker" + @echo " make vault init # инициализировать vault" + @echo " make vault create # создать секреты" + @echo "" + @echo "📖 Подробная справка: make [команда]" + @echo "==========================================" + +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С СОБСТВЕННЫМИ ОБРАЗАМИ +# ============================================================================= +custom-images: + @case "$(word 2, $(MAKECMDGOALS))" in \ + test) \ + echo "🧪 Тестирование с собственными образами AnsibleTemplate..."; \ + if [ -z "$(word 3, $(MAKECMDGOALS))" ]; then \ + echo "💡 Использование: make custom-images test [minimal|full|performance]"; \ + echo "💡 По умолчанию: minimal"; \ + ./scripts/test-custom-images.sh minimal; \ + else \ + ./scripts/test-custom-images.sh $(word 3, $(MAKECMDGOALS)); \ + fi;; \ + check) \ + echo "🔍 Проверка наличия собственных образов..."; \ + ./scripts/test-custom-images.sh check;; \ + build) \ + echo "🔨 Сборка всех образов для тестирования..."; \ + $(MAKE) docker build;; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 🧪 make custom-images test [minimal|full|performance] - тест с собственными образами"; \ + echo " 💡 minimal - минимальный тест (4 хоста)"; \ + echo " 💡 full - полный тест (все образы)"; \ + echo " 💡 performance - тест производительности (8 хостов)"; \ + echo ""; \ + echo " 🔍 make custom-images check - проверить наличие собственных образов"; \ + echo " 💡 Показывает: какие образы есть, какие отсутствуют"; \ + echo " 💡 Предлагает: команды для сборки отсутствующих образов"; \ + echo ""; \ + echo " 🔨 make custom-images build - собрать все образы для тестирования"; \ + echo " 💡 Выполняет: make docker build"; \ + echo " 💡 Собирает: все образы AnsibleTemplate"; \ + echo ""; \ + echo "💡 Пресеты для тестирования:"; \ + echo " - custom-minimal.yml - минимальный тест (4 хоста)"; \ + echo " - custom-images.yml - полный тест (все образы)"; \ + echo " - custom-performance.yml - тест производительности (8 хостов)"; \ + echo ""; \ + echo "💡 Собственные образы:"; \ + echo " - inecs/ansible-lab:ansible-controller-latest"; \ + echo " - inecs/ansible-lab:alt-linux-latest"; \ + echo " - inecs/ansible-lab:astra-linux-latest"; \ + echo " - inecs/ansible-lab:redos-latest"; \ + echo " - inecs/ansible-lab:rhel-latest"; \ + echo " - inecs/ansible-lab:centos-latest"; \ + echo " - inecs/ansible-lab:alma-latest"; \ + echo " - inecs/ansible-lab:rocky-latest"; \ + echo " - inecs/ansible-lab:ubuntu-latest"; \ + echo " - inecs/ansible-lab:debian-latest";; \ + esac + +# ============================================================================= +# АВТОМАТИЗАЦИЯ +# ============================================================================= + +update-playbooks: + @echo "🔄 Обновление playbook'ов..." + @chmod +x scripts/update-playbooks.sh + @./scripts/update-playbooks.sh + +generate-docs: + @echo "📚 Генерация документации..." + @chmod +x scripts/generate-role-docs.sh + @./scripts/generate-role-docs.sh + +setup-cicd: + @echo "🔧 Настройка CI/CD..." + @chmod +x scripts/setup-cicd.sh + @./scripts/setup-cicd.sh + +# Очистка контейнеров Molecule +.PHONY: clean-containers +clean-containers: + @echo "🧹 Очистка контейнеров Molecule..." + @echo "📋 Поиск контейнеров проекта..." + @docker ps -a --filter "ancestor=inecs/ansible-lab" --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" || true + @echo "" + @echo "🗑️ Удаление контейнеров..." + @docker ps -a --filter "ancestor=inecs/ansible-lab" --format "{{.ID}}" | xargs -r docker rm -f 2>/dev/null || true + @docker ps -a --filter "network=labnet" --format "{{.ID}}" | xargs -r docker rm -f 2>/dev/null || true + @echo "🧹 Очистка сетей..." + @docker network rm labnet 2>/dev/null || true + @echo "✅ Очистка завершена" + +# Пустые цели для совместимости +view create edit show delete lint deploy new advanced list info test build push pull clean prepare update run stop purge clean-builder setup-builder diagnose reset-builder build-image: + @true + +# Универсальный таргет для всех пресетов и других динамических целей +%: + @: diff --git a/README.md b/README.md index b371258..698beb5 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,406 @@ -# AnsibleTemplate +# AnsibleTemplate - Универсальная система тестирования Ansible ролей -Темплейт для создания, проверки и тестирование ролей Ansible с помощью контейнеров Docker. +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru +**Версия:** 2.0.0 -### С чего начать? +## 📋 Описание -На вашей машине вам необходимо сбилдить образ, где будут запускаться все роли через docker-compose. +AnsibleTemplate - это универсальная система для разработки, тестирования и развертывания Ansible ролей с использованием Docker, Molecule и preset конфигураций. Система поддерживает тестирование на различных ОС через Docker контейнеры. -Это можно сделать самостоятельно: +## ✨ Ключевые возможности -- **make docker build** - создание контейнера -- **make docker rebuild** - пересоздание контейнера, если были внесены изменения в Dockerfile -- **make docker prune** - очистить систему от лишних образов -- **make docker shell** - войти в контейнер Shell -- **make docker release** - собирает образ контейнера и пушит его в докер реджистри -- **make docker images** - собрать образы контейнеров с systemd, для удобного тестирования ролей -- **make images** - собрать и запушить все образы (основной Ansible, CentOS, Ubuntu) в Docker Hub (inecs/ansible) +- **Тестирование ролей** через Molecule с Docker +- **Preset система** для быстрого выбора окружений тестирования +- **Мультиплатформенное тестирование** (Ubuntu, Debian, CentOS, AlmaLinux, RHEL и другие) +- **Автоматическая проверка** синтаксиса Ansible ролей +- **Управление секретами** через Ansible Vault +- **Готовые Docker образы** для разных ОС -Или ввести команду: +## 📁 Структура проекта -- **make init** - которая создаст файл секретов с паролем. Сбилдит образ. И создаст новую роль. - -### Работа с ролью -- **make role new** - создать новую роль из шаблона. Название роли пишется на английском, описание роли на любом языке -- **make role lint** - проверяет все роли в папке roles/* на наличие ошибок -- **make role test** - позволяет тестировать роль, указанную в molecule/default/converge.yml -сразу на двух контейнерах (RedHat и Ubuntu) -- **make role deploy** - запускает роль в продакшен. Все хосты берет из файла inventory/hosts - -### Работа с файлом переменных - -Все переменные защищены через **Ansible-Vault** и находятся в папке vars/secrets.yml - -Для смены пароля измените его в файле **./vault-password.txt** - -- **make vault create** - создать новый файл с учетом пароля в файле **./vault-password.txt** -- **make vault delete** - удалить файл с переменными -- **make vault edit** - отредактировать файл переменных -- **make vault show** - показать содержимое файла переменных -- **make vault rekey** - сменить пароль шифрования -- **make vault encrypt** - зашифровать файл секретов -- **make vault decrypt** - расшифровать файл секретов - -### Работа с Git - -- **make git push** - запушить изменения. С выбором ветки и вводом коммита. -- **make git pull** - получить изменения из репы -- **make git new** - создание нового брэнча имя cluster-branch_name для IaC подхода. - -### Добавить свой образ контейнера для тестов - -Что бы добавить или изменить докер-образы для тестирования ролей измените файл настроек молекулы -molecule/default/molecule.yml -```yaml - - name: ubuntu-instance - image: "your.docker-registry.com/your-image:latest" - privileged: true - pre_build_image: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:ro ``` -Помните, что образ обязательно должен содержать python не ниже версии 3.12 и systemd для нормального тестирования ролей. \ No newline at end of file +AnsibleTemplate/ +├── molecule/ # Конфигурация Molecule +│ ├── default/ # Основная конфигурация +│ │ ├── create.yml # Создание контейнеров +│ │ ├── converge.yml # Запуск тестов +│ │ ├── destroy.yml # Удаление контейнеров +│ │ ├── site.yml # Основной playbook +│ │ └── molecule.yml # Конфигурация Molecule +│ └── presets/ # Preset конфигурации +│ ├── default.yml # Стандартный preset +│ ├── minimal.yml # Минимальный preset +│ └── examples/ # Примеры preset'ов +├── roles/ # Ansible роли +│ ├── docker/ # Роль установки Docker +│ ├── ping/ # Роль для ping проверок +│ └── deploy.yml # Playbook для развертывания +├── dockerfiles/ # Docker образы +│ └── ansible-controller/ # Ansible контроллер +├── cicd/ # CI/CD конфигурации +├── vault/ # Зашифрованные секреты +├── inventory/ # Инвентори файлы +├── scripts/ # Вспомогательные скрипты +├── docs/ # Документация +├── Makefile # Основные команды +└── requirements.yml # Ansible коллекции +``` + +## 🚀 Быстрый старт + +### 1. Клонирование репозитория + +```bash +git clone +cd AnsibleTemplate +``` + +### 2. Тестирование ролей + +```bash +# Тестирование с default preset (2 хоста) +make role test + +# Тестирование с минимальным preset (1 хост) +make role test minimal + +# Тестирование с кастомным preset +make role test my-custom-preset +``` + +### 3. Проверка синтаксиса + +```bash +# Проверка всех ролей +make role lint + +# Проверка конкретной роли +make role lint docker +make role lint ping +``` + +## 📚 Доступные роли + +### Docker + +Универсальная роль для установки Docker и Docker Compose на различных Linux-дистрибутивах. + +**Поддерживаемые ОС:** +- Debian 9/10/11/12 +- Ubuntu 20.04/22.04/24.04 +- CentOS 7/8/9 +- AlmaLinux 8/9 +- Rocky Linux 8/9 +- RHEL 8/9 + +**Пример использования:** +```yaml +- hosts: all + roles: + - role: docker + vars: + docker_users: + - ansible + - deploy +``` + +**Подробная документация:** [roles/docker/README.md](roles/docker/README.md) + +### Ping + +Роль для выполнения ping проверок подключения к сети. + +**Пример использования:** +```yaml +- hosts: all + roles: + - role: ping + vars: + ping_host: google.com + ping_count: 10 +``` + +**Подробная документация:** [roles/ping/README.md](roles/ping/README.md) + +## 🧪 Preset система + +Preset система позволяет быстро выбрать окружение для тестирования. + +### Доступные preset'ы + +| Preset | Описание | Хосты | +|--------|----------|-------| +| `default` | Стандартный preset | 2 хоста (Ubuntu + CentOS) | +| `minimal` | Минимальный preset | 1 хост (Debian) | +| `mytest` | Кастомный preset | 3 хоста | + +### Создание своего preset + +Создайте файл `molecule/presets/my-preset.yml`: + +```yaml +--- +#description: Мой кастомный preset +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +images: + ubuntu22: "inecs/ansible-lab:ubuntu22-latest" + centos9: "inecs/ansible-lab:centos9-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: web1 + family: ubuntu22 + groups: [web, test] + - name: db1 + family: centos9 + groups: [database, test] +``` + +Используйте preset: + +```bash +make role test my-preset +``` + +## 🔐 Управление секретами + +### Ansible Vault + +```bash +# Создание секретного файла +make vault create + +# Редактирование секретов +make vault edit + +# Просмотр секретов +make vault show + +# Шифрование файла +make vault encrypt + +# Расшифровка файла +make vault decrypt +``` + +## 🚀 Развертывание + +### Тестирование (Docker контейнеры) + +```bash +# Тестирование с разными preset'ами +make role test # default preset +make role test minimal # minimal preset +``` + +### Развертывание на реальные серверы + +```bash +# Развертывание на продакшн +make role deploy +``` + +**Инвентори для продакшн** находится в файле `inventory/hosts.ini`: + +```ini +# inventory/hosts.ini +[web_servers] +web1.example.com ansible_host=192.168.1.10 + +[db_servers] +db1.example.com ansible_host=192.168.1.20 + +[all:vars] +ansible_user=devops +ansible_ssh_private_key_file=~/.ssh/id_rsa +``` + +## 🔧 Основные команды + +### Управление ролями + +```bash +# Просмотр всех ролей +ls -1 roles/ + +# Проверка синтаксиса +make role lint # все роли +make role lint docker # конкретная роль + +# Тестирование +make role test # default preset +make role test minimal # minimal preset +``` + +### Управление секретами + +```bash +# Создание секретов +make vault create + +# Редактирование +make vault edit + +# Просмотр +make vault show +``` + +### Развертывание + +```bash +# Развертывание на продакшн +make role deploy +``` + +## 📖 Документация + +### Основная документация + +- **[docs/getting-started.md](docs/getting-started.md)** - Быстрый старт +- **[docs/molecule-guide.md](docs/molecule-guide.md)** - Руководство по Molecule +- **[docs/creating-roles.md](docs/creating-roles.md)** - Создание ролей +- **[docs/cicd-setup.md](docs/cicd-setup.md)** - Настройка CI/CD + +### Документация по ролям + +- **[roles/docker/README.md](roles/docker/README.md)** - Документация роли Docker +- **[roles/ping/README.md](roles/ping/README.md)** - Документация роли Ping + +### Docker образы + +- **[dockerfiles/README.md](dockerfiles/README.md)** - Информация об образах + +## 🐳 Docker образы + +Проект использует готовые Docker образы для различных ОС: + +- **Ubuntu** 20.04, 22.04, 24.04 +- **Debian** 9, 10, 11, 12 +- **CentOS** 7, 8, 9 +- **AlmaLinux** 8, 9 +- **Rocky Linux** 8, 9 +- **RHEL** 8, 9 + +Все образы с поддержкой systemd для корректной работы служб. + +## 🛠️ Разработка новых ролей + +### Создание структуры роли + +```bash +mkdir -p roles/my-role/{tasks,handlers,templates,files,vars,defaults,meta} +touch roles/my-role/{tasks,handlers,meta}/main.yml +touch roles/my-role/defaults/main.yml +``` + +### Основные файлы + +**tasks/main.yml:** +```yaml +--- +- name: Пример задачи + debug: + msg: "Роль my-role выполнена" +``` + +**defaults/main.yml:** +```yaml +--- +# Переменные по умолчанию +my_role_enabled: true +my_role_version: "1.0.0" +``` + +**README.md:** +```markdown +# Роль My-Role + +Описание роли... +``` + +### Тестирование новой роли + +```bash +# Проверка синтаксиса +make role lint my-role + +# Тестирование +make role test +``` + +## 🏗️ CI/CD + +Проект поддерживает интеграцию с различными CI/CD системами: + +- **GitHub Actions** - готовые workflow'ы +- **Azure DevOps** - pipeline конфигурации +- **Jenkins** - pipeline скрипты +- **GitLab CI** - интеграция + +Подробнее в [docs/cicd-setup.md](docs/cicd-setup.md) + +## 📊 Требования + +- **Docker** - для контейнеризации +- **Docker Compose** - для оркестрации +- **Ansible** >= 2.9 +- **Molecule** >= 3.0 +- **Python** >= 3.6 + +## 🎯 Поддерживаемые ОС + +### Для тестирования (Docker) +- Ubuntu 20.04/22.04/24.04 +- Debian 9/10/11/12 +- CentOS 7/8/9 +- AlmaLinux 8/9 +- Rocky Linux 8/9 +- RHEL 8/9 + +### Для развертывания +- Любые Linux системы с SSH доступом + +## 🤝 Вклад в проект + +1. Fork репозитория +2. Создайте feature branch (`git checkout -b feature/amazing-feature`) +3. Commit изменения (`git commit -m 'Add amazing feature'`) +4. Push в branch (`git push origin feature/amazing-feature`) +5. Создайте Pull Request + +## 📄 Лицензия + +MIT License + +## 📞 Поддержка + +При возникновении проблем: + +1. Проверьте наличие Docker +2. Убедитесь, что все preset файлы существуют +3. Используйте `make role lint` для проверки синтаксиса +4. Проверьте логи тестирования + +## 🎉 Основные достижения + +- ✅ Универсальная preset система +- ✅ Мультиплатформенное тестирование +- ✅ Автоматическая проверка синтаксиса +- ✅ Управление секретами через Ansible Vault +- ✅ Готовые Docker образы для разных ОС +- ✅ CI/CD интеграция + +--- + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg deleted file mode 100644 index d43f8b2..0000000 --- a/ansible.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[defaults] -inventory = inventory/hosts -vault_password_file = vault-password.txt -remote_user = devops -host_key_checking = False -enable_plugins = yaml, ini -roles_path = roles/ -interpreter_python = auto \ No newline at end of file diff --git a/cicd/.gitlab-ci.yml b/cicd/.gitlab-ci.yml new file mode 100644 index 0000000..46c6e74 --- /dev/null +++ b/cicd/.gitlab-ci.yml @@ -0,0 +1,51 @@ +# GitLab CI для AnsibleTemplate +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +stages: + - test + - deploy + +variables: + DOCKER_IMAGE: "quay.io/ansible/creator-ee:latest" + DOCKER_TLS_CERTDIR: "" + ANSIBLE_FORCE_COLOR: "true" + +before_script: + - echo "Установка зависимостей..." + - pip install molecule[docker] ansible-lint + - ansible-galaxy collection install -r requirements.yml + +# Тестирование с Molecule +test: + stage: test + image: $DOCKER_IMAGE + services: + - docker:dind + variables: + DOCKER_TLS_CERTDIR: "" + script: + - echo "Запуск тестов Molecule..." + - cd molecule/universal + - molecule test -s universal + artifacts: + reports: + junit: molecule/universal/.molecule/reports/junit.xml + paths: + - molecule/universal/.molecule/ + expire_in: 1 week + only: + - merge_requests + - main + - develop + +# Деплой (если нужен) +deploy: + stage: deploy + image: $DOCKER_IMAGE + script: + - echo "Деплой не настроен" + - echo "Добавьте логику деплоя в этот job" + when: manual + only: + - main \ No newline at end of file diff --git a/cicd/azure-devops/azure-pipelines.yml b/cicd/azure-devops/azure-pipelines.yml new file mode 100644 index 0000000..37ffdf6 --- /dev/null +++ b/cicd/azure-devops/azure-pipelines.yml @@ -0,0 +1,167 @@ +# Azure DevOps Pipeline для AnsibleLab +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +trigger: +- main +- develop + +pool: + vmImage: 'ubuntu-latest' + +variables: + ANSIBLE_FORCE_COLOR: 'true' + DOCKER_TLS_CERTDIR: '' + +stages: +# Стадия 1: Lint проверка +- stage: Lint + displayName: '🔍 Lint Check' + jobs: + - job: LintJob + displayName: 'Run Lint' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + displayName: 'Use Python 3.11' + + - script: | + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + displayName: 'Install Dependencies' + + - script: | + echo "🔍 Проверка синтаксиса ролей..." + make role lint + displayName: 'Run Ansible Lint' + + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '.ansible-lint' + artifactName: 'lint-results' + condition: always() + +# Стадия 2: Тестирование +- stage: Test + displayName: '🧪 Role Testing' + dependsOn: Lint + condition: succeeded() + jobs: + - job: TestJob + displayName: 'Run Tests' + strategy: + matrix: + minimal: + preset: minimal + default: + preset: default + performance: + preset: performance + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + displayName: 'Use Python 3.11' + + - script: | + sudo apt-get update + sudo apt-get install -y docker.io make + sudo systemctl start docker + sudo usermod -aG docker $USER + displayName: 'Install System Dependencies' + + - script: | + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + displayName: 'Install Python Dependencies' + + - script: | + make docker setup-builder + make docker build + displayName: 'Setup Docker and Build Images' + + - script: | + echo "🧪 Тестирование с preset: $(preset)" + make role test $(preset) + displayName: 'Run Molecule Tests' + env: + PRESET: $(preset) + + - task: PublishTestResults@2 + inputs: + testResultsFiles: 'molecule/default/.molecule/reports/junit.xml' + testRunTitle: 'Molecule Test Results - $(preset)' + condition: always() + + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: 'molecule/default/.molecule' + artifactName: 'test-results-$(preset)' + condition: always() + +# Стадия 3: Деплой (только для main ветки) +- stage: Deploy + displayName: '🚀 Deploy Check' + dependsOn: [Lint, Test] + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + jobs: + - job: DeployJob + displayName: 'Check Deployment' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + displayName: 'Use Python 3.11' + + - script: | + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + displayName: 'Install Dependencies' + + - script: | + mkdir -p inventory + cat > inventory/hosts.ini << EOF + [test_servers] + localhost ansible_connection=local + + [all:vars] + ansible_python_interpreter=python3 + EOF + displayName: 'Create Inventory File' + + - script: | + echo "🚀 Проверка развертывания (dry-run)..." + make role deploy + displayName: 'Run Deployment Check' + + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: 'deployment.log' + artifactName: 'deployment-results' + condition: always() + +# Уведомления +- stage: Notify + displayName: '📢 Notifications' + dependsOn: [Lint, Test, Deploy] + condition: always() + jobs: + - job: NotifyJob + displayName: 'Send Notifications' + steps: + - script: | + echo "🔍 Lint: $(Lint.result)" + echo "🧪 Test: $(Test.result)" + echo "🚀 Deploy: $(Deploy.result)" + + if [ "$(Lint.result)" = "Succeeded" ] && [ "$(Test.result)" = "Succeeded" ]; then + echo "✅ Все проверки пройдены успешно!" + else + echo "❌ Проверки не пройдены!" + exit 1 + fi + displayName: 'Check Results and Notify' diff --git a/cicd/github/workflows.yml b/cicd/github/workflows.yml new file mode 100644 index 0000000..ee05852 --- /dev/null +++ b/cicd/github/workflows.yml @@ -0,0 +1,172 @@ +# GitHub Actions Workflow для AnsibleLab +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +name: AnsibleLab CI/CD Pipeline + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + # Стадия 1: Lint проверка + lint: + name: 🔍 Lint Check + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + + - name: Run Ansible Lint + run: | + echo "🔍 Проверка синтаксиса ролей..." + make role lint + + - name: Upload lint results + uses: actions/upload-artifact@v3 + if: always() + with: + name: lint-results + path: | + .ansible-lint + lint-report.txt + + # Стадия 2: Тестирование + test: + name: 🧪 Role Testing + runs-on: ubuntu-latest + needs: lint + + strategy: + matrix: + preset: [minimal, default, performance] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y docker.io make + sudo systemctl start docker + sudo usermod -aG docker $USER + + - name: Install Python dependencies + run: | + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + + - name: Setup Docker builder + run: | + make docker setup-builder + + - name: Build Docker images + run: | + make docker build + + - name: Run Molecule tests + run: | + echo "🧪 Тестирование с preset: ${{ matrix.preset }}" + make role test ${{ matrix.preset }} + + - name: Upload test results + uses: actions/upload-artifact@v3 + if: always() + with: + name: test-results-${{ matrix.preset }} + path: | + molecule/default/.molecule/ + test-report-${{ matrix.preset }}.txt + + # Стадия 3: Деплой (только для main ветки) + deploy: + name: 🚀 Deploy Check + runs-on: ubuntu-latest + needs: [lint, test] + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + + - name: Create inventory file + run: | + mkdir -p inventory + cat > inventory/hosts.ini << EOF + [test_servers] + localhost ansible_connection=local + + [all:vars] + ansible_python_interpreter=python3 + EOF + + - name: Run deployment check + run: | + echo "🚀 Проверка развертывания (dry-run)..." + make role deploy + + - name: Upload deployment results + uses: actions/upload-artifact@v3 + if: always() + with: + name: deployment-results + path: | + deployment.log + deployment-report.txt + + # Уведомления + notify: + name: 📢 Notifications + runs-on: ubuntu-latest + needs: [lint, test, deploy] + if: always() + + steps: + - name: Notify on success + if: needs.lint.result == 'success' && needs.test.result == 'success' + run: | + echo "✅ Все проверки пройдены успешно!" + echo "🔍 Lint: ${{ needs.lint.result }}" + echo "🧪 Test: ${{ needs.test.result }}" + echo "🚀 Deploy: ${{ needs.deploy.result }}" + + - name: Notify on failure + if: needs.lint.result == 'failure' || needs.test.result == 'failure' + run: | + echo "❌ Проверки не пройдены!" + echo "🔍 Lint: ${{ needs.lint.result }}" + echo "🧪 Test: ${{ needs.test.result }}" + echo "🚀 Deploy: ${{ needs.deploy.result }}" + exit 1 diff --git a/cicd/gitlab/.gitlab-ci.yml b/cicd/gitlab/.gitlab-ci.yml new file mode 100644 index 0000000..36e80cb --- /dev/null +++ b/cicd/gitlab/.gitlab-ci.yml @@ -0,0 +1,153 @@ +# GitLab CI Pipeline для AnsibleLab +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +stages: + - lint + - test + - deploy + +variables: + ANSIBLE_FORCE_COLOR: "true" + DOCKER_TLS_CERTDIR: "" + +# Стадия 1: Lint проверка +lint: + stage: lint + image: python:3.11 + before_script: + - pip install --upgrade pip + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - echo "🔍 Проверка синтаксиса ролей..." + - make role lint + artifacts: + reports: + junit: .ansible-lint + paths: + - .ansible-lint + expire_in: 1 week + +# Стадия 2: Тестирование +test_minimal: + stage: test + image: docker:latest + services: + - docker:dind + variables: + DOCKER_TLS_CERTDIR: "" + before_script: + - apk add --no-cache make python3 py3-pip + - pip install --upgrade pip + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + - make docker setup-builder + - make docker build + script: + - echo "🧪 Тестирование с preset: minimal" + - make role test minimal + artifacts: + reports: + junit: molecule/default/.molecule/reports/junit.xml + paths: + - molecule/default/.molecule/ + expire_in: 1 week + +test_default: + stage: test + image: docker:latest + services: + - docker:dind + variables: + DOCKER_TLS_CERTDIR: "" + before_script: + - apk add --no-cache make python3 py3-pip + - pip install --upgrade pip + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + - make docker setup-builder + - make docker build + script: + - echo "🧪 Тестирование с preset: default" + - make role test default + artifacts: + reports: + junit: molecule/default/.molecule/reports/junit.xml + paths: + - molecule/default/.molecule/ + expire_in: 1 week + +test_performance: + stage: test + image: docker:latest + services: + - docker:dind + variables: + DOCKER_TLS_CERTDIR: "" + before_script: + - apk add --no-cache make python3 py3-pip + - pip install --upgrade pip + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + - make docker setup-builder + - make docker build + script: + - echo "🧪 Тестирование с preset: performance" + - make role test performance + artifacts: + reports: + junit: molecule/default/.molecule/reports/junit.xml + paths: + - molecule/default/.molecule/ + expire_in: 1 week + +# Стадия 3: Деплой (только для main ветки) +deploy: + stage: deploy + image: python:3.11 + only: + - main + before_script: + - pip install --upgrade pip + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - echo "🚀 Проверка развертывания (dry-run)..." + - mkdir -p inventory + - | + cat > inventory/hosts.ini << EOF + [test_servers] + localhost ansible_connection=local + + [all:vars] + ansible_python_interpreter=python3 + EOF + - make role deploy + artifacts: + paths: + - deployment.log + expire_in: 1 week + +# Уведомления +notify_success: + stage: deploy + image: python:3.11 + only: + - main + when: on_success + script: + - echo "✅ Все проверки пройдены успешно!" + - echo "🔍 Lint: Success" + - echo "🧪 Test: Success" + - echo "🚀 Deploy: Success" + +notify_failure: + stage: deploy + image: python:3.11 + when: on_failure + script: + - echo "❌ Проверки не пройдены!" + - echo "🔍 Lint: Failed" + - echo "🧪 Test: Failed" + - echo "🚀 Deploy: Failed" diff --git a/gitlab/config.json b/cicd/gitlab/config.json similarity index 100% rename from gitlab/config.json rename to cicd/gitlab/config.json diff --git a/gitlab/docker-compose.yaml b/cicd/gitlab/docker-compose.yaml similarity index 100% rename from gitlab/docker-compose.yaml rename to cicd/gitlab/docker-compose.yaml diff --git a/gitlab/runner/config.toml b/cicd/gitlab/runner/config.toml similarity index 100% rename from gitlab/runner/config.toml rename to cicd/gitlab/runner/config.toml diff --git a/cicd/jenkins/Jenkinsfile b/cicd/jenkins/Jenkinsfile new file mode 100644 index 0000000..0a39be7 --- /dev/null +++ b/cicd/jenkins/Jenkinsfile @@ -0,0 +1,138 @@ +// Jenkins Pipeline для AnsibleLab +// Автор: Сергей Антропов +// Сайт: https://devops.org.ru + +pipeline { + agent any + + environment { + ANSIBLE_FORCE_COLOR = 'true' + DOCKER_TLS_CERTDIR = '' + } + + stages { + stage('Checkout') { + steps { + checkout scm + } + } + + // Стадия 1: Lint проверка + stage('🔍 Lint Check') { + steps { + sh ''' + echo "🔍 Проверка синтаксиса ролей..." + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + make role lint + ''' + } + post { + always { + archiveArtifacts artifacts: '.ansible-lint', allowEmptyArchive: true + } + } + } + + // Стадия 2: Тестирование + stage('🧪 Role Testing') { + parallel { + stage('Test Minimal') { + steps { + sh ''' + echo "🧪 Тестирование с preset: minimal" + sudo apt-get update + sudo apt-get install -y docker.io make + sudo systemctl start docker + sudo usermod -aG docker $USER + make docker setup-builder + make docker build + make role test minimal + ''' + } + } + stage('Test Default') { + steps { + sh ''' + echo "🧪 Тестирование с preset: default" + sudo apt-get update + sudo apt-get install -y docker.io make + sudo systemctl start docker + sudo usermod -aG docker $USER + make docker setup-builder + make docker build + make role test default + ''' + } + } + stage('Test Performance') { + steps { + sh ''' + echo "🧪 Тестирование с preset: performance" + sudo apt-get update + sudo apt-get install -y docker.io make + sudo systemctl start docker + sudo usermod -aG docker $USER + make docker setup-builder + make docker build + make role test performance + ''' + } + } + } + } + + // Стадия 3: Деплой (только для main ветки) + stage('🚀 Deploy Check') { + when { + branch 'main' + } + steps { + sh ''' + echo "🚀 Проверка развертывания (dry-run)..." + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + + mkdir -p inventory + cat > inventory/hosts.ini << EOF + [test_servers] + localhost ansible_connection=local + + [all:vars] + ansible_python_interpreter=python3 + EOF + + make role deploy + ''' + } + post { + always { + archiveArtifacts artifacts: 'deployment.log', allowEmptyArchive: true + } + } + } + } + + post { + always { + archiveArtifacts artifacts: 'molecule/default/.molecule/**/*', allowEmptyArchive: true + publishTestResults testResultsPattern: 'molecule/default/.molecule/reports/junit.xml' + } + + success { + echo '✅ Все проверки пройдены успешно!' + echo '🔍 Lint: Success' + echo '🧪 Test: Success' + echo '🚀 Deploy: Success' + } + + failure { + echo '❌ Проверки не пройдены!' + echo '🔍 Lint: Failed' + echo '🧪 Test: Failed' + echo '🚀 Deploy: Failed' + } + } +} diff --git a/default/deploy.yaml b/default/deploy.yaml deleted file mode 100644 index 61ab8b8..0000000 --- a/default/deploy.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -- name: Deploy roles - hosts: all - become: true - become_user: root - become_method: ansible.builtin.sudo - gather_facts: true - vars_files: - - ../../vars/secrets.yml - roles: \ No newline at end of file diff --git a/default/handlers/.gitkeep b/default/handlers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/default/meta/.gitkeep b/default/meta/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/default/tasks/debian/main.yaml b/default/tasks/debian/main.yaml deleted file mode 100644 index 4c32e03..0000000 --- a/default/tasks/debian/main.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- name: Пример таски - debug: - msg: "Привет! Я запустился на Debian/Ubuntu!" diff --git a/default/tasks/main.yaml b/default/tasks/main.yaml deleted file mode 100644 index 2b9ddee..0000000 --- a/default/tasks/main.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: "Определяем ОС" - set_fact: - os_family: "{{ ansible_facts['os_family'] }}" - -- name: "Подключаем таски для RedHat совместимых" - include_tasks: "redhat/main.yaml" - when: os_family == "RedHat" - -- name: "Подключаем таски для Debian/Ubuntu совместимых" - include_tasks: "debian/main.yaml" - when: os_family == "Debian" diff --git a/default/tasks/redhat/main.yaml b/default/tasks/redhat/main.yaml deleted file mode 100644 index 64e5c36..0000000 --- a/default/tasks/redhat/main.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- name: Пример таски - debug: - msg: "Привет! Я запустился на RedHat/CentOS/Fedora!" diff --git a/default/templates/.gitkeep b/default/templates/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/default/tests/.gitkeep b/default/tests/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index e920595..0000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,12 +0,0 @@ -services: - ansible: - image: inecs/ansible:latest - container_name: ansible - volumes: - - .:/ansible - - /var/run/docker.sock:/var/run/docker.sock - environment: - - ANSIBLE_VAULT_PASSWORD_FILE=./vault-password.txt - tty: true - privileged: true - working_dir: /ansible \ No newline at end of file diff --git a/dockerfiles/README.md b/dockerfiles/README.md new file mode 100644 index 0000000..839bab8 --- /dev/null +++ b/dockerfiles/README.md @@ -0,0 +1,682 @@ +# Docker образы для универсальной системы тестирования AnsibleLab + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru +**Версия:** 2.0.0 + +## 🐳 Обзор + +Эта директория содержит Docker образы для различных операционных систем и компонентов, используемых в универсальной системе тестирования Ansible ролей. Все образы поддерживают multi-arch сборку (amd64, arm64, riscv64, ppc64le, s390x, 386, arm/v7, arm/v6) и автоматически публикуются в Docker Hub. + +## 📁 Структура + +``` +dockerfiles/ +├── ansible-controller/ # Ansible контроллер с предустановленными коллекциями +├── alt-linux/ # ALT Linux с systemd +├── astra-linux/ # Astra Linux с systemd +├── redos/ # RED OS с systemd +├── rhel/ # Red Hat Enterprise Linux с systemd +├── centos/ # CentOS Stream с systemd +├── alma/ # AlmaLinux с systemd +├── rocky/ # Rocky Linux с systemd +├── ubuntu/ # Ubuntu с systemd +├── debian/ # Debian с systemd +└── README.md # Документация +``` + +## 🚀 Доступные образы + +### 1. ansible-controller + +**Базовый образ:** `ubuntu:22.04` +**Тег:** `inecs/ansible-lab:ansible-controller-latest` +**Описание:** Ansible контроллер с предустановленными коллекциями и инструментами + +#### Компоненты: +- **Ansible Core** с последними коллекциями +- **Docker CLI** для работы с контейнерами +- **kubectl** для управления Kubernetes +- **Helm** для управления пакетами Kubernetes +- **Kind** для локального Kubernetes +- **yq** для работы с YAML +- **jq** для работы с JSON + +#### Предустановленные коллекции: +```yaml +collections: + - name: community.docker + version: ">=3.0.0" + - name: community.general + version: ">=7.0.0" + - name: ansible.posix + version: ">=1.5.4" +``` + +#### Предустановленные роли: +- `geerlingguy.docker` - управление Docker +- `geerlingguy.kubernetes` - управление Kubernetes + +#### Переменные окружения: +```bash +DOCKER_HOST=unix:///var/run/docker.sock +ANSIBLE_FORCE_COLOR=1 +ANSIBLE_STDOUT_CALLBACK=yaml +ANSIBLE_CALLBACKS_ENABLED=profile_tasks +``` + +#### Использование: +```bash +# Запуск контроллера +docker run -it --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v $(pwd):/workspace \ + -w /workspace \ + inecs/ansible-lab:ansible-controller-latest + +# Выполнение Ansible команд +docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v $(pwd):/workspace \ + -w /workspace \ + inecs/ansible-lab:ansible-controller-latest \ + ansible-playbook site.yml +``` + +### 2. ubuntu + +**Базовый образ:** `ubuntu:22.04` +**Тег:** `inecs/ansible-lab:ubuntu-latest` +**Описание:** Ubuntu 22.04 LTS с systemd и Docker + +#### Компоненты: +- **Ubuntu 22.04 LTS** (Jammy Jellyfish) +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano htop tree jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск Ubuntu контейнера +docker run -d --privileged \ + --name ubuntu-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:ubuntu-latest + +# Подключение к контейнеру +docker exec -it ubuntu-test bash +``` + +### 3. debian + +**Базовый образ:** `debian:bookworm` +**Тег:** `inecs/ansible-lab:debian-latest` +**Описание:** Debian 12 (Bookworm) с systemd и Docker + +#### Компоненты: +- **Debian 12** (Bookworm) +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano htop tree jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск Debian контейнера +docker run -d --privileged \ + --name debian-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:debian-latest +``` + +### 4. rhel + +**Базовый образ:** `registry.access.redhat.com/ubi8/ubi` +**Тег:** `inecs/ansible-lab:rhel-latest` +**Описание:** Red Hat Enterprise Linux 8 с systemd и Docker + +#### Компоненты: +- **RHEL 8** (Universal Base Image) +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск RHEL контейнера +docker run -d --privileged \ + --name rhel-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:rhel-latest +``` + +### 5. centos + +**Базовый образ:** `quay.io/centos/centos:stream9` +**Тег:** `inecs/ansible-lab:centos-latest` +**Описание:** CentOS Stream 9 с systemd и Docker + +#### Компоненты: +- **CentOS Stream 9** +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск CentOS контейнера +docker run -d --privileged \ + --name centos-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:centos-latest +``` + +### 6. alma + +**Базовый образ:** `almalinux:8` +**Тег:** `inecs/ansible-lab:alma-latest` +**Описание:** AlmaLinux 8 с systemd и Docker + +#### Компоненты: +- **AlmaLinux 8** +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск AlmaLinux контейнера +docker run -d --privileged \ + --name alma-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:alma-latest +``` + +### 7. rocky + +**Базовый образ:** `rockylinux:8` +**Тег:** `inecs/ansible-lab:rocky-latest` +**Описание:** Rocky Linux 8 с systemd и Docker + +#### Компоненты: +- **Rocky Linux 8** +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск Rocky Linux контейнера +docker run -d --privileged \ + --name rocky-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:rocky-latest +``` + +### 8. alt-linux + +**Базовый образ:** `altlinux/p9` +**Тег:** `inecs/ansible-lab:alt-linux-latest` +**Описание:** ALT Linux 9 с systemd и Docker + +#### Компоненты: +- **ALT Linux 9** (Platform 9) +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano htop tree jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск ALT Linux контейнера +docker run -d --privileged \ + --name alt-linux-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:alt-linux-latest +``` + +### 9. astra-linux + +**Базовый образ:** `astralinux/astra-1.7` +**Тег:** `inecs/ansible-lab:astra-linux-latest` +**Описание:** Astra Linux 1.7 с systemd и Docker + +#### Компоненты: +- **Astra Linux 1.7** +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano htop tree jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск Astra Linux контейнера +docker run -d --privileged \ + --name astra-linux-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:astra-linux-latest +``` + +### 10. redos + +**Базовый образ:** `redos/redos:9` +**Тег:** `inecs/ansible-lab:redos-latest` +**Описание:** RED OS 9 с systemd и Docker + +#### Компоненты: +- **RED OS 9** +- **systemd** для управления сервисами +- **Docker CE** с Docker Compose +- **Python 3** с pip +- **Пользователь ansible** с sudo правами + +#### Установленные пакеты: +```bash +systemd systemd-sysv dbus +curl wget git vim nano htop tree jq +python3 python3-pip +docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +#### Настройки systemd: +```bash +systemctl set-default multi-user.target +``` + +#### Использование: +```bash +# Запуск RED OS контейнера +docker run -d --privileged \ + --name redos-test \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + --tmpfs /run --tmpfs /run/lock \ + --cap-add SYS_ADMIN \ + inecs/ansible-lab:redos-latest +``` + +## 🔧 Управление образами + +### Сборка всех образов + +```bash +# Сборка всех образов (multi-arch) +make docker build + +# Сборка конкретного образа +make docker build-image IMAGE=ubuntu + +# Полная пересборка с очисткой кеша +make docker rebuild +``` + +### Отправка в Docker Hub + +```bash +# Отправка всех образов +make docker push + +# Загрузка всех образов +make docker pull +``` + +### Очистка образов + +```bash +# Очистка локальных образов +make docker clean + +# Полная очистка Docker +make docker purge +``` + +### Информация об образах + +```bash +# Информация о собранных образах +make docker info + +# Диагностика проблем +make docker diagnose +``` + +## 🏗️ Multi-Arch поддержка + +### Поддерживаемые архитектуры + +| Архитектура | Описание | Статус | +|-------------|----------|--------| +| `linux/amd64` | Intel/AMD 64-bit | ✅ Поддерживается | +| `linux/arm64` | ARM 64-bit | ✅ Поддерживается | +| `linux/riscv64` | RISC-V 64-bit | ✅ Поддерживается | +| `linux/ppc64le` | PowerPC 64-bit LE | ✅ Поддерживается | +| `linux/s390x` | IBM Z 64-bit | ✅ Поддерживается | +| `linux/386` | Intel 32-bit | ✅ Поддерживается | +| `linux/arm/v7` | ARM 32-bit v7 | ✅ Поддерживается | +| `linux/arm/v6` | ARM 32-bit v6 | ✅ Поддерживается | + +### Настройка builder'а + +```bash +# Настройка multi-arch builder +make docker setup-builder + +# Проверка builder'а +make docker diagnose + +# Сброс builder'а при проблемах +make docker reset-builder +``` + +## 🚀 Использование в preset'ах + +### Пример preset'а с собственными образами + +```yaml +# molecule/presets/custom-images.yml +--- +#description: Preset с собственными образами AnsibleLab +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# Собственные образы +images: + ubuntu: "inecs/ansible-lab:ubuntu-latest" + debian: "inecs/ansible-lab:debian-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" + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-latest" + redos: "inecs/ansible-lab:redos-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: ubuntu1 + family: ubuntu + groups: [web, frontend] + - name: debian1 + family: debian + groups: [web, frontend] + - name: rhel1 + family: rhel + groups: [database, backend] + - name: centos1 + family: centos + groups: [database, backend] + - name: alma1 + family: alma + groups: [monitoring] + - name: rocky1 + family: rocky + groups: [monitoring] + - name: alt1 + family: alt + groups: [security] + - name: astra1 + family: astra + groups: [security] + - name: redos1 + family: redos + groups: [security] +``` + +### Тестирование с собственными образами + +```bash +# Тестирование с собственными образами +make custom-images test full + +# Проверка наличия образов +make custom-images check + +# Сборка всех образов +make custom-images build +``` + +## 📊 Мониторинг и диагностика + +### Проверка образов + +```bash +# Проверка размера образов +docker images | grep inecs/ansible-lab + +# Проверка архитектур +docker manifest inspect inecs/ansible-lab:ubuntu-latest + +# Проверка содержимого образа +docker run --rm inecs/ansible-lab:ubuntu-latest cat /etc/os-release +``` + +### Логи сборки + +```bash +# Подробные логи сборки +make docker build 2>&1 | tee build.log + +# Логи конкретного образа +make docker build-image IMAGE=ubuntu 2>&1 | tee ubuntu-build.log +``` + +## 🐛 Troubleshooting + +### Проблемы с сборкой + +1. **Builder не создается:** + ```bash + make docker diagnose + make docker reset-builder + ``` + +2. **Образы не собираются:** + ```bash + make docker clean + make docker setup-builder + make docker build + ``` + +3. **Проблемы с multi-arch:** + ```bash + make docker clean-builder + make docker setup-builder + ``` + +### Проблемы с образами + +1. **Образы не запускаются:** + ```bash + # Проверка systemd + docker run --rm --privileged inecs/ansible-lab:ubuntu-latest systemctl status + + # Проверка Docker + docker run --rm --privileged inecs/ansible-lab:ubuntu-latest docker --version + ``` + +2. **Проблемы с правами:** + ```bash + # Проверка пользователя ansible + docker run --rm inecs/ansible-lab:ubuntu-latest id ansible + + # Проверка sudo прав + docker run --rm inecs/ansible-lab:ubuntu-latest sudo -l + ``` + +## 📈 Производительность + +### Оптимизация сборки + +```bash +# Использование кеша Docker +make docker build + +# Очистка кеша при проблемах +make docker rebuild +``` + +### Оптимизация образов + +- **Многоэтапная сборка** для уменьшения размера +- **Кеширование слоев** для ускорения сборки +- **Минимальные базовые образы** для безопасности +- **Оптимизированные зависимости** для производительности + +## 🔒 Безопасность + +### Безопасность образов + +- **Регулярные обновления** базовых образов +- **Минимальные права** для пользователей +- **Сканирование уязвимостей** в CI/CD +- **Подписанные образы** для целостности + +### Лучшие практики + +1. **Используйте конкретные теги** вместо `latest` +2. **Регулярно обновляйте** базовые образы +3. **Сканируйте образы** на уязвимости +4. **Используйте multi-arch** для совместимости + +## 📚 Дополнительные ресурсы + +- [Docker Multi-Arch Build](https://docs.docker.com/buildx/working-with-buildx/) +- [Ansible Collections](https://docs.ansible.com/ansible/latest/collections_guide/index.html) +- [Molecule Documentation](https://molecule.readthedocs.io/) +- [Systemd in Containers](https://systemd.io/CONTAINER_INTERFACE/) + +--- + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru \ No newline at end of file diff --git a/dockerfiles/alma/Dockerfile b/dockerfiles/alma/Dockerfile new file mode 100644 index 0000000..d914d89 --- /dev/null +++ b/dockerfiles/alma/Dockerfile @@ -0,0 +1,52 @@ +# AlmaLinux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# https://hub.docker.com/_/almalinux + +FROM almalinux:8 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python39 \ + python39-pip \ + sudo \ + && dnf clean all + +# Создаем symlink для python3 -> python3.9 +RUN ln -sf /usr/bin/python3.9 /usr/bin/python3 + +# Устанавливаем yq +# RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ +# && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +# RUN dnf install -y dnf-plugins-core \ +# && dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo \ +# && dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] \ No newline at end of file diff --git a/dockerfiles/alt-linux/Dockerfile b/dockerfiles/alt-linux/Dockerfile new file mode 100644 index 0000000..7c05415 --- /dev/null +++ b/dockerfiles/alt-linux/Dockerfile @@ -0,0 +1,52 @@ +# ALT Linux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# https://hub.docker.com/_/alt/tags + +FROM alt:p9 + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + sudo \ + && apt-get clean + +# Устанавливаем pip для Python 3.7 +RUN curl -sS https://bootstrap.pypa.io/pip/3.7/get-pip.py | python3 + +# Устанавливаем yq +# RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ +# && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker вручную для ALT Linux +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/ansible-controller/Dockerfile b/dockerfiles/ansible-controller/Dockerfile new file mode 100644 index 0000000..71d3a77 --- /dev/null +++ b/dockerfiles/ansible-controller/Dockerfile @@ -0,0 +1,93 @@ +# Ansible Controller с предустановленными коллекциями +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM ubuntu:22.04 + +# Обновляем систему +RUN apt-get update && apt-get upgrade -y && apt-get clean + +# Устанавливаем Python и Ansible +RUN apt-get install -y \ + python3 \ + python3-pip \ + python3-venv \ + python3-dev \ + build-essential \ + && apt-get clean + +# Устанавливаем Ansible, ansible-lint и passlib для хеширования паролей +RUN pip3 install ansible ansible-core ansible-lint passlib + +# Устанавливаем дополнительные пакеты +RUN apt-get install -y \ + curl \ + wget \ + git \ + vim \ + nano \ + htop \ + tree \ + jq \ + && apt-get clean + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker CLI +RUN apt-get install -y docker.io docker-compose + +# Устанавливаем kubectl +RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \ + && chmod +x kubectl \ + && mv kubectl /usr/local/bin/ + +# Устанавливаем Helm +RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + +# Устанавливаем Kind +RUN curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64 \ + && chmod +x ./kind \ + && mv ./kind /usr/local/bin/ + +## Устанавливаем Istio CLI +#RUN curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.1 sh - \ +# && mv istio-1.22.1/bin/istioctl /usr/local/bin/ \ +# && rm -rf istio-1.22.1 + +# Копируем файлы зависимостей +COPY requirements.yml /tmp/requirements.yml +COPY requirements.txt /tmp/requirements.txt + +# Устанавливаем Python зависимости +RUN pip3 install -r /tmp/requirements.txt + +# Устанавливаем Ansible коллекции +RUN ansible-galaxy collection install -r /tmp/requirements.yml + +# Создаем пользователя ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Создаем рабочую директорию +WORKDIR /ansible + +# Устанавливаем права +RUN chown -R ansible:ansible /ansible + +# Переключаемся на пользователя ansible +USER ansible + +# Устанавливаем дополнительные роли +RUN ansible-galaxy install geerlingguy.docker \ + && ansible-galaxy install geerlingguy.kubernetes + +# Настройки для работы с Docker +ENV DOCKER_HOST=unix:///var/run/docker.sock +ENV ANSIBLE_FORCE_COLOR=1 +ENV ANSIBLE_STDOUT_CALLBACK=yaml +ENV ANSIBLE_CALLBACKS_ENABLED=profile_tasks + +# Команда по умолчанию +CMD ["sleep", "infinity"] diff --git a/dockerfiles/ansible-controller/docker-compose.yml b/dockerfiles/ansible-controller/docker-compose.yml new file mode 100644 index 0000000..11b3d16 --- /dev/null +++ b/dockerfiles/ansible-controller/docker-compose.yml @@ -0,0 +1,22 @@ +version: "3.9" + +services: + ansible-controller: + image: inecs/ansible-lab:ansible-controller-latest + container_name: ansible-controller + privileged: true + command: sleep infinity + environment: + DOCKER_HOST: unix:///var/run/docker.sock + ANSIBLE_VAULT_PASSWORD_FILE: /ansible/vault/.vault + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - .:/ansible + working_dir: /ansible + networks: + - labnet + +networks: + labnet: + external: true + diff --git a/dockerfiles/ansible-controller/requirements.txt b/dockerfiles/ansible-controller/requirements.txt new file mode 100644 index 0000000..983ba28 --- /dev/null +++ b/dockerfiles/ansible-controller/requirements.txt @@ -0,0 +1,9 @@ +# Python зависимости для Ansible Controller +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Основные зависимости для работы с паролями +passlib>=1.7.4 + +# Дополнительные зависимости для безопасности +bcrypt>=4.0.1 diff --git a/dockerfiles/ansible-controller/requirements.yml b/dockerfiles/ansible-controller/requirements.yml new file mode 100644 index 0000000..037030c --- /dev/null +++ b/dockerfiles/ansible-controller/requirements.yml @@ -0,0 +1,9 @@ +--- +# Ansible Collections for Molecule Universal +collections: + - name: community.docker + version: ">=3.0.0" + - name: community.general + version: ">=7.0.0" + - name: ansible.posix + version: ">=1.5.4" \ No newline at end of file diff --git a/dockerfiles/astra-linux/Dockerfile b/dockerfiles/astra-linux/Dockerfile new file mode 100644 index 0000000..3ab4a1f --- /dev/null +++ b/dockerfiles/astra-linux/Dockerfile @@ -0,0 +1,70 @@ +# Astra Linux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# https://registry.astralinux.ru/browse/library/ +# ВАЖНО: Базовый образ поддерживает только linux/amd64 +# Для сборки используйте: docker buildx build --platform linux/amd64 + +FROM registry.astralinux.ru/library/astra/ubi17:1.7.6.uu2 + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем yq (автоопределение архитектуры) +# RUN ARCH=$(dpkg --print-architecture | sed 's/amd64/amd64/; s/arm64/arm64/; s/aarch64/arm64/') && \ +# wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${ARCH}" && \ +# chmod +x /usr/local/bin/yq + +# Устанавливаем Docker вручную для AstraLinux (автоопределение архитектуры) +# RUN ARCH=$(dpkg --print-architecture) && \ +# apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release && \ +# mkdir -p /usr/share/keyrings && \ +# curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && \ +# echo "deb [arch=${ARCH} signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian buster stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \ +# apt-get update && \ +# apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin && \ +# apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Отключаем Parsec для работы в контейнере +RUN if [ -f /etc/parsec/parsec.conf ]; then \ + sed -i 's/enabled=1/enabled=0/' /etc/parsec/parsec.conf || true; \ + fi && \ + if [ -f /lib/modules/$(uname -r)/parsec.ko ]; then \ + mv /lib/modules/$(uname -r)/parsec.ko /lib/modules/$(uname -r)/parsec.ko.disabled || true; \ + fi && \ + systemctl disable parsec 2>/dev/null || true + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/centos7/Dockerfile b/dockerfiles/centos7/Dockerfile new file mode 100644 index 0000000..ebb8f56 --- /dev/null +++ b/dockerfiles/centos7/Dockerfile @@ -0,0 +1,50 @@ +# CentOS 7 с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM centos:7 + +# Настраиваем vault репозитории для CentOS 7 (так как основные репозитории больше не поддерживаются) +RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*.repo && \ + sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*.repo + +# Обновляем систему +RUN yum update -y && yum upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN yum install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && yum clean all + +# Устанавливаем yq +# RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ +# && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +# RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/centos8/Dockerfile b/dockerfiles/centos8/Dockerfile new file mode 100644 index 0000000..b2851d2 --- /dev/null +++ b/dockerfiles/centos8/Dockerfile @@ -0,0 +1,50 @@ +# CentOS 8 с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM quay.io/centos/centos:8 + +# Настраиваем vault репозитории для CentOS 8 (так как основные репозитории больше не поддерживаются) +RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*.repo && \ + sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*.repo + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y --allowerasing \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && dnf clean all + +# Устанавливаем yq +# RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ +# && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +# RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/centos9/Dockerfile b/dockerfiles/centos9/Dockerfile new file mode 100644 index 0000000..41534a7 --- /dev/null +++ b/dockerfiles/centos9/Dockerfile @@ -0,0 +1,46 @@ +# CentOS с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM quay.io/centos/centos:stream9 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y --allowerasing \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && dnf clean all + +# Устанавливаем yq +# RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ +# && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +# RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/debian10/Dockerfile b/dockerfiles/debian10/Dockerfile new file mode 100644 index 0000000..e12d4b3 --- /dev/null +++ b/dockerfiles/debian10/Dockerfile @@ -0,0 +1,62 @@ +# Debian 10 Buster с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM debian:10 + +# Устанавливаем переменные окружения для автоматического ответа на запросы +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + +# Настраиваем archive репозитории для Debian 10 (так как основные репозитории больше не поддерживаются) +RUN sed -i 's|http://deb.debian.org/debian|http://archive.debian.org/debian|g' /etc/apt/sources.list && \ + sed -i 's|http://security.debian.org/debian-security|http://archive.debian.org/debian-security|g' /etc/apt/sources.list && \ + echo "deb http://archive.debian.org/debian buster main" > /etc/apt/sources.list && \ + echo "deb http://archive.debian.org/debian-security buster/updates main" >> /etc/apt/sources.list + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем Docker вручную для Debian +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release \ +# && mkdir -p /usr/share/keyrings \ +# && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ +# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bookworm stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ +# && apt-get update \ +# && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/debian11/Dockerfile b/dockerfiles/debian11/Dockerfile new file mode 100644 index 0000000..269889a --- /dev/null +++ b/dockerfiles/debian11/Dockerfile @@ -0,0 +1,56 @@ +# Debian 11 Bullseye с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM debian:11 + +# Устанавливаем переменные окружения для автоматического ответа на запросы +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем Docker вручную для Debian +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release \ +# && mkdir -p /usr/share/keyrings \ +# && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ +# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bookworm stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ +# && apt-get update \ +# && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/debian12/Dockerfile b/dockerfiles/debian12/Dockerfile new file mode 100644 index 0000000..5c05734 --- /dev/null +++ b/dockerfiles/debian12/Dockerfile @@ -0,0 +1,56 @@ +# Debian 12 Bookworm с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM debian:bookworm + +# Устанавливаем переменные окружения для автоматического ответа на запросы +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем Docker вручную для Debian +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release \ +# && mkdir -p /usr/share/keyrings \ +# && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ +# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bookworm stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ +# && apt-get update \ +# && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/debian9/Dockerfile b/dockerfiles/debian9/Dockerfile new file mode 100644 index 0000000..3db3a12 --- /dev/null +++ b/dockerfiles/debian9/Dockerfile @@ -0,0 +1,62 @@ +# Debian 9 Stretch с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM debian:9 + +# Устанавливаем переменные окружения для автоматического ответа на запросы +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + +# Настраиваем archive репозитории для Debian 9 (так как основные репозитории больше не поддерживаются) +RUN sed -i 's|http://deb.debian.org/debian|http://archive.debian.org/debian|g' /etc/apt/sources.list && \ + sed -i 's|http://security.debian.org/debian-security|http://archive.debian.org/debian-security|g' /etc/apt/sources.list && \ + echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list && \ + echo "deb http://archive.debian.org/debian-security stretch/updates main" >> /etc/apt/sources.list + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем Docker вручную для Debian +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release \ +# && mkdir -p /usr/share/keyrings \ +# && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ +# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bookworm stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ +# && apt-get update \ +# && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/redos/Dockerfile b/dockerfiles/redos/Dockerfile new file mode 100644 index 0000000..cc4af4a --- /dev/null +++ b/dockerfiles/redos/Dockerfile @@ -0,0 +1,54 @@ +# RED OS с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# https://registry.red-soft.ru/ubi7/ubi/tags +# docker search registry.red-soft.ru/ubi7/ubi +# ВАЖНО: Базовый образ поддерживает только linux/amd64 +# Для сборки используйте: docker buildx build --platform linux/amd64 + +FROM registry.red-soft.ru/ubi7/ubi + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && dnf clean all + +# Устанавливаем yq (автоопределение архитектуры) +# RUN ARCH=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/') && \ +# wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${ARCH}" && \ +# chmod +x /usr/local/bin/yq + +# Устанавливаем Docker вручную для RED OS +# RUN dnf install -y dnf-plugins-core \ +# && dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo \ +# && dnf install -y docker-ce docker-ce-cli containerd.io \ +# && dnf clean all + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/rhel/Dockerfile b/dockerfiles/rhel/Dockerfile new file mode 100644 index 0000000..c62c286 --- /dev/null +++ b/dockerfiles/rhel/Dockerfile @@ -0,0 +1,49 @@ +# RHEL с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM registry.access.redhat.com/ubi8/ubi + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python39 \ + python39-pip \ + sudo \ + && dnf clean all + +# Создаем symlink для python3 -> python3.9 +RUN ln -sf /usr/bin/python3.9 /usr/bin/python3 + +# Устанавливаем yq +# RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ +# && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +# RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/rocky/Dockerfile b/dockerfiles/rocky/Dockerfile new file mode 100644 index 0000000..780e47b --- /dev/null +++ b/dockerfiles/rocky/Dockerfile @@ -0,0 +1,54 @@ +# Rocky Linux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM rockylinux:9 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y --allowerasing \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + python3-devel \ + sudo \ + && dnf clean all + +# Устанавливаем более новую версию Python через pip если нужно +RUN python3 -m pip install --upgrade pip + +# Устанавливаем yq (автоматически определяем архитектуру) +# RUN ARCH=$(uname -m) && \ +# if [ "$ARCH" = "x86_64" ]; then ARCH="amd64"; elif [ "$ARCH" = "aarch64" ]; then ARCH="arm64"; fi && \ +# wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${ARCH}" && \ +# chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +# RUN dnf install -y dnf-plugins-core \ +# && dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo \ +# && dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/ubuntu20/Dockerfile b/dockerfiles/ubuntu20/Dockerfile new file mode 100644 index 0000000..e8b11bf --- /dev/null +++ b/dockerfiles/ubuntu20/Dockerfile @@ -0,0 +1,56 @@ +# Ubuntu 20.04 с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM ubuntu:20.04 + +# Устанавливаем переменные окружения для автоматического ответа на запросы +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем Docker вручную для Ubuntu +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release \ +# && mkdir -p /usr/share/keyrings \ +# && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ +# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu jammy stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ +# && apt-get update \ +# && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/ubuntu22/Dockerfile b/dockerfiles/ubuntu22/Dockerfile new file mode 100644 index 0000000..33140ef --- /dev/null +++ b/dockerfiles/ubuntu22/Dockerfile @@ -0,0 +1,56 @@ +# Ubuntu 22.04 с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM ubuntu:22.04 + +# Устанавливаем переменные окружения для автоматического ответа на запросы +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем Docker вручную для Ubuntu +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release \ +# && mkdir -p /usr/share/keyrings \ +# && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ +# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu jammy stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ +# && apt-get update \ +# && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/dockerfiles/ubuntu24/Dockerfile b/dockerfiles/ubuntu24/Dockerfile new file mode 100644 index 0000000..8a45a2e --- /dev/null +++ b/dockerfiles/ubuntu24/Dockerfile @@ -0,0 +1,56 @@ +# Ubuntu 24.04 с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM ubuntu:24.04 + +# Устанавливаем переменные окружения для автоматического ответа на запросы +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + +# Обновляем систему +RUN apt-get update && apt-get dist-upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + && apt-get clean + +# Устанавливаем Docker вручную для Ubuntu +# RUN apt-get update && apt-get install -y \ +# ca-certificates \ +# curl \ +# gnupg \ +# lsb-release \ +# && mkdir -p /usr/share/keyrings \ +# && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ +# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu jammy stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ +# && apt-get update \ +# && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \ +# && apt-get clean + +# Устанавливаем Docker Compose +# RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ +# && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/docs/all-images-preset.md b/docs/all-images-preset.md new file mode 100644 index 0000000..fc8dbf4 --- /dev/null +++ b/docs/all-images-preset.md @@ -0,0 +1,169 @@ +# Пресет all-images - Тестирование всех образов + +## Описание + +Пресет `all-images` предназначен для комплексного тестирования Ansible ролей на всех доступных операционных системах проекта. Это самый полный пресет, который включает все 16 образов: + +### Включенные образы + +#### Debian-based системы: +- **Ubuntu 20.04** (ubuntu20-test) - порт 8080 +- **Ubuntu 22.04** (ubuntu22-test) - порт 8081 +- **Ubuntu 24.04** (ubuntu24-test) - порт 8082 +- **Debian 9** (debian9-test) - порт 8083 +- **Debian 10** (debian10-test) - порт 8084 +- **Debian 11** (debian11-test) - порт 8085 +- **Debian 12** (debian12-test) - порт 8086 +- **Alt Linux** (alt-test) - порт 8087 +- **Astra Linux** (astra-test) - порт 8088 + +#### RHEL-based системы: +- **CentOS 7** (centos7-test) - порт 8090 +- **CentOS 8** (centos8-test) - порт 8091 +- **CentOS 9** (centos9-test) - порт 8092 +- **RHEL** (rhel-test) - порт 8085 +- **AlmaLinux** (alma-test) - порт 8086 +- **Rocky Linux** (rocky-test) - порт 8087 +- **RedOS** (redos-test) - порт 8088 + +## Использование + +### Запуск тестирования всех образов + +```bash +# Тестирование всех образов +make role test all-images +``` + +### Предварительные требования + +1. **Собранные образы** - все образы должны быть собраны: + ```bash + make docker build + ``` + +2. **Достаточно ресурсов** - тест запускает 16 контейнеров одновременно, требуется: + - Минимум 16GB RAM + - Минимум 8 CPU cores + - Достаточно места на диске + +### Особенности + +#### Порты +Каждый контейнер использует уникальный порт для доступа: +- Ubuntu 20.04: `localhost:8080` +- Ubuntu 22.04: `localhost:8081` +- Ubuntu 24.04: `localhost:8082` +- Debian 9: `localhost:8083` +- Debian 10: `localhost:8084` +- Debian 11: `localhost:8085` +- Debian 12: `localhost:8086` +- Alt Linux: `localhost:8087` +- Astra Linux: `localhost:8088` +- CentOS 7: `localhost:8090` +- CentOS 8: `localhost:8091` +- CentOS 9: `localhost:8092` +- RHEL: `localhost:8085` +- AlmaLinux: `localhost:8086` +- Rocky Linux: `localhost:8087` +- RedOS: `localhost:8088` + +#### Переменные окружения +Каждый контейнер получает переменные: +- `TEST_OS` - название ОС +- `TEST_FAMILY` - семейство ОС (Debian/RedHat/Altlinux/Astra Linux) + +#### Специальные настройки +- **Astra Linux**: автоматическое отключение Parsec +- **Все образы**: предустановленный sudo с настройкой sudoers +- **Systemd**: полная поддержка systemd в контейнерах + +## Производительность + +### Время выполнения +- **Создание контейнеров**: ~2-3 минуты +- **Тестирование ролей**: зависит от сложности ролей +- **Очистка**: ~30 секунд + +### Ресурсы +- **RAM**: 16-32GB (рекомендуется) +- **CPU**: 8-16 cores +- **Диск**: 20-40GB свободного места + +## Отладка + +### Проверка статуса контейнеров +```bash +# Список запущенных контейнеров +docker ps --filter "network=labnet" + +# Логи конкретного контейнера +docker logs ubuntu-test +docker logs astra-test +``` + +### Проблемы и решения + +#### Контейнеры не запускаются +1. Проверьте, что образы собраны: + ```bash + docker images | grep inecs/ansible-lab + ``` + +2. Пересоберите образы: + ```bash + make docker rebuild + ``` + +#### Astra Linux перезапускается +- Проблема решена в Dockerfile (отключение Parsec) +- Если проблема остается, проверьте логи: + ```bash + docker logs astra-test + ``` + +#### Нехватка ресурсов +- Уменьшите количество контейнеров в пресете +- Используйте пресет `minimal` для быстрого тестирования + +## Альтернативные пресеты + +Если `all-images` слишком ресурсоемкий, используйте: + +- `minimal` - 1 контейнер (Debian) +- `default` - 2 контейнера (Debian + RHEL) +- `multi-os` - 12 контейнеров (разные ОС) + +## Мониторинг + +### Логи тестирования +```bash +# Просмотр логов ansible-controller +docker logs ansible-controller + +# Логи конкретного playbook +tail -f /tmp/molecule_workspace/logs/ansible.log +``` + +### Метрики производительности +- Время выполнения каждого этапа +- Использование ресурсов +- Количество успешных/неудачных тестов + +## Интеграция с CI/CD + +Пресет `all-images` идеально подходит для: +- **GitHub Actions** - полное тестирование на всех ОС +- **GitLab CI** - комплексная проверка совместимости +- **Jenkins** - автоматическое тестирование релизов + +### Пример для GitHub Actions +```yaml +- name: Test all images + run: make role test all-images + timeout-minutes: 30 +``` + +## Заключение + +Пресет `all-images` обеспечивает максимальное покрытие тестирования, гарантируя совместимость Ansible ролей со всеми поддерживаемыми операционными системами. Это критически важно для production-окружений с разнородной инфраструктурой. diff --git a/docs/buildx-fixes.md b/docs/buildx-fixes.md new file mode 100644 index 0000000..3e8c48c --- /dev/null +++ b/docs/buildx-fixes.md @@ -0,0 +1,98 @@ +# Исправления проблем с Docker Buildx + +## Проблема +Команда `docker buildx ls` часто зависает в CI/CD окружениях из-за: +- Мертвых Docker контекстов (tcp://...) +- Проблем с доступом к registry +- Недостаточных привилегий +- Старых/битых builder'ов + +## Решение + +### 1. Замена `buildx ls` на `buildx inspect` +**Было:** +```bash +if ! docker buildx ls | grep -q $(DOCKER_BUILDX_BUILDER); then +``` + +**Стало:** +```bash +if docker buildx inspect $(DOCKER_BUILDX_BUILDER) >/dev/null 2>&1; then +``` + +### 2. Новые надежные функции + +#### `docker-check-builder` +- Проверяет существование builder'а через `inspect` +- Не зависает на мертвых контекстах +- Возвращает четкий статус + +#### `docker-create-builder` +- Предварительная загрузка образа `moby/buildkit:buildx-stable-1` +- Очистка старых builder'ов +- Явное указание образа buildkit +- Проверка готовности через `inspect --bootstrap` + +#### `docker-diagnose-buildx` +- Полная диагностика проблем с buildx +- Проверка версий Docker и Buildx +- Поиск мертвых контекстов +- Проверка доступа к registry +- Проверка Docker socket +- Рекомендации по устранению + +#### `docker-reset-builder` +- Полная очистка и пересоздание builder'а +- Удаление buildkit контейнеров +- Создание нового builder'а с предварительной загрузкой + +### 3. Обновленные команды + +#### `make docker setup-builder` +- Использует `docker-check-builder` вместо `buildx ls` +- Безопасное создание builder'а +- Предварительная загрузка образа + +#### `make docker clean-builder` +- Теперь использует `docker-reset-builder` +- Полная очистка buildkit контейнеров + +#### Новые команды: +- `make docker diagnose` - диагностика проблем +- `make docker reset-builder` - сброс builder'а + +### 4. Преимущества + +✅ **Нет зависаний** - не использует `buildx ls` +✅ **Быстрая диагностика** - четкие сообщения об ошибках +✅ **Предварительная загрузка** - избегает проблем с pull в bootstrap +✅ **Полная очистка** - удаляет все связанные контейнеры +✅ **Подробные логи** - понятные сообщения о процессе + +### 5. Использование + +```bash +# Диагностика проблем +make docker diagnose + +# Сброс builder'а при проблемах +make docker reset-builder + +# Обычная настройка (теперь безопасная) +make docker setup-builder + +# Сборка образов +make docker build +``` + +### 6. Рекомендации для CI/CD + +1. **Используйте `docker-diagnose-buildx`** при проблемах +2. **Настройте прокси** для доступа к registry +3. **Очищайте мертвые контексты** регулярно +4. **Используйте `docker-reset-builder`** при зависаниях +5. **Проверяйте права доступа** к Docker socket + +## Автор +Сергей Антропов +Сайт: https://devops.org.ru diff --git a/docs/cicd-setup.md b/docs/cicd-setup.md new file mode 100644 index 0000000..92c653f --- /dev/null +++ b/docs/cicd-setup.md @@ -0,0 +1,913 @@ +# Настройка CI/CD для AnsibleLab + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## 🚀 GitHub Actions + +### Базовая конфигурация + +**`.github/workflows/ansible-test.yml`:** +```yaml +name: Ansible Testing +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + - name: Run lint + run: make role lint + + test: + runs-on: ubuntu-latest + needs: lint + strategy: + matrix: + preset: [minimal, default, performance] + steps: + - uses: actions/checkout@v4 + - name: Setup Docker + run: | + sudo systemctl start docker + sudo usermod -aG docker $USER + - name: Run tests + run: make role test ${{ matrix.preset }} + + deploy-check: + runs-on: ubuntu-latest + needs: [lint, test] + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Check deployment + run: make role deploy + env: + ANSIBLE_HOST_KEY_CHECKING: false +``` + +### Продвинутая конфигурация + +**`.github/workflows/ansible-advanced.yml`:** +```yaml +name: Advanced Ansible Testing +on: [push, pull_request] + +env: + ANSIBLE_FORCE_COLOR: 'true' + DOCKER_TLS_CERTDIR: '' + +jobs: + detect-roles: + runs-on: ubuntu-latest + outputs: + roles: ${{ steps.detect.outputs.roles }} + steps: + - uses: actions/checkout@v4 + - name: Detect new roles + id: detect + run: | + echo "roles=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | tr '\n' ' ')" >> $GITHUB_OUTPUT + + update-playbooks: + runs-on: ubuntu-latest + needs: detect-roles + steps: + - uses: actions/checkout@v4 + - name: Update playbooks + run: | + chmod +x scripts/update-playbooks.sh + ./scripts/update-playbooks.sh + - name: Commit changes + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add molecule/default/site.yml roles/deploy.yml + git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles" + git push + + lint: + runs-on: ubuntu-latest + needs: update-playbooks + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + - name: Run lint + run: make role lint + + test: + runs-on: ubuntu-latest + needs: [update-playbooks, lint] + strategy: + matrix: + preset: [minimal, default, performance] + steps: + - uses: actions/checkout@v4 + - name: Setup Docker + run: | + sudo systemctl start docker + sudo usermod -aG docker $USER + - name: Run tests + run: make role test ${{ matrix.preset }} + + deploy-check: + runs-on: ubuntu-latest + needs: [lint, test] + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Check deployment + run: make role deploy + env: + ANSIBLE_HOST_KEY_CHECKING: false + + notify: + runs-on: ubuntu-latest + needs: [lint, test, deploy-check] + if: always() + steps: + - name: Notify on success + if: needs.lint.result == 'success' && needs.test.result == 'success' + run: | + echo "✅ All tests passed for new roles" + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"✅ Ansible role tests passed for new roles"}' \ + ${{ secrets.SLACK_WEBHOOK_URL }} + - name: Notify on failure + if: needs.lint.result == 'failure' || needs.test.result == 'failure' + run: | + echo "❌ Tests failed for new roles" + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"❌ Ansible role tests failed for new roles"}' \ + ${{ secrets.SLACK_WEBHOOK_URL }} +``` + +## 🏢 Azure DevOps + +### Базовая конфигурация + +**`azure-pipelines.yml`:** +```yaml +trigger: +- main +- develop + +pool: + vmImage: 'ubuntu-latest' + +variables: + ANSIBLE_FORCE_COLOR: 'true' + DOCKER_TLS_CERTDIR: '' + +stages: +- stage: Lint + displayName: 'Lint Stage' + jobs: + - job: LintJob + displayName: 'Run Lint' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + - script: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + make role lint + displayName: 'Run Ansible Lint' + +- stage: Test + displayName: 'Test Stage' + dependsOn: Lint + jobs: + - job: TestJob + displayName: 'Run Tests' + strategy: + matrix: + minimal: + preset: minimal + default: + preset: default + performance: + preset: performance + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + - script: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + make role test $(preset) + displayName: 'Run Molecule Tests' + env: + PRESET: $(preset) + +- stage: Deploy + displayName: 'Deploy Stage' + dependsOn: Test + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + jobs: + - job: DeployJob + displayName: 'Check Deployment' + steps: + - script: make role deploy + displayName: 'Check Deployment' + env: + ANSIBLE_HOST_KEY_CHECKING: false +``` + +### Продвинутая конфигурация + +**`azure-pipelines-advanced.yml`:** +```yaml +trigger: +- main +- develop + +pool: + vmImage: 'ubuntu-latest' + +variables: + ANSIBLE_FORCE_COLOR: 'true' + DOCKER_TLS_CERTDIR: '' + +stages: +- stage: Detect + displayName: 'Detect Roles' + jobs: + - job: DetectJob + displayName: 'Detect New Roles' + steps: + - script: | + echo "##vso[task.setvariable variable=roles;isOutput=true]$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | tr '\n' ' ')" + displayName: 'Detect Roles' + name: detect + +- stage: Update + displayName: 'Update Playbooks' + dependsOn: Detect + jobs: + - job: UpdateJob + displayName: 'Update Playbooks' + steps: + - script: | + chmod +x scripts/update-playbooks.sh + ./scripts/update-playbooks.sh + displayName: 'Update Playbooks' + - script: | + git config --local user.email "action@azure.com" + git config --local user.name "Azure DevOps" + git add molecule/default/site.yml deploy.yml + git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles" + git push + displayName: 'Commit Changes' + +- stage: Lint + displayName: 'Lint Stage' + dependsOn: Update + jobs: + - job: LintJob + displayName: 'Run Lint' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + - script: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + make role lint + displayName: 'Run Ansible Lint' + +- stage: Test + displayName: 'Test Stage' + dependsOn: [Update, Lint] + jobs: + - job: TestJob + displayName: 'Run Tests' + strategy: + matrix: + minimal: + preset: minimal + default: + preset: default + performance: + preset: performance + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + - script: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + make role test $(preset) + displayName: 'Run Molecule Tests' + env: + PRESET: $(preset) + +- stage: Deploy + displayName: 'Deploy Stage' + dependsOn: [Lint, Test] + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + jobs: + - job: DeployJob + displayName: 'Check Deployment' + steps: + - script: make role deploy + displayName: 'Check Deployment' + env: + ANSIBLE_HOST_KEY_CHECKING: false + +- stage: Notify + displayName: 'Notification Stage' + dependsOn: [Lint, Test, Deploy] + condition: always() + jobs: + - job: NotifyJob + displayName: 'Send Notifications' + steps: + - script: | + if [ "$(Lint.result)" == "Succeeded" ] && [ "$(Test.result)" == "Succeeded" ]; then + echo "✅ All tests passed for new roles" + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"✅ Ansible role tests passed for new roles"}' \ + $(SLACK_WEBHOOK_URL) + else + echo "❌ Tests failed for new roles" + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"❌ Ansible role tests failed for new roles"}' \ + $(SLACK_WEBHOOK_URL) + fi + displayName: 'Send Notifications' + env: + SLACK_WEBHOOK_URL: $(SLACK_WEBHOOK_URL) +``` + +## 🏭 Jenkins + +### Базовая конфигурация + +**`Jenkinsfile`:** +```groovy +pipeline { + agent any + + environment { + ANSIBLE_FORCE_COLOR = 'true' + DOCKER_TLS_CERTDIR = '' + } + + stages { + stage('Checkout') { + steps { + checkout scm + } + } + + stage('Install Dependencies') { + steps { + sh ''' + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + ''' + } + } + + stage('Lint') { + steps { + sh 'make role lint' + } + } + + stage('Test') { + parallel { + stage('Test Minimal') { + steps { + sh 'make role test minimal' + } + } + stage('Test Default') { + steps { + sh 'make role test default' + } + } + stage('Test Performance') { + steps { + sh 'make role test performance' + } + } + } + } + + stage('Deploy Check') { + when { + branch 'main' + } + steps { + sh 'make role deploy' + } + } + } + + post { + always { + archiveArtifacts artifacts: 'molecule/**/.molecule/**/*', allowEmptyArchive: true + } + + success { + echo 'Pipeline completed successfully!' + } + + failure { + echo 'Pipeline failed!' + } + } +} +``` + +### Продвинутая конфигурация + +**`Jenkinsfile-advanced`:** +```groovy +pipeline { + agent any + + environment { + ANSIBLE_FORCE_COLOR = 'true' + DOCKER_TLS_CERTDIR = '' + } + + stages { + stage('Checkout') { + steps { + checkout scm + } + } + + stage('Detect Roles') { + steps { + script { + env.ROLES = sh( + script: 'find roles/ -name "main.yml" -path "*/tasks/*" | sed "s|roles/||; s|/tasks/main.yml||" | tr "\\n" " "', + returnStdout: true + ).trim() + } + echo "Detected roles: ${env.ROLES}" + } + } + + stage('Update Playbooks') { + steps { + sh ''' + chmod +x scripts/update-playbooks.sh + ./scripts/update-playbooks.sh + ''' + sh ''' + git config --local user.email "jenkins@example.com" + git config --local user.name "Jenkins" + git add molecule/default/site.yml roles/deploy.yml + git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles" + git push + ''' + } + } + + stage('Install Dependencies') { + steps { + sh ''' + pip install --upgrade pip + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + ''' + } + } + + stage('Lint') { + steps { + sh 'make role lint' + } + } + + stage('Test') { + parallel { + stage('Test Minimal') { + steps { + sh 'make role test minimal' + } + } + stage('Test Default') { + steps { + sh 'make role test default' + } + } + stage('Test Performance') { + steps { + sh 'make role test performance' + } + } + } + } + + stage('Deploy Check') { + when { + branch 'main' + } + steps { + sh 'make role deploy' + } + } + } + + post { + always { + archiveArtifacts artifacts: 'molecule/**/.molecule/**/*', allowEmptyArchive: true + } + + success { + echo 'Pipeline completed successfully!' + script { + if (env.SLACK_WEBHOOK_URL) { + sh ''' + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"✅ Ansible role tests passed for new roles"}' \ + ${SLACK_WEBHOOK_URL} + ''' + } + } + } + + failure { + echo 'Pipeline failed!' + script { + if (env.SLACK_WEBHOOK_URL) { + sh ''' + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"❌ Ansible role tests failed for new roles"}' \ + ${SLACK_WEBHOOK_URL} + ''' + } + } + } + } +} +``` + +## 🦊 GitLab CI + +### Базовая конфигурация + +**`.gitlab-ci.yml`:** +```yaml +stages: + - lint + - test + - deploy + +variables: + ANSIBLE_FORCE_COLOR: "true" + DOCKER_TLS_CERTDIR: "" + +lint: + stage: lint + image: python:3.11 + before_script: + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - make role lint + +test: + stage: test + image: docker:latest + services: + - docker:dind + variables: + DOCKER_TLS_CERTDIR: "" + before_script: + - apk add --no-cache make python3 py3-pip + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - make role test $PRESET + parallel: + matrix: + - PRESET: [minimal, default, performance] + +deploy: + stage: deploy + image: python:3.11 + only: + - main + before_script: + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - make role deploy + variables: + ANSIBLE_HOST_KEY_CHECKING: "false" +``` + +### Продвинутая конфигурация + +**`.gitlab-ci-advanced.yml`:** +```yaml +stages: + - detect + - update + - lint + - test + - deploy + - notify + +variables: + ANSIBLE_FORCE_COLOR: "true" + DOCKER_TLS_CERTDIR: "" + +detect-roles: + stage: detect + image: alpine:latest + script: + - echo "ROLES=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | tr '\n' ' ')" >> build.env + artifacts: + reports: + dotenv: build.env + +update-playbooks: + stage: update + image: alpine:latest + script: + - apk add --no-cache make bash + - chmod +x scripts/update-playbooks.sh + - ./scripts/update-playbooks.sh + - git config --local user.email "gitlab@example.com" + - git config --local user.name "GitLab CI" + - git add molecule/default/site.yml deploy.yml + - git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles" + - git push + only: + - main + - develop + +lint: + stage: lint + image: python:3.11 + before_script: + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - make role lint + +test: + stage: test + image: docker:latest + services: + - docker:dind + variables: + DOCKER_TLS_CERTDIR: "" + before_script: + - apk add --no-cache make python3 py3-pip + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - make role test $PRESET + parallel: + matrix: + - PRESET: [minimal, default, performance] + +deploy: + stage: deploy + image: python:3.11 + only: + - main + before_script: + - pip install ansible ansible-lint + - ansible-galaxy collection install -r requirements.yml + script: + - make role deploy + variables: + ANSIBLE_HOST_KEY_CHECKING: "false" + +notify: + stage: notify + image: alpine:latest + script: + - | + if [ "$CI_JOB_STATUS" == "success" ]; then + echo "✅ All tests passed for new roles" + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"✅ Ansible role tests passed for new roles"}' \ + ${SLACK_WEBHOOK_URL} + else + echo "❌ Tests failed for new roles" + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"❌ Ansible role tests failed for new roles"}' \ + ${SLACK_WEBHOOK_URL} + fi + when: always + variables: + SLACK_WEBHOOK_URL: $SLACK_WEBHOOK_URL +``` + +## 🔔 Настройка уведомлений + +### Slack уведомления + +```yaml +# .github/workflows/notifications.yml +name: Notifications +on: [workflow_run] + +jobs: + notify: + runs-on: ubuntu-latest + if: always() + steps: + - name: Notify Slack + uses: 8398a7/action-slack@v3 + with: + status: ${{ job.status }} + channel: '#ansible' + webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} +``` + +### Teams уведомления + +```yaml +# .github/workflows/teams-notifications.yml +name: Teams Notifications +on: [workflow_run] + +jobs: + notify: + runs-on: ubuntu-latest + if: always() + steps: + - name: Notify Teams + uses: skitionek/notify-microsoft-teams@master + with: + webhook_url: ${{ secrets.TEAMS_WEBHOOK_URL }} + status: ${{ job.status }} + title: 'Ansible Role Tests' +``` + +## 📊 Мониторинг CI/CD + +### Метрики производительности + +```yaml +# .github/workflows/metrics.yml +name: CI/CD Metrics +on: [workflow_run] + +jobs: + metrics: + runs-on: ubuntu-latest + steps: + - name: Collect Metrics + run: | + echo "Build time: $(date)" + echo "Commit: ${{ github.sha }}" + echo "Branch: ${{ github.ref }}" + echo "Actor: ${{ github.actor }}" +``` + +### Отчеты о тестировании + +```yaml +# .github/workflows/reports.yml +name: Test Reports +on: [workflow_run] + +jobs: + reports: + runs-on: ubuntu-latest + steps: + - name: Generate Report + run: | + echo "## Test Results" >> $GITHUB_STEP_SUMMARY + echo "- Lint: ✅ Passed" >> $GITHUB_STEP_SUMMARY + echo "- Test: ✅ Passed" >> $GITHUB_STEP_SUMMARY + echo "- Deploy: ✅ Passed" >> $GITHUB_STEP_SUMMARY +``` + +## 🔧 Настройка секретов + +### GitHub Secrets + +```bash +# Настройка секретов в GitHub +gh secret set SLACK_WEBHOOK_URL --body "https://hooks.slack.com/services/..." +gh secret set TEAMS_WEBHOOK_URL --body "https://outlook.office.com/webhook/..." +``` + +### Azure DevOps Variables + +```yaml +# azure-pipelines.yml +variables: + - group: ansible-secrets + - name: SLACK_WEBHOOK_URL + value: $(SLACK_WEBHOOK_URL) +``` + +### Jenkins Credentials + +```groovy +// Jenkinsfile +pipeline { + agent any + environment { + SLACK_WEBHOOK_URL = credentials('slack-webhook-url') + } + // ... остальная конфигурация +} +``` + +## 🚀 Автоматизация + +### Автоматическое создание скриптов + +```bash +#!/bin/bash +# scripts/setup-cicd.sh +# Автоматическая настройка CI/CD + +echo "🔧 Настройка CI/CD для AnsibleTemplate..." + +# Создание директории .github/workflows +mkdir -p .github/workflows + +# Создание базового workflow +cat > .github/workflows/ansible-test.yml << 'EOF' +name: Ansible Testing +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run tests + run: make role test +EOF + +# Создание Azure DevOps pipeline +cat > azure-pipelines.yml << 'EOF' +trigger: +- main +pool: + vmImage: 'ubuntu-latest' +stages: +- stage: Test + jobs: + - job: TestJob + steps: + - script: make role test +EOF + +# Создание Jenkinsfile +cat > Jenkinsfile << 'EOF' +pipeline { + agent any + stages { + stage('Test') { + steps { + sh 'make role test' + } + } + } +} +EOF + +# Создание GitLab CI +cat > .gitlab-ci.yml << 'EOF' +stages: + - test +test: + stage: test + script: + - make role test +EOF + +echo "✅ CI/CD настроен" +``` + +--- + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru diff --git a/docs/creating-roles.md b/docs/creating-roles.md new file mode 100644 index 0000000..790ad4a --- /dev/null +++ b/docs/creating-roles.md @@ -0,0 +1,609 @@ +# Создание и разработка ролей для AnsibleLab + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## 🚀 Быстрый старт + +### Интерактивное управление ролями + +```bash +# Просмотр всех ролей +make role list + +# Создание новой роли (интерактивно) +make role create + +# Удаление роли (интерактивно) +make role delete +``` + +### Автоматическое обновление + +При создании или удалении роли система автоматически: +- ✅ Обновляет `roles/deploy.yml` +- ✅ Создает полную структуру папок +- ✅ Генерирует README.md с документацией +- ✅ Настраивает метаданные роли + +## 📁 Структура роли + +### Стандартная структура + +``` +roles/my-role/ +├── tasks/ # Основные задачи +│ └── main.yml +├── handlers/ # Обработчики +│ └── main.yml +├── templates/ # Шаблоны Jinja2 +│ └── my-role.conf.j2 +├── files/ # Статические файлы +│ └── my-role.service +├── vars/ # Переменные роли +│ └── main.yml +├── defaults/ # Переменные по умолчанию +│ └── main.yml +├── meta/ # Метаданные роли +│ └── main.yml +└── README.md # Документация роли +``` + +### Создание структуры + +#### Автоматическое создание (рекомендуется) + +```bash +# Интерактивное создание роли +make role create + +# Система автоматически: +# - Создаст структуру папок +# - Создаст все необходимые файлы +# - Обновит roles/deploy.yml +# - Создаст README.md с документацией +``` + +#### Ручное создание + +```bash +# Создание директории роли +mkdir -p roles/my-role/{tasks,handlers,templates,files,vars,defaults,meta} + +# Создание основных файлов +touch roles/my-role/{tasks,handlers,meta}/main.yml +touch roles/my-role/defaults/main.yml +touch roles/my-role/vars/main.yml +touch roles/my-role/README.md +``` + +## 📝 Разработка роли + +### 1. Основные задачи (tasks/main.yml) + +```yaml +--- +# Основные задачи для роли my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Установка пакетов + package: + name: "{{ my_role_packages }}" + state: present + when: my_role_enabled | default(true) + tags: + - my-role + - install + +- name: Создание пользователя + user: + name: "{{ my_role_user }}" + system: "{{ my_role_system_user | default(false) }}" + shell: "{{ my_role_shell | default('/bin/bash') }}" + home: "{{ my_role_home | default('/home/' + my_role_user) }}" + when: my_role_create_user | default(true) + tags: + - my-role + - user + +- name: Настройка конфигурации + template: + src: my-role.conf.j2 + dest: "{{ my_role_config_file }}" + owner: "{{ my_role_user }}" + group: "{{ my_role_group | default(my_role_user) }}" + mode: '0644' + backup: "{{ my_role_backup | default(true) }}" + notify: restart my-role + tags: + - my-role + - config + +- name: Настройка сервиса + systemd: + name: "{{ my_role_service_name | default('my-role') }}" + enabled: "{{ my_role_enabled | default(true) }}" + state: "{{ 'started' if my_role_enabled | default(true) else 'stopped' }}" + daemon_reload: true + tags: + - my-role + - service + +- name: Настройка файрвола + firewalld: + port: "{{ my_role_port | default('8080') }}/tcp" + permanent: true + state: "{{ 'enabled' if my_role_firewall | default(false) else 'disabled' }}" + immediate: true + when: my_role_firewall | default(false) + tags: + - my-role + - firewall +``` + +### 2. Обработчики (handlers/main.yml) + +```yaml +--- +# Обработчики для роли my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: restart my-role + systemd: + name: "{{ my_role_service_name | default('my-role') }}" + state: restarted + daemon_reload: true + when: my_role_enabled | default(true) + +- name: reload my-role + systemd: + name: "{{ my_role_service_name | default('my-role') }}" + state: reloaded + when: my_role_enabled | default(true) + +- name: stop my-role + systemd: + name: "{{ my_role_service_name | default('my-role') }}" + state: stopped + when: not my_role_enabled | default(true) +``` + +### 3. Переменные по умолчанию (defaults/main.yml) + +```yaml +--- +# Переменные по умолчанию для роли my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Основные настройки +my_role_enabled: true +my_role_user: my-role +my_role_group: my-role +my_role_system_user: false +my_role_shell: /bin/bash +my_role_home: "{{ '/home/' + my_role_user if not my_role_system_user else '/var/lib/' + my_role_user }}" + +# Пакеты +my_role_packages: + - nginx + - curl + - htop + +# Конфигурация +my_role_config_file: /etc/my-role/my-role.conf +my_role_log_level: info +my_role_port: 8080 +my_role_backup: true + +# Сервис +my_role_service_name: my-role +my_role_create_user: true + +# Безопасность +my_role_firewall: false +my_role_ssl_enabled: false +my_role_ssl_certificate: /etc/ssl/certs/my-role.crt +my_role_ssl_private_key: /etc/ssl/private/my-role.key +``` + +### 4. Переменные роли (vars/main.yml) + +```yaml +--- +# Переменные роли my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Системные переменные +my_role_system_packages: + - python3 + - python3-pip + - python3-venv + +# Конфигурационные переменные +my_role_config_template: my-role.conf.j2 +my_role_service_template: my-role.service.j2 + +# Пути +my_role_log_dir: /var/log/my-role +my_role_data_dir: /var/lib/my-role +my_role_cache_dir: /var/cache/my-role +``` + +### 5. Метаданные (meta/main.yml) + +```yaml +--- +# Метаданные роли my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +galaxy_info: + author: Сергей Антропов + description: Моя кастомная роль для AnsibleTemplate + company: https://devops.org.ru + license: MIT + min_ansible_version: "2.9" + platforms: + - name: Ubuntu + versions: + - focal + - jammy + - name: Debian + versions: + - bullseye + - bookworm + - name: EL + versions: + - 7 + - 8 + - 9 + - name: CentOS + versions: + - 7 + - 8 + - 9 + - name: AlmaLinux + versions: + - 8 + - 9 + - name: Rocky + versions: + - 8 + - 9 + galaxy_tags: + - system + - configuration + - my-role + - web + - service + +dependencies: + - role: geerlingguy.docker + when: my_role_docker_enabled | default(false) + - role: geerlingguy.kubernetes + when: my_role_k8s_enabled | default(false) +``` + +### 6. Шаблоны (templates/) + +**`templates/my-role.conf.j2`:** +```jinja2 +# Конфигурация my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +[main] +enabled = {{ my_role_enabled | default(true) }} +user = {{ my_role_user }} +group = {{ my_role_group | default(my_role_user) }} +log_level = {{ my_role_log_level | default('info') }} +port = {{ my_role_port | default(8080) }} + +[logging] +log_file = {{ my_role_log_dir | default('/var/log/my-role') }}/my-role.log +log_level = {{ my_role_log_level | default('info') }} +max_size = {{ my_role_log_max_size | default('100M') }} +max_files = {{ my_role_log_max_files | default('5') }} + +[security] +ssl_enabled = {{ my_role_ssl_enabled | default(false) }} +{% if my_role_ssl_enabled | default(false) %} +ssl_certificate = {{ my_role_ssl_certificate }} +ssl_private_key = {{ my_role_ssl_private_key }} +{% endif %} + +[network] +host = {{ my_role_host | default('0.0.0.0') }} +port = {{ my_role_port | default(8080) }} +timeout = {{ my_role_timeout | default(30) }} + +{% if my_role_web_config | default(false) %} +[web] +enabled = true +{% raw %} +{{ my_role_nginx_config }} +{% endraw %} +{% endif %} +``` + +**`templates/my-role.service.j2`:** +```ini +[Unit] +Description=My Role Service +After=network.target + +[Service] +Type=simple +User={{ my_role_user }} +Group={{ my_role_group | default(my_role_user) }} +ExecStart=/usr/bin/my-role --config {{ my_role_config_file }} +ExecReload=/bin/kill -HUP $MAINPID +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +### 7. Статические файлы (files/) + +**`files/my-role.service`:** +```ini +[Unit] +Description=My Role Service +After=network.target + +[Service] +Type=simple +User=my-role +Group=my-role +ExecStart=/usr/bin/my-role --config /etc/my-role/my-role.conf +ExecReload=/bin/kill -HUP $MAINPID +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +## 🧪 Тестирование роли + +### 1. Lint проверка + +```bash +# Lint проверка роли +make role lint + +# Lint проверка конкретной роли +ansible-lint roles/my-role/ +``` + +### 2. Тестирование в Docker + +```bash +# Тестирование с default preset +make role test + +# Тестирование с minimal preset +make role test minimal + +# Тестирование с custom preset +make role test my-custom-preset +``` + +### 3. Тестирование на реальных серверах + +```bash +# Dry-run развертывания +make role deploy + +# Развертывание на продакшн +make role deploy +# Подтвердить развертывание: y +``` + +## 🔧 Интеграция с системой + +### 1. Автоматическое включение в playbook'и + +Роль автоматически включается в: +- `molecule/default/site.yml` (для тестирования) +- `roles/deploy.yml` (для продакшн развертывания) + +### 2. Обновление playbook'ов + +```bash +# Автоматическое обновление playbook'ов +make update-playbooks + +# Проверка обновленных playbook'ов +make role test +``` + +### 3. Создание документации + +```bash +# Автоматическое создание документации +make generate-docs + +# Проверка созданной документации +ls -la roles/*/README.md +``` + +## 📚 Документация роли + +### README.md для роли + +```markdown +# Роль My-Role + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## Описание + +Роль для настройки и конфигурации my-role сервиса. + +## Требования + +- Ansible >= 2.9 +- Поддерживаемые ОС: Ubuntu, Debian, RHEL, CentOS, AlmaLinux, Rocky Linux + +## Переменные + +| Переменная | Тип | По умолчанию | Описание | +|------------|-----|--------------|----------| +| `my_role_enabled` | boolean | `true` | Включить роль | +| `my_role_user` | string | `my-role` | Пользователь для сервиса | +| `my_role_packages` | list | `['nginx', 'curl']` | Пакеты для установки | +| `my_role_port` | integer | `8080` | Порт сервиса | +| `my_role_ssl_enabled` | boolean | `false` | Включить SSL | + +## Примеры использования + +### Базовое использование + +```yaml +- name: Настройка my-role + hosts: all + roles: + - my-role +``` + +### С кастомными параметрами + +```yaml +- name: Настройка my-role с SSL + hosts: all + roles: + - role: my-role + vars: + my_role_ssl_enabled: true + my_role_port: 8443 + my_role_packages: + - nginx + - openssl +``` + +### В playbook + +```yaml +--- +- name: Настройка web серверов + hosts: web_servers + become: true + roles: + - role: my-role + vars: + my_role_enabled: true + my_role_ssl_enabled: true + my_role_firewall: true + tags: + - web + - my-role +``` + +## Tags + +- `my-role` - выполнение всех задач роли +- `install` - установка пакетов +- `user` - создание пользователя +- `config` - настройка конфигурации +- `service` - управление сервисом +- `firewall` - настройка файрвола + +## Поддерживаемые ОС + +- Red Hat Enterprise Linux 7/8/9 +- CentOS 7/8/Stream +- AlmaLinux 8/9 +- Rocky Linux 8/9 +- Ubuntu 20.04/22.04 +- Debian 10/11/12 + +## Лицензия + +MIT + +## Автор + +Сергей Антропов - https://devops.org.ru +``` + +## 🚀 Полный цикл разработки + +### 1. Создание роли + +```bash +# Создание структуры +mkdir -p roles/my-role/{tasks,handlers,templates,files,vars,defaults,meta} +touch roles/my-role/{tasks,handlers,meta}/main.yml +touch roles/my-role/defaults/main.yml +touch roles/my-role/vars/main.yml +touch roles/my-role/README.md +``` + +### 2. Разработка + +```bash +# Редактирование файлов роли +nano roles/my-role/tasks/main.yml +nano roles/my-role/defaults/main.yml +# ... остальные файлы +``` + +### 3. Тестирование + +```bash +# Lint проверка +make role lint + +# Тестирование в Docker +make role test minimal + +# Тестирование с custom preset +make role test my-custom-preset +``` + +### 4. Развертывание + +```bash +# Тестирование на реальных серверах +make role deploy + +# Развертывание на продакшн +make role deploy +# Подтвердить развертывание: y +``` + +## 🔧 Лучшие практики + +### 1. Структура кода + +- **Используйте теги** для группировки задач +- **Добавляйте условия** для условного выполнения +- **Используйте обработчики** для перезапуска сервисов +- **Документируйте переменные** в defaults/main.yml + +### 2. Безопасность + +- **Используйте vault** для секретов +- **Проверяйте права** пользователей +- **Настраивайте файрвол** при необходимости +- **Используйте SSL** для защищенных соединений + +### 3. Производительность + +- **Используйте кеширование** для повторных операций +- **Оптимизируйте пакеты** для уменьшения размера +- **Используйте параллельное выполнение** где возможно +- **Мониторьте ресурсы** системы + +--- + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru diff --git a/docs/deploy-yml-customization.md b/docs/deploy-yml-customization.md new file mode 100644 index 0000000..daf5ee1 --- /dev/null +++ b/docs/deploy-yml-customization.md @@ -0,0 +1,520 @@ +# Кастомизация deploy.yml - Полное руководство + +## Описание + +Файл `roles/deploy.yml` - это основной playbook для развертывания Ansible ролей на продакшн серверах. Этот документ содержит полную сводку по кастомизации и настройке различных сценариев развертывания. + +## Базовый пример + +```yaml +--- +# Playbook для развертывания на продакшн серверах +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Развертывание всех ролей + hosts: all + roles: + - ping +``` + +## 1. Управление привилегиями (become) + +### Базовое использование become +```yaml +- name: Развертывание с sudo правами + hosts: all + become: true + roles: + - nginx + - postgresql +``` + +### Become с паролем +```yaml +- name: Развертывание с sudo паролем + hosts: all + become: true + become_method: sudo + become_user: root + vars: + ansible_become_pass: "{{ vault_sudo_password }}" + roles: + - nginx +``` + +### Become для конкретных ролей +```yaml +- name: Развертывание с разными привилегиями + hosts: all + roles: + - role: nginx + become: true + - role: app-config + become: false +``` + +## 2. Группировка хостов + +### Развертывание по группам +```yaml +- name: Развертывание на веб-серверах + hosts: webservers + become: true + roles: + - nginx + - php-fpm + +- name: Развертывание на БД серверах + hosts: databases + become: true + roles: + - postgresql + - redis + +- name: Развертывание на мониторинг серверах + hosts: monitoring + become: true + roles: + - prometheus + - grafana +``` + +### Условное развертывание +```yaml +- name: Развертывание на production + hosts: production + become: true + when: environment == "production" + roles: + - nginx + - ssl-certificates + +- name: Развертывание на staging + hosts: staging + become: false + when: environment == "staging" + roles: + - nginx +``` + +## 3. Переменные и конфигурация + +### Глобальные переменные +```yaml +- name: Развертывание с переменными + hosts: all + become: true + vars: + nginx_port: 80 + nginx_ssl_port: 443 + app_name: "my-application" + app_version: "1.0.0" + roles: + - nginx + - application +``` + +### Переменные для конкретных ролей +```yaml +- name: Развертывание с ролевыми переменными + hosts: all + become: true + roles: + - role: nginx + vars: + nginx_port: 80 + nginx_ssl_enabled: true + - role: postgresql + vars: + postgresql_version: "13" + postgresql_max_connections: 200 +``` + +### Использование group_vars и host_vars +```yaml +# group_vars/webservers.yml +nginx_worker_processes: 4 +nginx_worker_connections: 1024 + +# group_vars/databases.yml +postgresql_shared_buffers: "256MB" +postgresql_effective_cache_size: "1GB" + +# В deploy.yml +- name: Развертывание с групповыми переменными + hosts: webservers:databases + become: true + roles: + - nginx + - postgresql +``` + +## 4. Теги (Tags) + +### Базовое использование тегов +```yaml +- name: Развертывание с тегами + hosts: all + become: true + roles: + - role: nginx + tags: ['web', 'nginx'] + - role: postgresql + tags: ['database', 'postgresql'] + - role: monitoring + tags: ['monitoring', 'prometheus'] +``` + +### Запуск с тегами +```bash +# Развертывание только веб-серверов +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --tags web + +# Развертывание только БД +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --tags database + +# Развертывание веб + БД +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --tags web,database + +# Пропустить мониторинг +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --skip-tags monitoring +``` + +## 5. Обработчики (Handlers) + +### Использование обработчиков +```yaml +- name: Развертывание с обработчиками + hosts: all + become: true + roles: + - nginx + - postgresql + handlers: + - name: restart nginx + service: + name: nginx + state: restarted + listen: "restart nginx" + + - name: restart postgresql + service: + name: postgresql + state: restarted + listen: "restart postgresql" +``` + +## 6. Условное выполнение + +### Условия на основе переменных +```yaml +- name: Развертывание с условиями + hosts: all + become: true + roles: + - role: nginx + when: nginx_enabled | default(true) + - role: postgresql + when: database_enabled | default(true) + - role: redis + when: cache_enabled | default(false) +``` + +### Условия на основе групп +```yaml +- name: Развертывание с групповыми условиями + hosts: all + become: true + roles: + - role: nginx + when: "'webservers' in group_names" + - role: postgresql + when: "'databases' in group_names" + - role: monitoring + when: "'monitoring' in group_names" +``` + +## 7. Параллельное выполнение + +### Настройка параллелизма +```yaml +- name: Развертывание с параллелизмом + hosts: all + become: true + serial: 2 # Выполнять на 2 хостах одновременно + roles: + - nginx + - postgresql +``` + +### Каскадное развертывание +```yaml +- name: Развертывание БД (первыми) + hosts: databases + become: true + serial: 1 + roles: + - postgresql + +- name: Развертывание приложений (после БД) + hosts: webservers + become: true + serial: 2 + roles: + - nginx + - application +``` + +## 8. Обработка ошибок + +### Игнорирование ошибок +```yaml +- name: Развертывание с игнорированием ошибок + hosts: all + become: true + ignore_errors: true + roles: + - nginx + - postgresql +``` + +### Обработка ошибок на уровне ролей +```yaml +- name: Развертывание с обработкой ошибок + hosts: all + become: true + roles: + - role: nginx + ignore_errors: true + - role: postgresql + ignore_errors: false +``` + +## 9. Инвентарь и подключение + +### Различные пользователи +```yaml +- name: Развертывание с разными пользователями + hosts: all + become: true + remote_user: "{{ ansible_user | default('ubuntu') }}" + roles: + - nginx + - postgresql +``` + +### SSH настройки +```yaml +- name: Развертывание с SSH настройками + hosts: all + become: true + gather_facts: true + roles: + - nginx + - postgresql + vars: + ansible_ssh_private_key_file: "~/.ssh/id_rsa" + ansible_ssh_common_args: "-o StrictHostKeyChecking=no" +``` + +## 10. Полный пример продакшн развертывания + +```yaml +--- +# Полный пример продакшн развертывания +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# 1. Развертывание инфраструктуры +- name: Развертывание инфраструктуры + hosts: infrastructure + become: true + serial: 1 + roles: + - role: nginx + vars: + nginx_ssl_enabled: true + nginx_ssl_cert: "{{ ssl_cert_path }}" + nginx_ssl_key: "{{ ssl_key_path }}" + tags: ['infrastructure', 'nginx'] + +# 2. Развертывание БД +- name: Развертывание базы данных + hosts: databases + become: true + serial: 1 + roles: + - role: postgresql + vars: + postgresql_version: "13" + postgresql_max_connections: 200 + postgresql_shared_buffers: "256MB" + tags: ['database', 'postgresql'] + +# 3. Развертывание приложений +- name: Развертывание приложений + hosts: webservers + become: true + serial: 2 + roles: + - role: nginx + vars: + nginx_upstream_servers: "{{ app_servers }}" + tags: ['application', 'nginx'] + - role: application + vars: + app_version: "{{ app_version }}" + app_environment: "{{ environment }}" + tags: ['application'] + +# 4. Развертывание мониторинга +- name: Развертывание мониторинга + hosts: monitoring + become: true + when: monitoring_enabled | default(true) + roles: + - role: prometheus + tags: ['monitoring', 'prometheus'] + - role: grafana + tags: ['monitoring', 'grafana'] +``` + +## 11. Команды запуска + +### Базовые команды +```bash +# Развертывание всех ролей +make role deploy + +# Развертывание с проверкой (dry-run) +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --check + +# Развертывание с тегами +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --tags web,database + +# Развертывание с переменными +ansible-playbook -i inventory/hosts.ini roles/deploy.yml -e "app_version=1.0.0" + +# Развертывание с лимитом хостов +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --limit webservers +``` + +### Продвинутые команды +```bash +# Развертывание с параллелизмом +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --forks 5 + +# Развертывание с детальным выводом +ansible-playbook -i inventory/hosts.ini roles/deploy.yml -vvv + +# Развертывание с обработкой ошибок +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --force-handlers + +# Развертывание с тестированием +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --check --diff +``` + +## 12. Переменные окружения + +### Использование переменных окружения +```bash +# Установка переменных окружения +export ANSIBLE_HOST_KEY_CHECKING=False +export ANSIBLE_SSH_RETRIES=3 +export ANSIBLE_TIMEOUT=30 + +# Развертывание +make role deploy +``` + +### Файл переменных +```yaml +# group_vars/all.yml +ansible_user: ubuntu +ansible_ssh_private_key_file: "~/.ssh/id_rsa" +ansible_ssh_common_args: "-o StrictHostKeyChecking=no" + +# Переменные приложения +app_name: "my-application" +app_version: "1.0.0" +environment: "production" + +# Переменные БД +postgresql_version: "13" +postgresql_max_connections: 200 +``` + +## 13. Безопасность + +### Использование Vault +```yaml +# В deploy.yml +- name: Развертывание с секретами + hosts: all + become: true + vars: + db_password: "{{ vault_db_password }}" + ssl_cert: "{{ vault_ssl_cert }}" + roles: + - postgresql + - nginx +``` + +### Запуск с Vault +```bash +# Развертывание с паролем Vault +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --ask-vault-pass + +# Развертывание с файлом пароля +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --vault-password-file .vault_pass +``` + +## 14. Отладка и логирование + +### Включение отладки +```yaml +- name: Развертывание с отладкой + hosts: all + become: true + debug: true + roles: + - nginx + - postgresql +``` + +### Логирование +```bash +# Развертывание с логированием +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --log-path /var/log/ansible.log + +# Развертывание с детальным выводом +ansible-playbook -i inventory/hosts.ini roles/deploy.yml -vvv +``` + +## 15. Лучшие практики + +### Структура файла +1. **Комментарии** - описывайте каждый блок +2. **Группировка** - логически группируйте роли +3. **Переменные** - выносите переменные в отдельные файлы +4. **Теги** - используйте теги для гибкости +5. **Условия** - добавляйте условия для безопасности + +### Рекомендации +- Используйте `become: true` для системных ролей +- Группируйте хосты по функциональности +- Применяйте теги для модульности +- Используйте переменные для конфигурации +- Добавляйте условия для безопасности +- Логируйте все операции +- Тестируйте с `--check` перед развертыванием + +## Заключение + +Файл `roles/deploy.yml` - это центральный элемент развертывания. Правильная его настройка обеспечивает гибкость, безопасность и надежность развертывания Ansible ролей на продакшн серверах. + +Для получения дополнительной информации см.: +- [Создание ролей](creating-roles.md) +- [Настройка CI/CD](cicd-setup.md) +- [Мониторинг](monitoring.md) diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..3567620 --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,425 @@ +# Примеры использования универсальной системы тестирования + +## Пример 1: Тестирование кластера etcd + PostgreSQL + Patroni + +### Описание +Этот пример демонстрирует тестирование высокодоступного кластера PostgreSQL с Patroni и etcd. + +### Preset: etcd-patroni + +```yaml +# molecule/presets/etcd-patroni.yml +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"] +``` + +### Запуск тестирования + +```bash +# Информация о preset'е +make preset-info PRESET=etcd-patroni + +# Тестирование с preset'ом +make preset-test PRESET=etcd-patroni + +# Или через role test +make role test etcd-patroni +``` + +### Проверка результатов + +```bash +# Проверить статус контейнеров +make container-info + +# Проверить vault файлы +make vault-check +``` + +## Пример 2: Нагрузочное тестирование + +### Описание +Этот пример демонстрирует тестирование под нагрузкой с множественными серверами и кэшем. + +### Preset: performance + +```yaml +# molecule/presets/performance.yml +hosts: + # Основные серверы (5 узлов) + - name: server1 + family: debian + groups: [servers, web, app] + - name: server2 + family: rhel + groups: [servers, web, app] + - name: server3 + family: debian + 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"] +``` + +### Запуск тестирования + +```bash +# Тестирование с performance preset'ом +make role test performance + +# Проверка статуса +make container-info +``` + +## Пример 3: Тестирование безопасности + +### Описание +Этот пример демонстрирует тестирование в безопасной среде с bastion хостами и изоляцией. + +### Preset: security + +```yaml +# molecule/presets/security.yml +hosts: + # Bastion хосты (точки входа) + - name: bastion1 + family: rhel + groups: [bastion, security, jump] + publish: ["2222:22"] + - name: bastion2 + family: debian + 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" +``` + +### Запуск тестирования + +```bash +# Тестирование с security preset'ом +make role test security + +# Проверка безопасности +make vault-check +make vault-scan +``` + +## Пример 4: Тестирование на разных ОС + +### Описание +Этот пример демонстрирует тестирование на различных операционных системах. + +### Preset: multi-os + +```yaml +# molecule/presets/multi-os.yml +hosts: + # Debian/Ubuntu серверы + - name: ubuntu1 + family: ubuntu + groups: [ubuntu, servers, web] + - name: debian1 + family: debian + groups: [debian, servers, web] + - name: ubuntu2 + family: ubuntu + groups: [ubuntu, servers, app] + - name: debian2 + family: debian + groups: [debian, servers, app] + + # RHEL/CentOS серверы + - name: rhel1 + family: rhel + groups: [rhel, servers, web] + - name: centos1 + family: centos + groups: [centos, servers, web] + - name: rhel2 + family: rhel + groups: [rhel, servers, app] + - name: centos2 + family: centos + groups: [centos, servers, app] + + # База данных на разных ОС + - name: db-ubuntu + family: ubuntu + groups: [database, ubuntu, 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"] +``` + +### Запуск тестирования + +```bash +# Тестирование с multi-os preset'ом +make role test multi-os + +# Проверка типов контейнеров +make container-types +``` + +## Пример 5: Создание собственного preset'а + +### Описание +Этот пример демонстрирует создание собственного preset'а для специфических нужд. + +### Создание preset'а + +```bash +# Создать новый preset +cat > molecule/presets/my-custom.yml << 'EOF' +--- +# Пресет для тестирования веб-приложения +# Автор: Ваше имя +# Сайт: https://your-site.com + +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: + # Веб-серверы + - name: web1 + family: debian + groups: [web, servers] + publish: ["80:80", "443:443"] + - name: web2 + family: rhel + groups: [web, servers] + publish: ["8080:80", "8443:443"] + + # База данных + - name: db1 + family: rhel + groups: [database, db] + - name: db2 + family: debian + groups: [database, db] + + # Кэш + - name: cache1 + family: debian + groups: [cache, redis] + + # DinD узел для тестирования + - name: app-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080"] +EOF +``` + +### Использование preset'а + +```bash +# Информация о preset'е +make preset-info PRESET=my-custom + +# Тестирование с preset'ом +make preset-test PRESET=my-custom + +# Или через role test +make role test my-custom +``` + +## Пример 6: Работа с Ansible Vault + +### Создание vault файла + +```bash +# Создать файл секретов +make vault create + +# Ввести имя файла: secrets +# Ввести содержимое: +# --- +# database_password: "super_secret_password" +# api_key: "your_api_key_here" +# ssl_cert: "your_ssl_certificate" +``` + +### Использование в ролях + +```yaml +# roles/my-role/tasks/main.yml +- name: Configure database + template: + src: database.conf.j2 + dest: /etc/database.conf + vars: + db_password: "{{ database_password }}" + api_key: "{{ api_key }}" +``` + +### Проверка безопасности + +```bash +# Проверить vault файлы +make vault-check + +# Найти потенциальные секреты +make vault-scan +``` + +## Заключение + +Эти примеры демонстрируют различные способы использования универсальной системы тестирования Ansible ролей. Вы можете: + +1. Использовать готовые preset'ы для быстрого тестирования +2. Создавать собственные preset'ы для специфических нужд +3. Комбинировать различные типы контейнеров +4. Использовать Ansible Vault для безопасности +5. Тестировать на различных операционных системах + +Для получения дополнительной информации используйте: +- `make help` - общая справка +- `make preset-list` - список preset'ов +- `make container-types` - типы контейнеров +- `make vault` - команды Vault + diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..0e3aa1b --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,294 @@ +# Быстрый старт с AnsibleLab + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## 🚀 Установка и настройка + +### 1. Клонирование репозитория + +```bash +git clone https://github.com/your-username/AnsibleLab.git +cd AnsibleLab +``` + +### 2. Настройка Docker + +```bash +# Настройка multi-arch builder +make docker setup-builder + +# Сборка всех образов +make docker build + +# Проверка собранных образов +make docker info +``` + +## 🧪 Первое тестирование + +### 1. Управление ролями + +```bash +# Просмотр всех ролей +make role list + +# Создание новой роли (интерактивно) +make role create + +# Удаление роли (интерактивно) +make role delete +``` + +### 2. Просмотр доступных preset'ов + +```bash +# Список всех preset'ов +make presets list + +# Информация о конкретном preset'е +make presets info PRESET=default +``` + +### 3. Тестирование роли ping + +```bash +# Тестирование с default preset +make role test + +# Тестирование с minimal preset +make role test minimal +``` + +### 3. Проверка результатов + +```bash +# Просмотр логов +docker logs ansible-controller + +# Вход в контейнер для отладки +docker exec -it ansible-controller bash +``` + +## 🔧 Создание первой роли + +### 1. Создание структуры роли + +```bash +# Создание директории роли +mkdir -p roles/my-role/{tasks,handlers,templates,files,vars,defaults,meta} + +# Создание основных файлов +touch roles/my-role/{tasks,handlers,meta}/main.yml +touch roles/my-role/defaults/main.yml +touch roles/my-role/vars/main.yml +touch roles/my-role/README.md +``` + +### 2. Разработка роли + +**`roles/my-role/tasks/main.yml`:** +```yaml +--- +# Основные задачи для роли my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Установка пакетов + package: + name: "{{ my_role_packages }}" + state: present + when: my_role_enabled | default(true) + tags: + - my-role + - install + +- name: Настройка конфигурации + template: + src: my-role.conf.j2 + dest: /etc/my-role/my-role.conf + owner: root + group: root + mode: '0644' + notify: restart my-role + tags: + - my-role + - config +``` + +**`roles/my-role/defaults/main.yml`:** +```yaml +--- +# Переменные по умолчанию для роли my-role +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Основные настройки +my_role_enabled: true +my_role_packages: + - nginx + - curl + +# Конфигурация +my_role_config_file: /etc/my-role/my-role.conf +my_role_log_level: info +``` + +### 3. Тестирование роли + +```bash +# Lint проверка +make role lint + +# Тестирование в Docker +make role test minimal + +# Тестирование с custom preset +make role test my-custom-preset +``` + +## 🚀 Развертывание на продакшн + +### 1. Настройка инвентори + +**`inventory/hosts.ini`:** +```ini +# Продакшн серверы +[web_servers] +web1.example.com ansible_host=192.168.1.10 +web2.example.com ansible_host=192.168.1.11 + +[db_servers] +db1.example.com ansible_host=192.168.1.20 +db2.example.com ansible_host=192.168.1.21 + +[all:vars] +ansible_user=devops +ansible_ssh_private_key_file=~/.ssh/id_rsa +ansible_ssh_common_args='-o StrictHostKeyChecking=no' +``` + +### 2. Настройка SSH ключей + +```bash +# Генерация SSH ключа +ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa + +# Копирование ключа на серверы +ssh-copy-id devops@web1.example.com +ssh-copy-id devops@web2.example.com +``` + +### 3. Тестирование подключения + +```bash +# Проверка подключения +ansible all -i inventory/hosts.ini -m ping + +# Dry-run развертывания +make role deploy +``` + +### 4. Развертывание + +```bash +# Развертывание на продакшн +make role deploy +# Подтвердить развертывание: y +``` + +## 🔐 Управление секретами + +### 1. Инициализация vault + +```bash +# Создание файла пароля +make vault init + +# Создание файла секретов +make vault create +``` + +### 2. Работа с секретами + +```bash +# Редактирование секретов +make vault edit + +# Просмотр секретов +make vault show + +# Шифрование файла +make vault encrypt +``` + +## 🏗️ CI/CD интеграция + +### 1. GitHub Actions + +```yaml +# .github/workflows/ansible-test.yml +name: Ansible Testing +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run tests + run: make role test +``` + +### 2. Azure DevOps + +```yaml +# azure-pipelines.yml +trigger: +- main +pool: + vmImage: 'ubuntu-latest' +stages: +- stage: Test + jobs: + - job: TestJob + steps: + - script: make role test +``` + +## 📊 Мониторинг и диагностика + +### 1. Диагностика Docker + +```bash +# Диагностика buildx проблем +make docker diagnose + +# Проверка builder'а +make docker setup-builder + +# Сброс builder'а при проблемах +make docker reset-builder +``` + +### 2. Логи и отчеты + +```bash +# Просмотр логов контейнера +docker logs ansible-controller + +# Вход в контейнер для отладки +docker exec -it ansible-controller bash +``` + +## 🎯 Следующие шаги + +1. **Изучите документацию** по [созданию ролей](creating-roles.md) +2. **Настройте CI/CD** по [инструкции](cicd-setup.md) +3. **Изучите Docker образы** в [dockerfiles/README.md](../dockerfiles/README.md) +4. **Настройте мониторинг** по [руководству](monitoring.md) + +--- + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru diff --git a/docs/linting-guide.md b/docs/linting-guide.md new file mode 100644 index 0000000..85f7285 --- /dev/null +++ b/docs/linting-guide.md @@ -0,0 +1,226 @@ +# 🔍 Руководство по линтингу ролей + +## Автор +Сергей Антропов +Сайт: https://devops.org.ru + +## Обзор + +Линтинг ролей - это автоматическая проверка синтаксиса, стиля и соответствия лучшим практикам Ansible. В AnsibleTemplate используется `ansible-lint` для обеспечения качества кода. + +## Команды линтинга + +### Проверка всех ролей +```bash +make role lint +``` +- Проверяет все роли в директории `roles/` +- Использует конфигурацию из `.ansible-lint` +- Показывает все найденные ошибки и предупреждения + +### Проверка конкретной роли +```bash +make role lint devops +make role lint ping +``` +- Проверяет только указанную роль +- Автоматически валидирует существование роли +- Показывает доступные роли при ошибке + +## Профили линтинга + +Ansible-lint использует несколько профилей для разных уровней строгости: + +### Production (по умолчанию) +- Самый строгий профиль +- Проверяет все правила +- Рекомендуется для продакшн кода + +### Basic +- Базовые правила +- Подходит для разработки +- Менее строгий чем production + +### Min +- Минимальные правила +- Только критичные ошибки +- Для быстрой проверки + +## Конфигурация + +Линтинг настраивается через файл `.ansible-lint`: + +```yaml +--- +# Профиль по умолчанию +profile: production + +# Исключения +skip_list: + - yaml[line-length] # Исключить проверку длины строк + +# Дополнительные правила +enable_list: + - name[casing] # Включить проверку именования + +# Игнорирование файлов +exclude_paths: + - .cache/ + - .github/ + - tests/ +``` + +## Типы ошибок + +### Синтаксические ошибки +- Неправильный YAML синтаксис +- Ошибки в Jinja2 шаблонах +- Неправильная структура playbook + +### Стилистические ошибки +- Trailing spaces (лишние пробелы) +- Неправильные комментарии +- Неправильное форматирование + +### Лучшие практики +- Использование устаревших модулей +- Неправильное использование become +- Отсутствие changed_when для command + +## Примеры исправлений + +### Trailing spaces +```yaml +# ❌ Неправильно + groups: ["sudo", "docker"] + # Лишние пробелы в конце строки + +# ✅ Правильно + groups: ["sudo", "docker"] +``` + +### Комментарии +```yaml +# ❌ Неправильно +#Комментарий без пробела + +# ✅ Правильно +# Комментарий с пробелом +``` + +### Changed when +```yaml +# ❌ Неправильно +- name: "Проверка статуса" + command: "systemctl status nginx" + +# ✅ Правильно +- name: "Проверка статуса" + command: "systemctl status nginx" + changed_when: false +``` + +## Автоматическое исправление + +Некоторые ошибки можно исправить автоматически: + +```bash +# Исправить trailing spaces +sed -i 's/[[:space:]]*$//' roles/*/tasks/*.yml + +# Исправить комментарии +sed -i 's/^#\([^ ]\)/# \1/' roles/*/tasks/*.yml +``` + +## Интеграция с CI/CD + +Линтинг автоматически запускается в CI/CD пайплайне: + +```yaml +# .github/workflows/lint.yml +name: Lint +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run lint + run: make role lint +``` + +## Лучшие практики + +### 1. Регулярная проверка +```bash +# Проверяйте код перед коммитом +make role lint + +# Проверяйте конкретную роль при разработке +make role lint devops +``` + +### 2. Исправляйте ошибки сразу +- Не накапливайте ошибки +- Исправляйте по мере обнаружения +- Используйте автоматические исправления + +### 3. Настройте IDE +- Включите поддержку YAML +- Настройте автоформатирование +- Используйте расширения для Ansible + +### 4. Используйте pre-commit hooks +```yaml +# .pre-commit-config.yaml +repos: + - repo: https://github.com/ansible/ansible-lint + rev: v6.0.0 + hooks: + - id: ansible-lint +``` + +## Устранение неполадок + +### Ошибка "Role not found" +```bash +❌ Роль 'nonexistent' не найдена в roles/ +📋 Доступные роли: + - devops + - ping +``` +**Решение**: Проверьте правильность имени роли + +### Ошибка "Docker image not found" +```bash +Unable to find image 'ansible-controller:latest' locally +``` +**Решение**: Соберите Docker образы: +```bash +make docker build +``` + +### Ошибка "Permission denied" +```bash +Permission denied: /workspace/roles/ +``` +**Решение**: Проверьте права доступа к файлам + +## Дополнительные ресурсы + +- [Ansible Lint Documentation](https://ansible.readthedocs.io/projects/lint/) +- [Ansible Best Practices](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html) +- [YAML Style Guide](https://yaml.org/spec/1.2/spec.html) + +## Поддержка + +Если у вас возникли вопросы или проблемы с линтингом: + +1. Проверьте документацию выше +2. Запустите `make role lint` для диагностики +3. Обратитесь к команде разработки + +--- + +**Последнее обновление**: $(date) +**Версия**: 1.0.0 diff --git a/docs/molecule-guide.md b/docs/molecule-guide.md new file mode 100644 index 0000000..299c3c6 --- /dev/null +++ b/docs/molecule-guide.md @@ -0,0 +1,859 @@ +# Подробное руководство по файлам 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` - команды для запуска тестов diff --git a/docs/monitoring.md b/docs/monitoring.md new file mode 100644 index 0000000..450eb1c --- /dev/null +++ b/docs/monitoring.md @@ -0,0 +1,593 @@ +# Мониторинг и диагностика AnsibleLab + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## 🔍 Диагностика Docker + +### Проверка состояния Docker + +```bash +# Проверка статуса Docker +docker info + +# Проверка запущенных контейнеров +docker ps -a + +# Проверка образов +docker images | grep inecs/ansible-lab + +# Проверка сетей +docker network ls +``` + +### Диагностика buildx проблем + +```bash +# Диагностика buildx +make docker diagnose + +# Проверка builder'а +make docker setup-builder + +# Сброс builder'а при проблемах +make docker reset-builder +``` + +### Логи Docker + +```bash +# Логи Docker daemon +sudo journalctl -u docker.service + +# Логи конкретного контейнера +docker logs ansible-controller + +# Логи с временными метками +docker logs -t ansible-controller + +# Следить за логами в реальном времени +docker logs -f ansible-controller +``` + +## 🧪 Диагностика тестирования + +### Проверка preset'ов + +```bash +# Список доступных preset'ов +make presets list + +# Информация о конкретном preset'е +make presets info PRESET=default + +# Проверка файлов preset'ов +ls -la molecule/presets/ +``` + +### Проверка инвентори + +```bash +# Проверка тестового инвентори +cat ${MOLECULE_EPHEMERAL_DIRECTORY}/inventory/hosts.ini + +# Проверка продакшн инвентори +cat inventory/hosts.ini + +# Тестирование подключения +ansible all -i inventory/hosts.ini -m ping +``` + +### Логи тестирования + +```bash +# Логи Molecule +ls -la molecule/default/.molecule/ + +# Логи конкретного теста +cat molecule/default/.molecule/test/ansible.log + +# Логи Ansible +cat molecule/default/.molecule/test/ansible.log | grep ERROR +``` + +## 📊 Мониторинг производительности + +### Мониторинг ресурсов + +```bash +# Использование CPU и памяти +docker stats + +# Использование диска +df -h + +# Использование памяти +free -h + +# Процессы Docker +ps aux | grep docker +``` + +### Мониторинг сети + +```bash +# Статистика сети +docker network inspect labnet + +# Подключения к портам +netstat -tulpn | grep docker + +# Проверка DNS +nslookup docker.io +``` + +### Мониторинг логов + +```bash +# Логи системы +sudo journalctl -f + +# Логи Docker +sudo journalctl -u docker.service -f + +# Логи Ansible +tail -f /var/log/ansible.log +``` + +## 🔧 Диагностика ролей + +### Проверка синтаксиса + +```bash +# Lint проверка всех ролей +make role lint + +# Lint проверка конкретной роли +ansible-lint roles/my-role/ + +# Проверка синтаксиса YAML +ansible-playbook --syntax-check roles/my-role/tasks/main.yml +``` + +### Проверка переменных + +```bash +# Проверка переменных роли +ansible-inventory --list -i inventory/hosts.ini + +# Проверка переменных для конкретного хоста +ansible-inventory --host web1.example.com -i inventory/hosts.ini + +# Проверка переменных группы +ansible-inventory --host web_servers -i inventory/hosts.ini +``` + +### Тестирование ролей + +```bash +# Тестирование с verbose выводом +ansible-playbook -i inventory/hosts.ini site.yml -vvv + +# Тестирование конкретной роли +ansible-playbook -i inventory/hosts.ini site.yml --tags my-role + +# Тестирование с dry-run +ansible-playbook -i inventory/hosts.ini site.yml --check +``` + +## 🚨 Алерты и уведомления + +### Настройка алертов + +```bash +#!/bin/bash +# scripts/monitor.sh +# Скрипт мониторинга AnsibleLab + +# Проверка Docker +if ! docker info >/dev/null 2>&1; then + echo "❌ Docker не запущен" + # Отправка уведомления + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"❌ Docker не запущен в AnsibleLab"}' \ + $SLACK_WEBHOOK_URL +fi + +# Проверка образов +if ! docker images | grep -q inecs/ansible-lab; then + echo "❌ Образы AnsibleLab не найдены" + # Отправка уведомления + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"❌ Образы AnsibleLab не найдены"}' \ + $SLACK_WEBHOOK_URL +fi + +# Проверка preset'ов +if [ ! -d "molecule/presets" ]; then + echo "❌ Директория preset'ов не найдена" + # Отправка уведомления + curl -X POST -H 'Content-type: application/json' \ + --data '{"text":"❌ Директория preset'ов не найдена"}' \ + $SLACK_WEBHOOK_URL +fi + +echo "✅ Мониторинг завершен" +``` + +### Настройка cron для мониторинга + +```bash +# Добавление в crontab +crontab -e + +# Проверка каждые 5 минут +*/5 * * * * /path/to/scripts/monitor.sh + +# Проверка каждый час +0 * * * * /path/to/scripts/monitor.sh + +# Проверка каждый день в 9:00 +0 9 * * * /path/to/scripts/monitor.sh +``` + +## 📈 Метрики и отчеты + +### Сбор метрик + +```bash +#!/bin/bash +# scripts/collect-metrics.sh +# Сбор метрик AnsibleLab + +echo "📊 Сбор метрик AnsibleLab..." + +# Создание директории для метрик +mkdir -p metrics + +# Метрики Docker +echo "=== Docker Metrics ===" > metrics/docker.txt +docker info >> metrics/docker.txt +docker images >> metrics/docker.txt +docker ps -a >> metrics/docker.txt + +# Метрики системы +echo "=== System Metrics ===" > metrics/system.txt +df -h >> metrics/system.txt +free -h >> metrics/system.txt +uptime >> metrics/system.txt + +# Метрики Ansible +echo "=== Ansible Metrics ===" > metrics/ansible.txt +ansible --version >> metrics/ansible.txt +ansible-galaxy list >> metrics/ansible.txt + +# Метрики ролей +echo "=== Roles Metrics ===" > metrics/roles.txt +find roles/ -name "main.yml" -path "*/tasks/*" | wc -l >> metrics/roles.txt +ls -la roles/ >> metrics/roles.txt + +echo "✅ Метрики собраны" +``` + +### Генерация отчетов + +```bash +#!/bin/bash +# scripts/generate-report.sh +# Генерация отчета о состоянии AnsibleLab + +echo "📋 Генерация отчета..." + +# Создание директории для отчетов +mkdir -p reports + +# Отчет о Docker +cat > reports/docker-report.md << EOF +# Docker Report + +## Образы +\`\`\` +$(docker images | grep inecs/ansible-lab) +\`\`\` + +## Контейнеры +\`\`\` +$(docker ps -a) +\`\`\` + +## Сети +\`\`\` +$(docker network ls) +\`\`\` +EOF + +# Отчет о ролях +cat > reports/roles-report.md << EOF +# Roles Report + +## Количество ролей +$(find roles/ -name "main.yml" -path "*/tasks/*" | wc -l) + +## Список ролей +\`\`\` +$(find roles/ -name "main.yml" -path "*/tasks/*" | sed 's|roles/||; s|/tasks/main.yml||') +\`\`\` +EOF + +# Отчет о preset'ах +cat > reports/presets-report.md << EOF +# Presets Report + +## Количество preset'ов +$(ls -1 molecule/presets/*.yml | wc -l) + +## Список preset'ов +\`\`\` +$(ls -1 molecule/presets/*.yml | sed 's|molecule/presets/||g' | sed 's|\.yml||g') +\`\`\` +EOF + +echo "✅ Отчеты сгенерированы" +``` + +## 🔍 Отладка проблем + +### Общие проблемы + +#### 1. Docker не запускается + +```bash +# Проверка статуса Docker +sudo systemctl status docker + +# Запуск Docker +sudo systemctl start docker + +# Проверка логов +sudo journalctl -u docker.service +``` + +#### 2. Образы не собираются + +```bash +# Проверка builder'а +make docker diagnose + +# Сброс builder'а +make docker reset-builder + +# Очистка кеша +make docker clean +``` + +#### 3. Тесты не проходят + +```bash +# Проверка preset'ов +make presets list + +# Проверка инвентори +cat ${MOLECULE_EPHEMERAL_DIRECTORY}/inventory/hosts.ini + +# Проверка логов +docker logs ansible-controller +``` + +#### 4. Роли не работают + +```bash +# Проверка синтаксиса +make role lint + +# Проверка переменных +ansible-inventory --list -i inventory/hosts.ini + +# Тестирование с verbose +ansible-playbook -i inventory/hosts.ini site.yml -vvv +``` + +### Логи для отладки + +```bash +# Сбор всех логов +mkdir -p debug-logs + +# Логи Docker +docker info > debug-logs/docker-info.txt +docker images > debug-logs/docker-images.txt +docker ps -a > debug-logs/docker-containers.txt + +# Логи системы +df -h > debug-logs/disk-usage.txt +free -h > debug-logs/memory-usage.txt +ps aux > debug-logs/processes.txt + +# Логи Ansible +ansible --version > debug-logs/ansible-version.txt +ansible-galaxy list > debug-logs/ansible-galaxy.txt + +# Логи ролей +find roles/ -name "*.yml" -exec ansible-playbook --syntax-check {} \; > debug-logs/roles-syntax.txt +``` + +## 📊 Дашборд мониторинга + +### Простой дашборд + +```bash +#!/bin/bash +# scripts/dashboard.sh +# Простой дашборд мониторинга + +echo "📊 AnsibleLab Dashboard" +echo "==========================" + +# Статус Docker +if docker info >/dev/null 2>&1; then + echo "✅ Docker: Запущен" +else + echo "❌ Docker: Не запущен" +fi + +# Количество образов +IMAGES=$(docker images | grep inecs/ansible-lab | wc -l) +echo "📦 Образы: $IMAGES" + +# Количество ролей +ROLES=$(find roles/ -name "main.yml" -path "*/tasks/*" | wc -l) +echo "🎭 Роли: $ROLES" + +# Количество preset'ов +PRESETS=$(ls -1 molecule/presets/*.yml 2>/dev/null | wc -l) +echo "⚙️ Preset'ы: $PRESETS" + +# Использование диска +DISK=$(df -h . | tail -1 | awk '{print $5}') +echo "💾 Диск: $DISK" + +# Использование памяти +MEMORY=$(free -h | grep Mem | awk '{print $3 "/" $2}') +echo "🧠 Память: $MEMORY" + +echo "==========================" +``` + +### Веб-дашборд + +```html + + + + AnsibleLab Dashboard + + + + + +

📊 AnsibleLab Dashboard

+ +
+ + + + +``` + +## 🔧 Автоматизация мониторинга + +### Настройка мониторинга + +```bash +#!/bin/bash +# scripts/setup-monitoring.sh +# Настройка мониторинга AnsibleLab + +echo "🔧 Настройка мониторинга..." + +# Создание директорий +mkdir -p {scripts,metrics,reports,debug-logs} + +# Создание скрипта мониторинга +cat > scripts/monitor.sh << 'EOF' +#!/bin/bash +# Скрипт мониторинга AnsibleLab + +# Проверка Docker +if ! docker info >/dev/null 2>&1; then + echo "❌ Docker не запущен" + exit 1 +fi + +# Проверка образов +if ! docker images | grep -q inecs/ansible-lab; then + echo "❌ Образы AnsibleLab не найдены" + exit 1 +fi + +echo "✅ Мониторинг завершен" +EOF + +# Создание скрипта сбора метрик +cat > scripts/collect-metrics.sh << 'EOF' +#!/bin/bash +# Сбор метрик AnsibleLab + +echo "📊 Сбор метрик..." + +# Метрики Docker +docker info > metrics/docker-info.txt +docker images > metrics/docker-images.txt + +# Метрики системы +df -h > metrics/disk-usage.txt +free -h > metrics/memory-usage.txt + +echo "✅ Метрики собраны" +EOF + +# Создание скрипта генерации отчетов +cat > scripts/generate-report.sh << 'EOF' +#!/bin/bash +# Генерация отчета о состоянии AnsibleLab + +echo "📋 Генерация отчета..." + +# Отчет о Docker +cat > reports/docker-report.md << EOL +# Docker Report + +## Образы +\`\`\` +$(docker images | grep inecs/ansible-lab) +\`\`\` +EOL + +echo "✅ Отчеты сгенерированы" +EOF + +# Делаем скрипты исполняемыми +chmod +x scripts/*.sh + +echo "✅ Мониторинг настроен" +``` + +--- + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru diff --git a/docs/platform-support.md b/docs/platform-support.md new file mode 100644 index 0000000..a23c337 --- /dev/null +++ b/docs/platform-support.md @@ -0,0 +1,148 @@ +# Поддержка платформ в пресетах + +## Автор +Сергей Антропов +Сайт: https://devops.org.ru + +## Описание + +Начиная с версии 1.0, Molecule Template поддерживает указание конкретных платформ для хостов в пресетах. Это позволяет автоматически фильтровать хосты, которые не поддерживаются на текущей архитектуре системы. + +## Обязательные требования + +**Для Astra Linux и RedOS** во всех пресетах **обязательно** должно быть указано `supported_platforms: ["linux/amd64"]`, так как эти системы не поддерживают arm64 архитектуру. Без этого указания могут возникать ошибки при запуске на ARM-системах. + +## Как это работает + +### Определение платформы + +Система автоматически определяет архитектуру хоста при запуске: +- `x86_64` → `linux/amd64` +- `aarch64` / `arm64` → `linux/arm64` +- `armv7l` → `linux/arm/v7` + +### Синтаксис в пресетах + +В файлах пресетов (molecule/presets/*.yml) можно указать поле `supported_platforms` для каждого хоста: + +```yaml +hosts: + - name: ubuntu-test + family: ubuntu + groups: [test] + # Без supported_platforms - работает на всех платформах + publish: + - "8080:80" + + - name: astra-test + family: astra + groups: [test] + supported_platforms: ["linux/amd64"] # Только amd64 + publish: + - "8083:80" + + - name: multi-test + family: ubuntu + groups: [test] + supported_platforms: ["linux/amd64", "linux/arm64"] # Несколько платформ + publish: + - "8084:80" +``` + +### Правила фильтрации + +1. **Если `supported_platforms` не указано** - хост будет запущен на всех платформах +2. **Если `supported_platforms: ["linux/amd64"]`** - хост запустится только на amd64 +3. **Если `supported_platforms: ["linux/amd64", "linux/arm64"]`** - хост запустится на обеих платформах + +### Примеры использования + +#### Универсальный хост (работает везде) +```yaml +- name: universal-test + family: ubuntu + groups: [test] + # supported_platforms не указано = работает на всех платформах +``` + +#### Только для amd64 +```yaml +- name: amd64-only-test + family: astra + groups: [test] + supported_platforms: ["linux/amd64"] +``` + +#### Для нескольких платформ +```yaml +- name: multi-platform-test + family: debian + groups: [test] + supported_platforms: ["linux/amd64", "linux/arm64"] +``` + +## Реализация + +Фильтрация происходит в файле `molecule/default/create.yml`: + +1. Система определяет текущую платформу +2. Загружается пресет +3. Хосты фильтруются по `supported_platforms` +4. Отображается количество хостов для текущей платформы + +```yaml +# Фильтрация хостов по поддерживаемым платформам +- 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 +``` + +## Текущее состояние + +### Хосты с ограничениями по платформе + +- **Astra Linux** - только `linux/amd64` (нет нативной поддержки arm64) + - Во всех пресетах имеет `supported_platforms: ["linux/amd64"]` + - Базовый образ `registry.astralinux.ru/library/astra/ubi17:1.7.6.uu2` доступен только для amd64 + +- **RedOS** - только `linux/amd64` (нет нативной поддержки arm64) + - Во всех пресетах имеет `supported_platforms: ["linux/amd64"]` + - Базовый образ `registry.red-soft.ru/ubi7/ubi` доступен только для amd64 + +**Важно:** При запуске на arm64 системе эти хосты будут автоматически исключены из списка, что предотвратит ошибки при сборке и запуске контейнеров. + +### Универсальные хосты + +Следующие системы работают на всех платформах: +- Ubuntu 20.04, 22.04, 24.04 +- Debian 9, 10, 11, 12 +- Alt Linux +- CentOS 7, 8, 9 +- RHEL +- AlmaLinux +- Rocky Linux + +## Примеры запуска + +### На amd64 (все 9 хостов) +```bash +make role test all-images +# Platform linux/amd64: 9 hosts will be deployed +``` + +### На arm64 (7 хостов, без Astra и RedOS) +```bash +make role test all-images +# Platform linux/arm64: 7 hosts will be deployed +``` + +## Дополнительная информация + +- Все образы загружаются с принудительным указанием платформы +- Система автоматически адаптирует количество контейнеров под текущую платформу +- Информация о количестве хостов отображается при запуске + diff --git a/docs/presets-by-os.md b/docs/presets-by-os.md new file mode 100644 index 0000000..92e251a --- /dev/null +++ b/docs/presets-by-os.md @@ -0,0 +1,183 @@ +# Пресеты по операционным системам + +Этот документ описывает специализированные пресеты для тестирования на конкретных версиях операционных систем. + +## 🐧 Ubuntu пресеты + +### ubuntu-all.yml +**Описание:** Пресет со всеми версиями Ubuntu (20.04, 22.04, 24.04) +**Хосты:** 6 хостов (по 2 на каждую версию) +**Порты:** 8020-8025 +**Использование:** +```bash +make role test ubuntu-all +``` + +### ubuntu20.yml +**Описание:** Пресет для Ubuntu 20.04 LTS +**Хосты:** 3 хоста (web, db, app) +**Порты:** 8020-8022 +**Использование:** +```bash +make role test ubuntu20 +``` + +### ubuntu22.yml +**Описание:** Пресет для Ubuntu 22.04 LTS +**Хосты:** 3 хоста (web, db, app) +**Порты:** 8220-8222 +**Использование:** +```bash +make role test ubuntu22 +``` + +### ubuntu24.yml +**Описание:** Пресет для Ubuntu 24.04 LTS +**Хосты:** 3 хоста (web, db, app) +**Порты:** 8240-8242 +**Использование:** +```bash +make role test ubuntu24 +``` + +## 🐧 Debian пресеты + +### debian-all.yml +**Описание:** Пресет со всеми версиями Debian (9, 10, 11, 12) +**Хосты:** 8 хостов (по 2 на каждую версию) +**Порты:** 9009-9016 +**Использование:** +```bash +make role test debian-all +``` + +### debian9.yml +**Описание:** Пресет для Debian 9 Stretch +**Хосты:** 3 хоста (web, db, app) +**Порты:** 9090-9092 +**Использование:** +```bash +make role test debian9 +``` + +### debian10.yml +**Описание:** Пресет для Debian 10 Buster +**Хосты:** 3 хоста (web, db, app) +**Порты:** 9100-9102 +**Использование:** +```bash +make role test debian10 +``` + +### debian11.yml +**Описание:** Пресет для Debian 11 Bullseye +**Хосты:** 3 хоста (web, db, app) +**Порты:** 9110-9112 +**Использование:** +```bash +make role test debian11 +``` + +### debian12.yml +**Описание:** Пресет для Debian 12 Bookworm +**Хосты:** 3 хоста (web, db, app) +**Порты:** 9120-9122 +**Использование:** +```bash +make role test debian12 +``` + +## 🐧 CentOS пресеты + +### centos-all.yml +**Описание:** Пресет со всеми версиями CentOS (7, 8, 9) +**Хосты:** 6 хостов (по 2 на каждую версию) +**Порты:** 7007-7012 +**Использование:** +```bash +make role test centos-all +``` + +### centos7.yml +**Описание:** Пресет для CentOS 7 +**Хосты:** 3 хоста (web, db, app) +**Порты:** 7070-7072 +**Использование:** +```bash +make role test centos7 +``` + +### centos8.yml +**Описание:** Пресет для CentOS 8 +**Хосты:** 3 хоста (web, db, app) +**Порты:** 7080-7082 +**Использование:** +```bash +make role test centos8 +``` + +### centos9.yml +**Описание:** Пресет для CentOS 9 Stream +**Хосты:** 3 хоста (web, db, app) +**Порты:** 7090-7092 +**Использование:** +```bash +make role test centos9 +``` + +## 📊 Сравнение пресетов + +| Пресет | ОС | Версии | Хостов | Порты | Назначение | +|--------|----|---------|---------|--------|------------| +| ubuntu-all | Ubuntu | 20.04, 22.04, 24.04 | 6 | 8020-8025 | Тестирование всех версий Ubuntu | +| debian-all | Debian | 9, 10, 11, 12 | 8 | 9009-9016 | Тестирование всех версий Debian | +| centos-all | CentOS | 7, 8, 9 | 6 | 7007-7012 | Тестирование всех версий CentOS | +| ubuntu20 | Ubuntu | 20.04 | 3 | 8020-8022 | Тестирование Ubuntu 20.04 | +| ubuntu22 | Ubuntu | 22.04 | 3 | 8220-8222 | Тестирование Ubuntu 22.04 | +| ubuntu24 | Ubuntu | 24.04 | 3 | 8240-8242 | Тестирование Ubuntu 24.04 | +| debian9 | Debian | 9 | 3 | 9090-9092 | Тестирование Debian 9 | +| debian10 | Debian | 10 | 3 | 9100-9102 | Тестирование Debian 10 | +| debian11 | Debian | 11 | 3 | 9110-9112 | Тестирование Debian 11 | +| debian12 | Debian | 12 | 3 | 9120-9122 | Тестирование Debian 12 | +| centos7 | CentOS | 7 | 3 | 7070-7072 | Тестирование CentOS 7 | +| centos8 | CentOS | 8 | 3 | 7080-7082 | Тестирование CentOS 8 | +| centos9 | CentOS | 9 | 3 | 7090-7092 | Тестирование CentOS 9 | + +## 🎯 Рекомендации по использованию + +### Для разработки: +- Используйте `ubuntu22` или `debian12` для быстрого тестирования +- Используйте `ubuntu-all` для проверки совместимости с разными версиями Ubuntu + +### Для продакшена: +- Используйте `centos-all` для проверки RHEL-совместимых систем +- Используйте `debian-all` для проверки Debian-совместимых систем + +### Для CI/CD: +- Используйте отдельные пресеты для изолированного тестирования +- Используйте `*-all` пресеты для комплексной проверки совместимости + +## 🔧 Настройка портов + +Все пресеты используют уникальные диапазоны портов: + +### Ubuntu пресеты: +- **ubuntu-all:** 8020-8025 (все версии) +- **ubuntu20:** 8020-8022 +- **ubuntu22:** 8220-8222 +- **ubuntu24:** 8240-8242 + +### Debian пресеты: +- **debian-all:** 9009-9016 (все версии) +- **debian9:** 9090-9092 +- **debian10:** 9100-9102 +- **debian11:** 9110-9112 +- **debian12:** 9120-9122 + +### CentOS пресеты: +- **centos-all:** 7007-7012 (все версии) +- **centos7:** 7070-7072 +- **centos8:** 7080-7082 +- **centos9:** 7090-7092 + +Это позволяет запускать несколько пресетов одновременно без конфликтов портов. diff --git a/docs/site-yml-guide.md b/docs/site-yml-guide.md new file mode 100644 index 0000000..e95f1ae --- /dev/null +++ b/docs/site-yml-guide.md @@ -0,0 +1,248 @@ +# Руководство по файлу site.yml + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## 📋 Описание + +Файл `molecule/default/site.yml` является **универсальным playbook'ом для тестирования Ansible ролей** в контейнерах. Этот файл отвечает за подготовку окружения и установку необходимых утилит внутри контейнеров при запуске тестов. + +## 🎯 Назначение + +### Основные функции: + +1. **Обновление пакетов** в контейнерах при запуске тестов +2. **Установка common tools** для корректной работы тестов +3. **Подготовка окружения** для тестирования ролей +4. **Импорт roles/deploy.yml** для запуска ролей + +## 🏗️ Структура файла + +### 1. Подготовка окружения для тестирования + +```yaml +- name: Подготовка окружения для тестирования + hosts: all + become: true + tasks: + # Задачи подготовки... +``` + +**Что делает:** +- Обновляет кеш пакетов для всех поддерживаемых ОС +- Устанавливает необходимые утилиты +- Настраивает пользователя для тестирования +- Создает рабочие директории + +### 2. Импорт deploy.yml + +```yaml +- import_playbook: ../../roles/deploy.yml +``` + +**Что делает:** +- Импортирует `roles/deploy.yml` для запуска ролей +- Разделяет логику: `site.yml` - подготовка, `deploy.yml` - роли +- Обеспечивает единую точку управления ролями + +## 🐧 Поддерживаемые ОС + +### Debian/Ubuntu +- **Менеджер пакетов:** `apt` +- **Обновление:** `apt update` +- **Утилиты:** `curl`, `jq`, `ca-certificates`, `iproute2`, `iputils-ping`, `procps`, `net-tools`, `sudo`, `vim`, `wget`, `unzip`, `git` + +### RHEL/CentOS/AlmaLinux/Rocky +- **Менеджер пакетов:** `yum` +- **Обновление:** `yum update_cache` +- **Утилиты:** `curl`, `jq`, `ca-certificates`, `iproute`, `iputils`, `procps-ng`, `net-tools`, `sudo`, `vim`, `wget`, `unzip`, `git` + +### Alt Linux +- **Менеджер пакетов:** `apt` (специальная версия) +- **Обновление:** `apt update` +- **Утилиты:** `curl`, `jq`, `ca-certificates`, `iproute2`, `iputils`, `procps`, `net-tools`, `sudo`, `vim`, `wget`, `unzip`, `git` + +## 🏷️ Теги (Tags) + +### setup +- Обновление пакетов +- Установка утилит +- Настройка пользователей +- Создание директорий + +### update +- Обновление кеша пакетов +- Обновление списка пакетов + +### tools +- Установка common tools +- Установка системных утилит + +### python +- Установка Python 3 +- Установка pip +- Установка venv + +### user +- Создание тестового пользователя +- Настройка домашней директории + +### sudo +- Настройка sudo для тестового пользователя +- Конфигурация прав доступа + +### directory +- Создание рабочих директорий +- Настройка прав доступа + +### roles +- Запуск тестирования ролей +- Выполнение функциональных тестов + +### test +- Тестирование функциональности +- Проверка работоспособности + +## 🚀 Использование + +### Запуск полного тестирования +```bash +make role test +``` + +### Запуск только подготовки окружения +```bash +make role test --tags setup +``` + +### Запуск только обновления пакетов +```bash +make role test --tags update +``` + +### Запуск только установки утилит +```bash +make role test --tags tools +``` + +### Запуск только тестирования ролей +```bash +make role test --tags roles +``` + +## 🔧 Настройка + +### Переменные окружения + +```bash +# Настройка тестового пользователя +export TEST_USER=testuser + +# Настройка рабочей директории +export TEST_DIR=/tmp/ansible-test + +# Настройка прав доступа +export TEST_MODE=0755 +``` + +### Кастомизация утилит + +Для добавления дополнительных утилит отредактируйте соответствующие секции: + +```yaml +# Для Debian/Ubuntu +- name: Install common tools (Debian/Ubuntu) + apt: + name: + - curl + - jq + - your-custom-tool # Добавьте сюда + state: present +``` + +## 🐛 Troubleshooting + +### Проблема: Ошибка обновления пакетов +**Решение:** Проверьте доступность репозиториев и интернет-соединение + +### Проблема: Не удается установить утилиты +**Решение:** Проверьте названия пакетов для конкретной ОС + +### Проблема: Ошибка создания пользователя +**Решение:** Проверьте права доступа и существование пользователя + +### Проблема: Ошибка настройки sudo +**Решение:** Проверьте синтаксис файла sudoers + +## 📊 Мониторинг + +### Логи выполнения +```bash +# Просмотр логов тестирования +make role test 2>&1 | tee test.log + +# Фильтрация по тегам +grep "TASK \[.*\]" test.log +``` + +### Проверка установленных утилит +```bash +# В контейнере +which curl jq vim git +``` + +### Проверка пользователя +```bash +# В контейнере +id testuser +sudo -l -U testuser +``` + +## 🔄 Автоматическое обновление + +Файл `site.yml` автоматически обновляется при добавлении новых ролей: + +```bash +# Автоматическое обновление +make update-playbooks +``` + +**Что происходит:** +1. Обнаруживаются все роли в директории `roles/` +2. Обновляется секция "Тестирование всех ролей" +3. Добавляются новые роли в список + +## 📝 Примеры использования + +### Тестирование конкретной роли +```bash +# Тестирование только роли ping +make role test minimal ping +``` + +### Тестирование с конкретным preset'ом +```bash +# Тестирование с preset'ом performance +make role test performance +``` + +### Отладка проблем +```bash +# Запуск с подробным выводом +make role test --verbose +``` + +## 🎯 Лучшие практики + +1. **Всегда используйте теги** для разделения задач +2. **Проверяйте совместимость** утилит с ОС +3. **Тестируйте на разных образах** перед коммитом +4. **Используйте idempotent задачи** для стабильности +5. **Документируйте изменения** в комментариях + +## 🔗 Связанные файлы + +- `molecule/default/molecule.yml` - конфигурация Molecule +- `roles/deploy.yml` - playbook для продакшн развертывания +- `inventory/hosts.ini` - инвентори для тестирования +- `Makefile` - команды для запуска тестов diff --git a/docs/testing-vs-deployment.md b/docs/testing-vs-deployment.md new file mode 100644 index 0000000..5836381 --- /dev/null +++ b/docs/testing-vs-deployment.md @@ -0,0 +1,99 @@ +# Тестирование vs Развертывание + +## Автор: Сергей Антропов +## Сайт: https://devops.org.ru + +## Различие между тестированием и развертыванием + +### 🧪 Тестирование (molecule) + +**Команда:** `make role test [preset]` + +**Использует:** +- Динамический inventory, создаваемый в `molecule/default/create.yml` +- Preset файлы из `molecule/presets/` +- Docker контейнеры для изоляции тестов +- Временные контейнеры (u1, u2, u3) + +**Процесс:** +1. Загружается preset конфигурация +2. Создаются Docker контейнеры согласно preset +3. Генерируется временный inventory файл +4. Запускаются тесты на контейнерах +5. Контейнеры удаляются после тестов + +**Пример:** +```bash +make role test standart # Тестирование в 3 контейнерах +make role test minimal # Тестирование в 1 контейнере +``` + +### 🚀 Развертывание (deploy) + +**Команда:** `make role deploy` + +**Использует:** +- Статический inventory файл `inventory/hosts.ini` +- Реальные серверы +- SSH подключение + +**Процесс:** +1. Проверяется наличие `inventory/hosts.ini` +2. Показывается содержимое inventory +3. Запускается dry-run (--check) +4. Запрашивается подтверждение +5. Выполняется развертывание на реальные серверы + +**Пример:** +```bash +make role deploy # Развертывание на реальные серверы +``` + +## Конфигурация + +### Для тестирования +- Preset файлы: `molecule/presets/*.yml` +- Динамический inventory создается в `create.yml` +- Контейнеры: Docker + +### Для развертывания +- Inventory файл: `inventory/hosts.ini` +- Серверы: Реальные хосты +- Подключение: SSH + +## Примеры конфигурации + +### Preset для тестирования (molecule/presets/standart.yml) +```yaml +hosts: + - name: u1 + family: debian + groups: [test] + - name: u2 + family: rhel + groups: [test] + - name: u3 + family: debian + groups: [test] +``` + +### Inventory для развертывания (inventory/hosts.ini) +```ini +[web_servers] +web1 ansible_host=192.168.1.10 ansible_user=ubuntu +web2 ansible_host=192.168.1.11 ansible_user=ubuntu + +[db_servers] +db1 ansible_host=192.168.1.20 ansible_user=ubuntu + +[all:vars] +ansible_ssh_private_key_file=~/.ssh/id_rsa +ansible_ssh_common_args='-o StrictHostKeyChecking=no' +``` + +## Рекомендации + +1. **Сначала тестируйте** с помощью `make role test [preset]` +2. **Затем развертывайте** с помощью `make role deploy` +3. **Используйте разные preset'ы** для разных сценариев тестирования +4. **Настройте inventory** для ваших реальных серверов diff --git a/docs/universal-testing.md b/docs/universal-testing.md new file mode 100644 index 0000000..6aa02cd --- /dev/null +++ b/docs/universal-testing.md @@ -0,0 +1,282 @@ +# Универсальная система тестирования Ansible ролей + +## Обзор + +Эта система предоставляет универсальную среду для тестирования и деплоя Ansible ролей с поддержкой различных типов контейнеров, автоматической генерации инвентаря и интеграции с Ansible Vault. + +## Основные возможности + +### 🐳 Типы контейнеров + +#### Systemd контейнеры (по умолчанию) +- Полная поддержка systemd сервисов +- Работа как виртуальные машины +- Подходит для тестирования ролей + +#### DinD (Docker-in-Docker) +- Изолированный Docker daemon +- Подходит для тестирования Docker Compose +- Полная изоляция от хостового Docker + +#### DOoD (Docker-out-of-Docker) +- Доступ к хостовому Docker daemon +- Быстрое тестирование +- Подходит для CI/CD + +### 📋 Preset'ы + +#### etcd-patroni +- Кластер etcd (5 узлов) +- Кластер PostgreSQL с Patroni (3 узла) +- HAProxy для балансировки +- DinD узел для тестирования + +#### performance +- 5 серверов приложений +- 3 узла базы данных +- 3 узла кэша Redis +- Load balancer +- DinD узел для тестирования + +#### security +- Bastion хосты +- Внутренние серверы +- Изолированная база данных +- Мониторинг и логирование +- Firewall компоненты +- DOoD узел для тестирования + +#### multi-os +- Тестирование на разных ОС +- Ubuntu, Debian, RHEL, CentOS +- Смешанные конфигурации +- DinD узел для тестирования + +### 🔐 Ansible Vault интеграция + +- Автоматическая расшифровка перед тестированием +- Безопасное хранение секретов +- Автоматическая повторная шифровка после тестирования +- Поддержка множественных vault'ов + +## Использование + +### Базовые команды + +```bash +# Показать все preset'ы +make preset-list + +# Информация о preset'е +make preset-info PRESET=etcd-patroni + +# Тестирование с preset'ом +make preset-test PRESET=etcd-patroni + +# Типы контейнеров +make container-types + +# Информация о контейнерах +make container-info + +# Проверка vault файлов +make vault-check + +# Поиск секретов +make vault-scan +``` + +### Тестирование ролей + +```bash +# С default preset +make role test + +# С конкретным preset'ом +make role test etcd-patroni +make role test performance +make role test security +make role test multi-os +``` + +### Работа с Ansible Vault + +```bash +# Создать файл секретов +make vault create + +# Редактировать секреты +make vault edit + +# Показать секреты +make vault show + +# Зашифровать файл +make vault encrypt + +# Расшифровать файл +make vault decrypt +``` + +## Структура проекта + +``` +. +├── molecule/ +│ ├── default/ +│ │ ├── create.yml # Создание контейнеров +│ │ ├── destroy.yml # Удаление контейнеров +│ │ ├── converge.yml # Запуск плейбуков +│ │ └── verify.yml # Проверка результатов +│ └── presets/ +│ ├── etcd-patroni.yml +│ ├── performance.yml +│ ├── security.yml +│ └── multi-os.yml +├── files/ +│ ├── requirements.yml +│ └── playbooks/ +│ └── site.yml +├── vault/ +│ └── secrets.yml +└── Makefile +``` + +## Создание собственных preset'ов + +### Пример preset'а + +```yaml +--- +# Пресет для тестирования кластера etcd + PostgreSQL + Patroni +# Автор: Сергей Антропов +# Сайт: 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: + # Systemd узлы + - name: server1 + family: debian + groups: [servers, web] + publish: ["80:80"] + + # DinD узел + - name: app-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080"] + + # DOoD узел + - name: docker-secure + type: dood + family: debian + groups: [docker, security] + publish: ["8081:8081"] + env: + DOCKER_HOST: "unix:///var/run/docker.sock" +``` + +### Параметры хостов + +- `name` - имя хоста +- `family` - семейство ОС (debian, rhel, ubuntu, centos) +- `type` - тип контейнера (dind, dood) +- `groups` - группы для инвентаря +- `publish` - порты для публикации +- `env` - переменные окружения +- `volumes` - дополнительные тома +- `capabilities` - дополнительные возможности + +## Лучшие практики + +### 1. Использование групп + +```yaml +hosts: + - name: web1 + groups: [web, servers, production] + - name: db1 + groups: [database, servers, production] +``` + +### 2. Безопасность + +```yaml +# Используйте Ansible Vault для секретов +vault_targets: + - /ansible/vault/secrets.yml + - /ansible/files/playbooks/group_vars/*/vault.yml + - /ansible/files/playbooks/host_vars/*/vault.yml +``` + +### 3. Тестирование + +```yaml +# Проверяйте различные сценарии +- name: Test web servers + hosts: web + tasks: + - name: Check nginx status + systemd: + name: nginx + state: started +``` + +## Troubleshooting + +### Проблемы с контейнерами + +```bash +# Проверить статус контейнеров +make container-info + +# Очистить Docker ресурсы +make docker clean +``` + +### Проблемы с Vault + +```bash +# Проверить vault файлы +make vault-check + +# Найти потенциальные секреты +make vault-scan +``` + +### Проблемы с preset'ами + +```bash +# Показать все preset'ы +make preset-list + +# Информация о preset'е +make preset-info PRESET=имя_пресета +``` + +## Заключение + +Универсальная система тестирования Ansible ролей предоставляет мощные инструменты для тестирования ролей в различных сценариях. Используйте preset'ы для быстрого создания тестовых сред, различные типы контейнеров для изоляции и Ansible Vault для безопасности. + +Для получения дополнительной информации используйте: +- `make help` - общая справка +- `make role` - команды для ролей +- `make molecule` - команды Molecule +- `make vault` - команды Vault + diff --git a/docs/vault-guide.md b/docs/vault-guide.md new file mode 100644 index 0000000..cf1e46f --- /dev/null +++ b/docs/vault-guide.md @@ -0,0 +1,249 @@ +# Руководство по работе с Ansible Vault + +## Автор +Сергей Антропов +Сайт: https://devops.org.ru + +## Описание + +Это руководство описывает работу с зашифрованными секретами в Ansible Vault для проекта AnsibleTemplate. + +## Безопасность + +⚠️ **ВАЖНО**: Зашифрованные файлы содержат секретные данные и должны храниться в безопасности! + +## Команды для работы с Vault + +### Инициализация Vault + +```bash +# Создание файла с паролем для vault +make vault init +``` + +### Основные операции + +```bash +# Создание нового файла секретов +make vault create + +# Редактирование существующих секретов +make vault edit + +# Просмотр содержимого секретов +make vault show + +# Шифрование существующего файла +make vault encrypt + +# Расшифровка файла +make vault decrypt + +# Смена пароля шифрования +make vault rekey + +# Удаление файла секретов +make vault delete + +# Проверка vault файлов +make vault check +``` + +## Структура файлов + +``` +vault/ +├── .vault # Файл с паролем для vault (НЕ коммитится в git) +├── secrets.yml # Зашифрованный файл с секретами +└── secrets/ # Директория для незашифрованных секретов + └── *.yml # Незашифрованные файлы секретов +``` + +## Примеры использования + +### 1. Создание нового файла секретов + +```bash +# Создать новый файл +make vault create +# Введите имя файла (без .yml): my-secrets +``` + +### 2. Редактирование секретов + +```bash +# Редактировать существующий файл +make vault edit +# Введите имя файла (без .yml): secrets +``` + +### 3. Просмотр секретов + +```bash +# Показать содержимое файла +make vault show +# Введите имя файла (без .yml): secrets +``` + +### 4. Шифрование файла + +```bash +# Зашифровать незашифрованный файл +make vault encrypt +# Введите имя файла (без .yml): secrets +``` + +### 5. Расшифровка файла + +```bash +# Расшифровать файл для редактирования +make vault decrypt +# Введите имя файла (без .yml): secrets +``` + +## Использование в Playbook + +### Передача пароля vault + +```bash +# Запуск playbook с паролем vault +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --ask-vault-pass + +# Использование файла с паролем +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --vault-password-file vault/.vault +``` + +### Переменные из vault + +```yaml +# В playbook +- name: "Использование секретов из vault" + hosts: all + vars_files: + - vault/secrets.yml + tasks: + - name: "Использование SSH ключа" + authorized_key: + user: "{{ devops_user.name }}" + key: "{{ devops_ssh_keys.public_key }}" +``` + +## Безопасность и лучшие практики + +### 1. Защита пароля vault + +```bash +# Установка правильных прав на файл пароля +chmod 600 vault/.vault + +# Добавление в .gitignore +echo "vault/.vault" >> .gitignore +``` + +### 2. Ротация паролей + +```bash +# Смена пароля vault +make vault rekey +# Введите имя файла (без .yml): secrets +``` + +### 3. Резервное копирование + +```bash +# Создание резервной копии зашифрованного файла +cp vault/secrets.yml vault/secrets.yml.backup + +# Создание резервной копии пароля +cp vault/.vault vault/.vault.backup +``` + +### 4. Проверка целостности + +```bash +# Проверка vault файлов +make vault check +``` + +## Troubleshooting + +### Проблема: "Unable to read source file" + +```bash +# Убедитесь, что файл существует +ls -la vault/*.yml + +# Проверьте права доступа +ls -la vault/ +``` + +### Проблема: "Vault password not provided" + +```bash +# Убедитесь, что файл .vault существует +ls -la vault/.vault + +# Проверьте содержимое файла +cat vault/.vault +``` + +### Проблема: "Invalid vault password" + +```bash +# Проверьте пароль в файле .vault +cat vault/.vault + +# Пересоздайте файл пароля +rm vault/.vault +make vault init +``` + +## Интеграция с CI/CD + +### GitHub Actions + +```yaml +# .github/workflows/deploy.yml +- name: "Deploy with Vault" + run: | + echo "${{ secrets.VAULT_PASSWORD }}" > vault/.vault + ansible-playbook -i inventory/hosts.ini roles/deploy.yml --vault-password-file vault/.vault +``` + +### GitLab CI + +```yaml +# .gitlab-ci.yml +deploy: + script: + - echo "$VAULT_PASSWORD" > vault/.vault + - ansible-playbook -i inventory/hosts.ini roles/deploy.yml --vault-password-file vault/.vault +``` + +## Мониторинг и логирование + +### Проверка статуса vault + +```bash +# Проверка всех vault файлов +make vault check + +# Проверка конкретного файла +ansible-vault view vault/secrets.yml --vault-password-file vault/.vault +``` + +### Логирование операций + +```bash +# Включение подробного логирования +export ANSIBLE_VERBOSITY=4 + +# Запуск с логированием +ansible-playbook -i inventory/hosts.ini roles/deploy.yml --vault-password-file vault/.vault -vvv +``` + +## Поддержка + +- 📧 Email: через сайт https://devops.org.ru +- 📖 Документация: `docs/` +- 🧪 Тесты: `roles/*/tests/` diff --git a/inventory/hosts b/inventory/hosts deleted file mode 100644 index a4a29bb..0000000 --- a/inventory/hosts +++ /dev/null @@ -1 +0,0 @@ -[all] diff --git a/inventory/hosts.ini b/inventory/hosts.ini new file mode 100644 index 0000000..c20a392 --- /dev/null +++ b/inventory/hosts.ini @@ -0,0 +1,16 @@ +# Инвентори для развертывания на реальные серверы +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Примеры серверов (замените на ваши реальные серверы) +[web_servers] +# web1 ansible_host=192.168.1.10 ansible_user=ubuntu +# web2 ansible_host=192.168.1.11 ansible_user=ubuntu + +[db_servers] +# db1 ansible_host=192.168.1.20 ansible_user=ubuntu + +[all:vars] +# Общие переменные для всех серверов +ansible_ssh_private_key_file=~/.ssh/id_rsa +ansible_ssh_common_args='-o StrictHostKeyChecking=no' \ No newline at end of file diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 749dcda..ea530f3 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -1,6 +1,75 @@ --- -- name: Converge - hosts: all - vars_files: - - ../../vars/secrets.yml - roles: \ No newline at end of file +- 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: + - /workspace/vault/secrets.yml + - /workspace/files/playbooks/group_vars/*/vault.yml + - /workspace/files/playbooks/host_vars/*/vault.yml + - /workspace/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 /workspace/requirements.yml --force --no-deps --upgrade >/dev/null 2>&1 || true" + + - 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 + ' + + - 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 + " + + - 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 \ No newline at end of file diff --git a/molecule/default/create.yml b/molecule/default/create.yml new file mode 100644 index 0000000..c405b91 --- /dev/null +++ b/molecule/default/create.yml @@ -0,0 +1,284 @@ +--- +- 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 + 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:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + hosts: + - name: u1 + family: debian + 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: 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) }}" + + - name: Display filtered hosts + debug: + msg: "Platform {{ ansible_architecture }}: {{ hosts | length }} hosts will be deployed" + + - name: Ensure network exists + community.docker.docker_network: + name: "{{ docker_network }}" + state: present + + # SYSTEMD nodes + - name: Pull systemd images with correct platform + command: "docker pull --platform {{ ansible_architecture }} {{ 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: pull_result + ignore_errors: yes + + - name: Display pull results + debug: + msg: "Pulled {{ item.item.name }}: {{ 'OK' if (item.rc is defined and item.rc == 0) else 'SKIPPED (not available for this platform)' }}" + loop: "{{ pull_result.results | default([]) }}" + loop_control: + label: "{{ item.item.name }}" + + - 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({}) }}" + # Специальные настройки для Astra Linux и RedOS (для совместимости с amd64 базовыми образами) + security_opts: "{{ ['seccomp=unconfined', 'apparmor=unconfined'] if item.family in ['astra', 'redos'] else [] }}" + platform: "{{ 'linux/amd64' if item.family in ['astra', 'redos'] else omit }}" + 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: 5 + when: hosts | length > 0 + + # Создание tmp директории в контейнерах + - name: Create Ansible tmp directory in containers + community.docker.docker_container_exec: + container: "{{ item.name }}" + command: "mkdir -p /tmp/.ansible-tmp && chmod 755 /tmp/.ansible-tmp" + loop: "{{ hosts | selectattr('type','undefined') | list }}" + loop_control: { label: "{{ item.name }}" } + when: item.family is defined and images[item.family] is defined + ignore_errors: true + retries: 3 + delay: 2 + + # DinD nodes + - 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 + 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) + 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 + 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 }}" + + # Render inventory + - name: Render inventory ini + set_fact: + inv_content: | + [all:vars] + ansible_connection=community.docker.docker + 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 для остальных хостов #} + [unmatched_hosts:vars] + ansible_python_interpreter=auto_silent + + - name: Write inventory file + copy: + dest: "{{ generated_inventory }}" + content: "{{ inv_content }}" + 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 }} \ No newline at end of file diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml index 82979c7..f319182 100644 --- a/molecule/default/destroy.yml +++ b/molecule/default/destroy.yml @@ -1,8 +1,83 @@ -- name: Destroy containers on interrupt - hosts: localhost +--- +- 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: Ensure containers are destroyed - docker_container: + - name: Load preset configuration + include_vars: "{{ preset_file }}" + when: preset_file is file + ignore_errors: true + + - name: Stop and remove containers + community.docker.docker_container: name: "{{ item.name }}" state: absent - loop: "{{ molecule_yml.platforms }}" \ No newline at end of file + force_kill: true + cleanup: true + loop: "{{ hosts }}" + loop_control: { label: "{{ item.name }}" } + ignore_errors: true + + - name: Force remove any remaining containers + shell: | + docker ps -a --filter "name={{ item.name }}" --format "{{ '{{' }}.ID{{ '}}' }}" | xargs -r docker rm -f + loop: "{{ hosts }}" + loop_control: { label: "{{ item.name }}" } + ignore_errors: true + + - name: Remove DinD volumes + community.docker.docker_volume: + name: "{{ item.name }}-docker" + state: absent + loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}" + 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 + + - name: Force cleanup all project containers + shell: | + # Удаляем все контейнеры из загруженного пресета + {% for host in hosts %} + docker ps -a --filter "name={{ host.name }}" --format "{{ '{{' }}.ID{{ '}}' }}" | xargs -r docker rm -f 2>/dev/null || true + {% endfor %} + # Удаляем все контейнеры с образами ansible-lab + docker ps -a --filter "ancestor=inecs/ansible-lab" --format "{{ '{{' }}.ID{{ '}}' }}" | xargs -r docker rm -f 2>/dev/null || true + # Удаляем все контейнеры с сетью labnet + docker ps -a --filter "network=labnet" --format "{{ '{{' }}.ID{{ '}}' }}" | xargs -r docker rm -f 2>/dev/null || true + ignore_errors: true + vars: + # Используем переменную hosts из загруженного пресета + hosts: "{{ hosts }}" + + - 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 }} \ No newline at end of file diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index f374694..10213ac 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -1,61 +1,73 @@ --- -dependency: - name: galaxy - enabled: false - options: - requirements-file: requirements.yml +# Универсальная конфигурация Molecule +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru driver: name: docker platforms: + # Платформы будут созданы динамически через preset файлы + # Поддержка собственных образов AnsibleLab + - name: placeholder + image: ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy + pre_build_image: true + # Собственные образы (будут использоваться через presets) + - name: ansible-controller + image: inecs/ansible-lab:ansible-controller-latest + pre_build_image: true + - name: alt-linux + image: inecs/ansible-lab:alt-linux-latest + pre_build_image: true + - name: astra-linux + image: inecs/ansible-lab:astra-linux-latest + pre_build_image: true + - name: redos + image: inecs/ansible-lab:redos-latest + pre_build_image: true + - name: rhel + image: inecs/ansible-lab:rhel-latest + pre_build_image: true - name: centos - image: "inecs/ansible:centos" - privileged: true + image: inecs/ansible-lab:centos-latest + pre_build_image: true + - name: alma + image: inecs/ansible-lab:alma-latest + pre_build_image: true + - name: rocky + image: inecs/ansible-lab:rocky-latest pre_build_image: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:ro - - /var/run/docker.sock:/var/run/docker.sock - tmpfs: - - /tmp - - /run - name: ubuntu - image: "inecs/ansible:ubuntu" - privileged: true + image: inecs/ansible-lab:ubuntu-latest + pre_build_image: true + - name: debian + image: inecs/ansible-lab:debian-latest pre_build_image: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:ro - - /var/run/docker.sock:/var/run/docker.sock - tmpfs: - - /tmp - - /run provisioner: name: ansible - connection_options: - ansible_connection: docker - ansible_user: root + config_options: + defaults: + stdout_callback: yaml + remote_tmp: /tmp/.ansible-tmp + interpreter_python: auto_silent env: - ANSIBLE_PYTHON_INTERPRETER: /usr/bin/python3 - lint: - name: ansible-lint + ANSIBLE_STDOUT_CALLBACK: yaml + ANSIBLE_REMOTE_TMP: /tmp/.ansible-tmp + inventory: + links: + hosts: "${MOLECULE_EPHEMERAL_DIRECTORY}/inventory/hosts.ini" + playbooks: + create: create.yml + converge: converge.yml + destroy: destroy.yml + +dependency: + name: galaxy verifier: name: ansible -scenario: - name: default - test_sequence: - - dependency - - cleanup - - destroy - - syntax - - create - - prepare - - converge - - idempotence - - side_effect - - verify - - cleanup - - destroy - +lint: |- + set -e + ansible-lint /workspace/roles/ \ No newline at end of file diff --git a/molecule/default/no-prepare.yml b/molecule/default/no-prepare.yml deleted file mode 100644 index 57b792f..0000000 --- a/molecule/default/no-prepare.yml +++ /dev/null @@ -1,43 +0,0 @@ -- name: Prepare - hosts: all - tasks: - - name: Detect OS family - ansible.builtin.setup: - gather_subset: - - "min" - - - name: Обновляем пакеты для работы с Ansible в RockyLinux (Centos/RedHat) - when: ansible_facts['os_family'] == "RedHat" - block: - - name: Устанавливаем репозиторий AppStream (если его нет) - ansible.builtin.raw: dnf config-manager --set-enabled appstream - changed_when: false - - - name: Установить rsync - ansible.builtin.raw: dnf install -y rsync - changed_when: false - - - name: Устанавливаем Python 3.8 - ansible.builtin.raw: dnf install -y python38 python38-pip - changed_when: false - - - name: Обновляем символическую ссылку python3 - ansible.builtin.raw: alternatives --set python /usr/bin/python3.8 - changed_when: false -# - name: Fix repository URLs -# ansible.builtin.command: -# cmd: sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* -# changed_when: false - -# - name: Update baseurl -# ansible.builtin.command: -# cmd: sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* -# changed_when: false - -# - name: Install required packages -# ansible.builtin.yum: -# name: -# - epel-release -# - python3 -# - python3-pip -# state: present diff --git a/molecule/default/no-verify.yml b/molecule/default/no-verify.yml deleted file mode 100644 index 5e80115..0000000 --- a/molecule/default/no-verify.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Prepare - hosts: all - tasks: - - name: Reun verify - debug: - msg: "Hello, Verify!" diff --git a/molecule/default/site.yml b/molecule/default/site.yml new file mode 100644 index 0000000..447ca70 --- /dev/null +++ b/molecule/default/site.yml @@ -0,0 +1,216 @@ +--- +# Универсальный playbook для тестирования Ansible ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# +# Этот файл отвечает за: +# 1. Обновление пакетов в контейнерах при запуске тестов +# 2. Установку common tools для корректной работы тестов +# 3. Подготовку окружения для тестирования ролей +# 4. Запуск всех ролей из директории roles/ + +- name: Подготовка окружения для тестирования + hosts: all + become: true + tasks: + # Создание tmp директории для Ansible + - name: Create Ansible tmp directory + file: + path: /tmp/.ansible-tmp + state: directory + mode: '0755' + owner: root + group: root + tags: + - setup + - tmp + # Обновление кеша пакетов для Debian/Ubuntu + - name: Update package cache (Debian/Ubuntu) + apt: + update_cache: true + cache_valid_time: 3600 + when: ansible_os_family == 'Debian' + changed_when: false + tags: + - setup + - update + + # Обновление кеша пакетов для RHEL/CentOS/AlmaLinux/Rocky + - name: Update package cache (RHEL/CentOS/AlmaLinux/Rocky) + yum: + update_cache: true + when: ansible_os_family == 'RedHat' + changed_when: false + tags: + - setup + - update + + # Обновление кеша пакетов для Alt Linux + - name: Update package cache (Alt Linux) + command: apt-get update + when: ansible_os_family == 'Altlinux' + changed_when: false + failed_when: false + tags: + - setup + - update + + # Обновление кеша пакетов для Astra Linux + - name: Update package cache (Astra Linux) + command: apt-get update + when: ansible_os_family == 'Astra Linux' + changed_when: false + failed_when: false + tags: + - setup + - update + + # Установка common tools для всех ОС (ЗАКОММЕНТИРОВАНО) + # - name: Install common tools (Debian/Ubuntu) + # apt: + # name: + # - curl + # - jq + # - ca-certificates + # - iproute2 + # - iputils-ping + # - procps + # - net-tools + # - vim + # - wget + # - unzip + # - git + # state: present + # update_cache: false + # when: ansible_os_family == 'Debian' + # tags: + # - setup + # - tools + + # - name: Install common tools (RHEL/CentOS/AlmaLinux/Rocky) + # yum: + # name: + # - curl + # - jq + # - ca-certificates + # - iproute + # - iputils + # - procps-ng + # - net-tools + # - vim + # - wget + # - unzip + # - git + # state: present + # when: ansible_os_family == 'RedHat' + # tags: + # - setup + # - tools + + # - name: Install common tools (Alt Linux) + # command: apt-get install -y curl jq ca-certificates iproute2 iputils procps net-tools vim wget unzip git + # when: ansible_os_family == 'Altlinux' + # changed_when: false + # failed_when: false + # tags: + # - setup + # - tools + + # - name: Install common tools (Astra Linux) + # command: apt-get install -y curl jq ca-certificates iproute2 iputils procps net-tools vim wget unzip git + # when: ansible_os_family == 'Astra Linux' + # changed_when: false + # failed_when: false + # tags: + # - setup + # - tools + + # Установка Python для Ansible (если не установлен) + - name: Install Python (Debian/Ubuntu) + apt: + name: + - python3 + - python3-pip + - python3-venv + state: present + when: ansible_os_family == 'Debian' + tags: + - setup + - python + + # Установка Python 3.8+ для RHEL/CentOS/Rocky/AlmaLinux + - name: Install Python 3.8+ (RHEL/CentOS/Rocky/AlmaLinux) + yum: + name: + - python3 + - python3-pip + state: present + when: ansible_os_family == 'RedHat' + tags: + - setup + - python + + - name: Install Python (RHEL/CentOS/AlmaLinux/Rocky) + yum: + name: + - python3 + - python3-pip + state: present + when: ansible_os_family == 'RedHat' + tags: + - setup + - python + + - name: Install Python (Alt Linux) + command: apt-get install -y python3 python3-pip + when: ansible_os_family == 'Altlinux' + changed_when: false + failed_when: false + tags: + - setup + - python + + - name: Install Python (Astra Linux) + command: apt-get install -y python3 python3-pip + when: ansible_os_family == 'Astra Linux' + changed_when: false + failed_when: false + tags: + - setup + - python + + # Создание пользователя для тестирования (ЗАКОММЕНТИРОВАНО) + # - name: Create test user + # user: + # name: testuser + # shell: /bin/bash + # create_home: yes + # state: present + # tags: + # - setup + # - user + + # Настройка sudo для тестового пользователя (ЗАКОММЕНТИРОВАНО) + # - name: Configure sudo for test user + # lineinfile: + # path: /etc/sudoers + # line: "testuser ALL=(ALL) NOPASSWD:ALL" + # state: present + # validate: 'visudo -cf %s' + # tags: + # - setup + # - sudo + + # Создание директории для тестов (ЗАКОММЕНТИРОВАНО) + # - name: Create test directory + # file: + # path: /tmp/ansible-test + # state: directory + # mode: '0755' + # owner: testuser + # group: testuser + # tags: + # - setup + # - directory + +- import_playbook: ../../roles/deploy.yml diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml index a8aa9f6..6e8d806 100644 --- a/molecule/default/verify.yml +++ b/molecule/default/verify.yml @@ -1,132 +1,123 @@ --- -# Проверка работы systemd, docker и docker-compose в образах -# Автор: Сергей Антропов -# Сайт: https://devops.org.ru +- 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] -- name: Verify systemd, docker and docker-compose services - hosts: all - gather_facts: true tasks: - - name: Display OS information - debug: - msg: "Тестирование на {{ ansible_distribution }} {{ ansible_distribution_version }}" + - name: Load preset configuration + include_vars: "{{ preset_file }}" + when: preset_file is file + ignore_errors: true - - name: Check if systemd is available and running - systemd: - name: systemd - state: started + # Проверка 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 - failed_when: false + ignore_errors: true - - name: Display systemd status + - name: Display systemd nodes status debug: - msg: "Systemd статус: {{ 'Доступен и запущен' if systemd_status is succeeded else 'Недоступен или не запущен' }}" + msg: "Systemd node {{ item.0.name }}: {{ item.1.stdout | default('unknown') }}" + loop: "{{ systemd_status.results | default([]) }}" + when: systemd_status is defined - - name: Check systemd version - command: systemd --version - register: systemd_version - failed_when: false - changed_when: false + # Проверка 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 systemd version + - name: Display DinD nodes status debug: - msg: "Версия systemd: {{ systemd_version.stdout_lines[0] if systemd_version.stdout_lines else 'Не определена' }}" + msg: "DinD node {{ item.0.name }}: Docker {{ item.1.stdout | default('not running') }}" + loop: "{{ dind_status.results | default([]) }}" + when: dind_status is defined - - name: Check if docker service exists - stat: - path: /usr/bin/docker - register: docker_binary + # Проверка 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: Check if docker service exists (alternative path) - stat: - path: /usr/local/bin/docker - register: docker_binary_alt - - - name: Display docker binary status + - name: Display DOoD nodes status debug: - msg: "Docker binary: {{ 'Найден в /usr/bin/docker' if docker_binary.stat.exists else ('Найден в /usr/local/bin/docker' if docker_binary_alt.stat.exists else 'Не найден') }}" + 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: Check docker version - command: docker --version - register: docker_version - failed_when: false - changed_when: false + # Проверка сетевого подключения + - 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 docker version + - name: Display network connectivity results debug: - msg: "Версия Docker: {{ docker_version.stdout if docker_version.stdout else 'Docker не установлен' }}" + 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 if docker daemon is running - command: docker info - register: docker_info - failed_when: false - changed_when: false + # Проверка портов + - 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 docker daemon status + - name: Display port status debug: - msg: "Docker daemon: {{ 'Запущен' if docker_info is succeeded else 'Не запущен или недоступен' }}" + 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: Check if docker-compose binary exists - stat: - path: /usr/local/bin/docker-compose - register: docker_compose_binary - - - name: Check if docker-compose binary exists (alternative path) - stat: - path: /usr/bin/docker-compose - register: docker_compose_binary_alt - - - name: Check if docker compose plugin exists - command: docker compose version - register: docker_compose_plugin - failed_when: false - changed_when: false - - - name: Display docker-compose status - debug: - msg: "Docker Compose: {{ 'Найден как binary' if docker_compose_binary.stat.exists or docker_compose_binary_alt.stat.exists else ('Найден как plugin' if docker_compose_plugin is succeeded else 'Не найден') }}" - - - name: Display docker-compose version - debug: - msg: "Версия Docker Compose: {{ docker_compose_plugin.stdout if docker_compose_plugin is succeeded else 'Docker Compose не установлен' }}" - - - name: Test docker functionality - command: docker run --rm hello-world - register: docker_test - failed_when: false - changed_when: false - - - name: Display docker test result - debug: - msg: "Тест Docker: {{ 'Успешно' if docker_test is succeeded else 'Ошибка - ' + docker_test.stderr }}" - - - name: Check systemd services status - command: systemctl list-units --type=service --state=running - register: running_services - failed_when: false - changed_when: false - - - name: Display running services count - debug: - msg: "Количество запущенных сервисов: {{ running_services.stdout_lines | length }}" - - - name: Check for docker-related systemd services - command: systemctl list-units --type=service | grep -i docker - register: docker_services - failed_when: false - changed_when: false - - - name: Display docker services - debug: - msg: "Docker сервисы: {{ docker_services.stdout_lines if docker_services.stdout_lines else 'Не найдены' }}" - - - name: Final summary + # Проверка групп + - name: Display inventory groups debug: msg: | - ======================================== - РЕЗУЛЬТАТЫ ПРОВЕРКИ ОБРАЗА {{ ansible_distribution }}: - ======================================== - Systemd: {{ '✓ Работает' if systemd_status is succeeded else '✗ Не работает' }} - Docker: {{ '✓ Установлен и работает' if docker_info is succeeded else '✗ Не установлен или не работает' }} - Docker Compose: {{ '✓ Доступен' if (docker_compose_binary.stat.exists or docker_compose_binary_alt.stat.exists or docker_compose_plugin is succeeded) else '✗ Недоступен' }} - ======================================== + 📋 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 }} + diff --git a/molecule/presets/default.yml b/molecule/presets/default.yml new file mode 100644 index 0000000..66bb22b --- /dev/null +++ b/molecule/presets/default.yml @@ -0,0 +1,43 @@ +--- +#description: Стандартный пресет по умолчанию для тестирования с 2 хостами (Ubuntu + Debian) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: + # Стандартный набор - 2 хоста для базового тестирования (стабильные ОС) + - name: u1 + family: ubuntu22 + groups: [test, web] + - name: u2 + family: debian12 + groups: [test, web] \ No newline at end of file diff --git a/molecule/presets/examples/all-images.yml b/molecule/presets/examples/all-images.yml new file mode 100644 index 0000000..7d2ec14 --- /dev/null +++ b/molecule/presets/examples/all-images.yml @@ -0,0 +1,184 @@ +--- +#description: Пресет для тестирования всех доступных образов (9 хостов) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# Примечание: Astra Linux и RedOS поддерживают только linux/amd64 + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: + # Debian-based системы + - name: ubuntu20-test + family: ubuntu2220 + groups: [test, debian, ubuntu] + publish: + - "8080:80" + env: + TEST_OS: "Ubuntu 20.04" + TEST_FAMILY: "Debian" + + - name: ubuntu22-test + family: ubuntu22 + groups: [test, debian, ubuntu] + publish: + - "8081:80" + env: + TEST_OS: "Ubuntu 22.04" + TEST_FAMILY: "Debian" + + - name: ubuntu24-test + family: ubuntu2224 + groups: [test, debian, ubuntu] + publish: + - "8082:80" + env: + TEST_OS: "Ubuntu 24.04" + TEST_FAMILY: "Debian" + + - name: debian9-test + family: debian129 + groups: [test, debian] + publish: + - "8083:80" + env: + TEST_OS: "Debian 9" + TEST_FAMILY: "Debian" + + - name: debian10-test + family: debian1210 + groups: [test, debian] + publish: + - "8084:80" + env: + TEST_OS: "Debian 10" + TEST_FAMILY: "Debian" + + - name: debian11-test + family: debian1211 + groups: [test, debian] + publish: + - "8085:80" + env: + TEST_OS: "Debian 11" + TEST_FAMILY: "Debian" + + - name: debian12-test + family: debian12 + groups: [test, debian] + publish: + - "8086:80" + env: + TEST_OS: "Debian 12" + TEST_FAMILY: "Debian" + + - name: alt-test + family: alt + groups: [test, altlinux] + publish: + - "8082:80" + env: + TEST_OS: "Alt Linux" + TEST_FAMILY: "Altlinux" + + - name: astra-test + family: astra + groups: [test, astra] + supported_platforms: ["linux/amd64"] # Только amd64 + publish: + - "8083:80" + env: + TEST_OS: "Astra Linux" + TEST_FAMILY: "Astra Linux" + + # RHEL-based системы + - name: centos7-test + family: centos97 + groups: [test, rhel, centos] + publish: + - "8090:80" + env: + TEST_OS: "CentOS 7" + TEST_FAMILY: "RedHat" + + - name: centos8-test + family: centos98 + groups: [test, rhel, centos] + publish: + - "8091:80" + env: + TEST_OS: "CentOS 8" + TEST_FAMILY: "RedHat" + + - name: centos9-test + family: centos99 + groups: [test, rhel, centos] + publish: + - "8092:80" + env: + TEST_OS: "CentOS 9" + TEST_FAMILY: "RedHat" + + - name: rhel-test + family: rhel + groups: [test, rhel] + publish: + - "8085:80" + env: + TEST_OS: "RHEL" + TEST_FAMILY: "RedHat" + + - name: alma-test + family: alma + groups: [test, rhel] + publish: + - "8086:80" + env: + TEST_OS: "AlmaLinux" + TEST_FAMILY: "RedHat" + + - name: rocky-test + family: rocky + groups: [test, rhel] + publish: + - "8087:80" + env: + TEST_OS: "Rocky Linux" + TEST_FAMILY: "RedHat" + + - name: redos-test + family: redos + groups: [test, rhel] + supported_platforms: ["linux/amd64"] # Только amd64 + publish: + - "8088:80" + env: + TEST_OS: "RedOS" + TEST_FAMILY: "RedHat" \ No newline at end of file diff --git a/molecule/presets/examples/centos-all.yml b/molecule/presets/examples/centos-all.yml new file mode 100644 index 0000000..bd47a91 --- /dev/null +++ b/molecule/presets/examples/centos-all.yml @@ -0,0 +1,52 @@ +--- +#description: Пресет со всеми версиями CentOS (7, 8, 9) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы CentOS +images: + centos7: "inecs/ansible-lab:centos7-latest" + centos8: "inecs/ansible-lab:centos8-latest" + centos9: "inecs/ansible-lab:centos9-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # CentOS 7 + - name: centos7-1 + family: centos7 + groups: [centos, test, web] + publish: ["7007:80"] + - name: centos7-2 + family: centos7 + groups: [centos, test, db] + publish: ["7008:80"] + + # CentOS 8 + - name: centos8-1 + family: centos8 + groups: [centos, test, web] + publish: ["7009:80"] + - name: centos8-2 + family: centos8 + groups: [centos, test, db] + publish: ["7010:80"] + + # CentOS 9 Stream + - name: centos9-1 + family: centos9 + groups: [centos, test, web] + publish: ["7011:80"] + - name: centos9-2 + family: centos9 + groups: [centos, test, db] + publish: ["7012:80"] diff --git a/molecule/presets/examples/centos7.yml b/molecule/presets/examples/centos7.yml new file mode 100644 index 0000000..1e00555 --- /dev/null +++ b/molecule/presets/examples/centos7.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для CentOS 7 +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ CentOS 7 +images: + centos7: "inecs/ansible-lab:centos7-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # CentOS 7 хосты + - name: centos7-web + family: centos7 + groups: [centos, test, web] + publish: ["7070:80"] + - name: centos7-db + family: centos7 + groups: [centos, test, db] + publish: ["7071:80"] + - name: centos7-app + family: centos7 + groups: [centos, test, app] + publish: ["7072:80"] diff --git a/molecule/presets/examples/centos8.yml b/molecule/presets/examples/centos8.yml new file mode 100644 index 0000000..f684216 --- /dev/null +++ b/molecule/presets/examples/centos8.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для CentOS 8 +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ CentOS 8 +images: + centos8: "inecs/ansible-lab:centos8-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # CentOS 8 хосты + - name: centos8-web + family: centos8 + groups: [centos, test, web] + publish: ["7080:80"] + - name: centos8-db + family: centos8 + groups: [centos, test, db] + publish: ["7081:80"] + - name: centos8-app + family: centos8 + groups: [centos, test, app] + publish: ["7082:80"] diff --git a/molecule/presets/examples/centos9.yml b/molecule/presets/examples/centos9.yml new file mode 100644 index 0000000..55b1bd9 --- /dev/null +++ b/molecule/presets/examples/centos9.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для CentOS 9 Stream +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ CentOS 9 +images: + centos9: "inecs/ansible-lab:centos9-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # CentOS 9 Stream хосты + - name: centos9-web + family: centos9 + groups: [centos, test, web] + publish: ["7090:80"] + - name: centos9-db + family: centos9 + groups: [centos, test, db] + publish: ["7091:80"] + - name: centos9-app + family: centos9 + groups: [centos, test, app] + publish: ["7092:80"] diff --git a/molecule/presets/examples/debian-all.yml b/molecule/presets/examples/debian-all.yml new file mode 100644 index 0000000..12af22f --- /dev/null +++ b/molecule/presets/examples/debian-all.yml @@ -0,0 +1,63 @@ +--- +#description: Пресет со всеми версиями Debian (9, 10, 11, 12) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы Debian +images: + 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: + # Debian 9 Stretch + - name: debian9-1 + family: debian9 + groups: [debian, test, web] + publish: ["9009:80"] + - name: debian9-2 + family: debian9 + groups: [debian, test, db] + publish: ["9010:80"] + + # Debian 10 Buster + - name: debian10-1 + family: debian10 + groups: [debian, test, web] + publish: ["9011:80"] + - name: debian10-2 + family: debian10 + groups: [debian, test, db] + publish: ["9012:80"] + + # Debian 11 Bullseye + - name: debian11-1 + family: debian11 + groups: [debian, test, web] + publish: ["9013:80"] + - name: debian11-2 + family: debian11 + groups: [debian, test, db] + publish: ["9014:80"] + + # Debian 12 Bookworm + - name: debian12-1 + family: debian12 + groups: [debian, test, web] + publish: ["9015:80"] + - name: debian12-2 + family: debian12 + groups: [debian, test, db] + publish: ["9016:80"] diff --git a/molecule/presets/examples/debian10.yml b/molecule/presets/examples/debian10.yml new file mode 100644 index 0000000..4cc645a --- /dev/null +++ b/molecule/presets/examples/debian10.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для Debian 10 Buster +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ Debian 10 +images: + debian10: "inecs/ansible-lab:debian10-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Debian 10 Buster хосты + - name: debian10-web + family: debian10 + groups: [debian, test, web] + publish: ["9100:80"] + - name: debian10-db + family: debian10 + groups: [debian, test, db] + publish: ["9101:80"] + - name: debian10-app + family: debian10 + groups: [debian, test, app] + publish: ["9102:80"] diff --git a/molecule/presets/examples/debian11.yml b/molecule/presets/examples/debian11.yml new file mode 100644 index 0000000..f499b24 --- /dev/null +++ b/molecule/presets/examples/debian11.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для Debian 11 Bullseye +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ Debian 11 +images: + debian11: "inecs/ansible-lab:debian11-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Debian 11 Bullseye хосты + - name: debian11-web + family: debian11 + groups: [debian, test, web] + publish: ["9110:80"] + - name: debian11-db + family: debian11 + groups: [debian, test, db] + publish: ["9111:80"] + - name: debian11-app + family: debian11 + groups: [debian, test, app] + publish: ["9112:80"] diff --git a/molecule/presets/examples/debian12.yml b/molecule/presets/examples/debian12.yml new file mode 100644 index 0000000..8084a5c --- /dev/null +++ b/molecule/presets/examples/debian12.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для Debian 12 Bookworm +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ Debian 12 +images: + 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: + # Debian 12 Bookworm хосты + - name: debian12-web + family: debian12 + groups: [debian, test, web] + publish: ["9120:80"] + - name: debian12-db + family: debian12 + groups: [debian, test, db] + publish: ["9121:80"] + - name: debian12-app + family: debian12 + groups: [debian, test, app] + publish: ["9122:80"] diff --git a/molecule/presets/examples/debian9.yml b/molecule/presets/examples/debian9.yml new file mode 100644 index 0000000..7545138 --- /dev/null +++ b/molecule/presets/examples/debian9.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для Debian 9 Stretch +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ Debian 9 +images: + debian9: "inecs/ansible-lab:debian9-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Debian 9 Stretch хосты + - name: debian9-web + family: debian9 + groups: [debian, test, web] + publish: ["9090:80"] + - name: debian9-db + family: debian9 + groups: [debian, test, db] + publish: ["9091:80"] + - name: debian9-app + family: debian9 + groups: [debian, test, app] + publish: ["9092:80"] diff --git a/molecule/presets/examples/docker-full.yml b/molecule/presets/examples/docker-full.yml new file mode 100644 index 0000000..22adf6d --- /dev/null +++ b/molecule/presets/examples/docker-full.yml @@ -0,0 +1,58 @@ +--- +#description: Полный пресет с Docker функциональностью (DinD + DOoD) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: ubuntu22 + groups: [test, web] + - name: u2 + family: debian12 + groups: [test, web] + + # DinD узел (Docker-in-Docker) + - name: docker1 + type: dind + groups: [docker] + publish: ["8080:8080"] + + # DOoD узел (Docker-out-of-Docker) + - name: dood1 + type: dood + family: ubuntu22 + groups: [dood] + publish: ["8081:8081"] + env: + DOCKER_HOST: unix:///var/run/docker.sock diff --git a/molecule/presets/examples/docker-test.yml b/molecule/presets/examples/docker-test.yml new file mode 100644 index 0000000..af5925a --- /dev/null +++ b/molecule/presets/examples/docker-test.yml @@ -0,0 +1,58 @@ +--- +#description: Пресет с Docker контейнерами (DinD + DOoD) для тестирования Docker-задач +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: test1 + family: debian12 + groups: [test] + - name: test2 + family: rhel + groups: [test] + + # DinD узел (Docker-in-Docker) + - name: docker1 + type: dind + groups: [docker] + publish: ["8080:8080"] + + # DOoD узел (Docker-out-of-Docker) + - name: dood1 + type: dood + family: debian12 + groups: [dood] + publish: ["8081:8081"] + env: + DOCKER_HOST: unix:///var/run/docker.sock diff --git a/molecule/presets/examples/etcd-patroni.yml b/molecule/presets/examples/etcd-patroni.yml new file mode 100644 index 0000000..69ae07f --- /dev/null +++ b/molecule/presets/examples/etcd-patroni.yml @@ -0,0 +1,76 @@ +--- +#description: Пресет для тестирования кластера etcd + PostgreSQL + Patroni (9 хостов) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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"] + +# Описание кластера etcd + Patroni + HAProxy +hosts: + # ETCD кластер (5 узлов для высокой доступности) + - name: etcd1 + family: debian12 + groups: [etcd, cluster] + - name: etcd2 + family: rhel + groups: [etcd, cluster] + - name: etcd3 + family: debian12 + groups: [etcd, cluster] + - name: etcd4 + family: rhel + groups: [etcd, cluster] + - name: etcd5 + family: debian12 + groups: [etcd, cluster] + + # Patroni кластер (3 узла PostgreSQL) + - name: patroni1 + family: rhel + groups: [patroni, database, cluster] + - name: patroni2 + family: debian12 + groups: [patroni, database, cluster] + - name: patroni3 + family: rhel + groups: [patroni, database, cluster] + + # HAProxy для балансировки + - name: haproxy + family: debian12 + groups: [haproxy, loadbalancer] + publish: ["5000:5000", "5001:5001"] # RW и RO порты + + # DinD узел для тестирования Docker Compose внутри + - name: app-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080"] diff --git a/molecule/presets/examples/minimal.yml b/molecule/presets/examples/minimal.yml new file mode 100644 index 0000000..9d9cf4c --- /dev/null +++ b/molecule/presets/examples/minimal.yml @@ -0,0 +1,44 @@ +--- +#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: astra + groups: [test] + supported_platforms: ["linux/amd64"] # Только amd64 + - name: u2 + family: alt + groups: [test] \ No newline at end of file diff --git a/molecule/presets/examples/multi-os.yml b/molecule/presets/examples/multi-os.yml new file mode 100644 index 0000000..f0073cc --- /dev/null +++ b/molecule/presets/examples/multi-os.yml @@ -0,0 +1,84 @@ +--- +#description: Пресет для тестирования на разных ОС с 12 хостами (Debian + RHEL) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы для разных ОС +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: + # Debian серверы + - name: debian1 + family: debian12 + groups: [debian, servers, web] + - name: debian2 + family: debian12 + groups: [debian, servers, web] + - name: debian3 + family: debian12 + groups: [debian, servers, app] + - name: debian4 + family: debian12 + 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: debian12 + groups: [database, debian, db] + - name: db-rhel + family: rhel + groups: [database, rhel, db] + + # Load balancer + - name: lb-mixed + family: debian12 + groups: [loadbalancer, haproxy] + publish: ["80:80", "443:443"] + + # DinD узел для тестирования Docker + - name: docker-mixed + type: dind + groups: [docker, apps] + publish: ["8080:8080"] diff --git a/molecule/presets/examples/performance.yml b/molecule/presets/examples/performance.yml new file mode 100644 index 0000000..477a431 --- /dev/null +++ b/molecule/presets/examples/performance.yml @@ -0,0 +1,87 @@ +--- +#description: Пресет для нагрузочного тестирования с 12 хостами (серверы + БД + кэш) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: + # Основные серверы (5 узлов) + - name: server1 + family: debian12 + groups: [servers, web, app] + - name: server2 + family: rhel + groups: [servers, web, app] + - name: server3 + family: debian12 + groups: [servers, web, app] + - name: server4 + family: rhel + groups: [servers, web, app] + - name: server5 + family: debian12 + groups: [servers, web, app] + + # База данных (3 узла) + - name: db1 + family: rhel + groups: [database, db] + - name: db2 + family: debian12 + groups: [database, db] + - name: db3 + family: rhel + groups: [database, db] + + # Кэш (3 узла Redis) + - name: cache1 + family: debian12 + groups: [cache, redis] + - name: cache2 + family: rhel + groups: [cache, redis] + - name: cache3 + family: debian12 + 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"] \ No newline at end of file diff --git a/molecule/presets/examples/security.yml b/molecule/presets/examples/security.yml new file mode 100644 index 0000000..82f3006 --- /dev/null +++ b/molecule/presets/examples/security.yml @@ -0,0 +1,90 @@ +--- +#description: Пресет для тестирования безопасности с 10 хостами (bastion + internal + monitoring) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: + # Bastion хосты (точки входа) + - name: bastion1 + family: rhel + groups: [bastion, security, jump] + publish: ["2222:22"] + - name: bastion2 + family: debian12 + groups: [bastion, security, jump] + publish: ["2223:22"] + + # Внутренние серверы (без внешнего доступа) + - name: internal1 + family: rhel + groups: [internal, servers, app] + - name: internal2 + family: debian12 + 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: debian12 + groups: [database, secure, internal] + + # Мониторинг и логирование + - name: monitor1 + family: debian12 + groups: [monitoring, security, logs] + - name: monitor2 + family: rhel + groups: [monitoring, security, logs] + + # Firewall и сетевые компоненты + - name: fw1 + family: rhel + groups: [firewall, network, security] + - name: fw2 + family: debian12 + groups: [firewall, network, security] + + # DOoD узел для тестирования Docker безопасности + - name: docker-secure + type: dood + family: debian12 + groups: [docker, security, apps] + publish: ["8080:8080"] + env: + DOCKER_HOST: "unix:///var/run/docker.sock" \ No newline at end of file diff --git a/molecule/presets/examples/stable.yml b/molecule/presets/examples/stable.yml new file mode 100644 index 0000000..50ec4eb --- /dev/null +++ b/molecule/presets/examples/stable.yml @@ -0,0 +1,43 @@ +--- +#description: Стабильный пресет для тестирования с Ubuntu и Debian (проверенные ОС) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: ubuntu22 + groups: [test, web] + - name: u2 + family: debian12 + groups: [test, web] diff --git a/molecule/presets/examples/standart.yml b/molecule/presets/examples/standart.yml new file mode 100644 index 0000000..6044d61 --- /dev/null +++ b/molecule/presets/examples/standart.yml @@ -0,0 +1,46 @@ +--- +#description: Стандартный пресет для тестирования с 3 хостами (Debian + RHEL) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: + # Стандартный набор - 3 хоста + - name: u1 + family: debian12 + groups: [test] + - name: u2 + family: rhel + groups: [test] + - name: u3 + family: debian12 + groups: [test] diff --git a/molecule/presets/examples/test.yml b/molecule/presets/examples/test.yml new file mode 100644 index 0000000..f6e8ee7 --- /dev/null +++ b/molecule/presets/examples/test.yml @@ -0,0 +1,40 @@ +--- +#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: debian12 + groups: [test] diff --git a/molecule/presets/examples/ubuntu-all.yml b/molecule/presets/examples/ubuntu-all.yml new file mode 100644 index 0000000..df89d43 --- /dev/null +++ b/molecule/presets/examples/ubuntu-all.yml @@ -0,0 +1,52 @@ +--- +#description: Пресет со всеми версиями Ubuntu (20.04, 22.04, 24.04) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы Ubuntu +images: + ubuntu20: "inecs/ansible-lab:ubuntu20-latest" + ubuntu22: "inecs/ansible-lab:ubuntu22-latest" + ubuntu24: "inecs/ansible-lab:ubuntu24-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Ubuntu 20.04 LTS + - name: ubuntu20-1 + family: ubuntu20 + groups: [ubuntu, test, web] + publish: ["8020:80"] + - name: ubuntu20-2 + family: ubuntu20 + groups: [ubuntu, test, db] + publish: ["8026:80"] + + # Ubuntu 22.04 LTS + - name: ubuntu22-1 + family: ubuntu22 + groups: [ubuntu, test, web] + publish: ["8022:80"] + - name: ubuntu22-2 + family: ubuntu22 + groups: [ubuntu, test, db] + publish: ["8023:80"] + + # Ubuntu 24.04 LTS + - name: ubuntu24-1 + family: ubuntu24 + groups: [ubuntu, test, web] + publish: ["8024:80"] + - name: ubuntu24-2 + family: ubuntu24 + groups: [ubuntu, test, db] + publish: ["8025:80"] diff --git a/molecule/presets/examples/ubuntu20.yml b/molecule/presets/examples/ubuntu20.yml new file mode 100644 index 0000000..ca04b6d --- /dev/null +++ b/molecule/presets/examples/ubuntu20.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для Ubuntu 20.04 LTS +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ Ubuntu 20.04 +images: + ubuntu20: "inecs/ansible-lab:ubuntu20-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Ubuntu 20.04 LTS хосты + - name: ubuntu20-web + family: ubuntu20 + groups: [ubuntu, test, web] + publish: ["8020:80"] + - name: ubuntu20-db + family: ubuntu20 + groups: [ubuntu, test, db] + publish: ["8021:80"] + - name: ubuntu20-app + family: ubuntu20 + groups: [ubuntu, test, app] + publish: ["8022:80"] diff --git a/molecule/presets/examples/ubuntu22.yml b/molecule/presets/examples/ubuntu22.yml new file mode 100644 index 0000000..7ef23ac --- /dev/null +++ b/molecule/presets/examples/ubuntu22.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для Ubuntu 22.04 LTS +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ Ubuntu 22.04 +images: + ubuntu22: "inecs/ansible-lab:ubuntu22-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Ubuntu 22.04 LTS хосты + - name: ubuntu22-web + family: ubuntu22 + groups: [ubuntu, test, web] + publish: ["8220:80"] + - name: ubuntu22-db + family: ubuntu22 + groups: [ubuntu, test, db] + publish: ["8221:80"] + - name: ubuntu22-app + family: ubuntu22 + groups: [ubuntu, test, app] + publish: ["8222:80"] diff --git a/molecule/presets/examples/ubuntu24.yml b/molecule/presets/examples/ubuntu24.yml new file mode 100644 index 0000000..db76eef --- /dev/null +++ b/molecule/presets/examples/ubuntu24.yml @@ -0,0 +1,34 @@ +--- +#description: Пресет для Ubuntu 24.04 LTS +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образ Ubuntu 24.04 +images: + ubuntu24: "inecs/ansible-lab:ubuntu24-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Ubuntu 24.04 LTS хосты + - name: ubuntu24-web + family: ubuntu24 + groups: [ubuntu, test, web] + publish: ["8240:80"] + - name: ubuntu24-db + family: ubuntu24 + groups: [ubuntu, test, db] + publish: ["8241:80"] + - name: ubuntu24-app + family: ubuntu24 + groups: [ubuntu, test, app] + publish: ["8242:80"] diff --git a/molecule/presets/mytest.yml b/molecule/presets/mytest.yml new file mode 100644 index 0000000..7fabbe5 --- /dev/null +++ b/molecule/presets/mytest.yml @@ -0,0 +1,46 @@ +--- +#description: Стандартный пресет по умолчанию для тестирования с 2 хостами (Ubuntu + Debian) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-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: + # Стандартный набор - 2 хоста для базового тестирования (стабильные ОС) + - name: u1 + family: ubuntu22 + groups: [test] + - name: u2 + family: debian12 + groups: [test] + - name: u3 + family: centos9 + groups: [test] \ No newline at end of file diff --git a/requirements.yml b/requirements.yml deleted file mode 100644 index cf12a33..0000000 --- a/requirements.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -collections: - - name: maxhoesel.proxmox - version: 5.0.1 diff --git a/default/defaults/.gitkeep b/roles/.gitkeep similarity index 100% rename from default/defaults/.gitkeep rename to roles/.gitkeep diff --git a/roles/deploy.yaml b/roles/deploy.yaml deleted file mode 100644 index 73b314f..0000000 --- a/roles/deploy.yaml +++ /dev/null @@ -1 +0,0 @@ ---- \ No newline at end of file diff --git a/roles/deploy.yml b/roles/deploy.yml new file mode 100644 index 0000000..6507fb2 --- /dev/null +++ b/roles/deploy.yml @@ -0,0 +1,11 @@ +--- +# Playbook для развертывания на продакшн серверах +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Развертывание всех ролей + hosts: all + roles: + # - ping + # - devops + - docker diff --git a/roles/devops/QUICKSTART.md b/roles/devops/QUICKSTART.md new file mode 100644 index 0000000..a349008 --- /dev/null +++ b/roles/devops/QUICKSTART.md @@ -0,0 +1,122 @@ +# Быстрый старт - Роль devops + +## Автор +Сергей Антропов +Сайт: https://devops.org.ru + +## Что делает роль + +Роль `devops` автоматически: +1. ✅ Создает пользователя `devops` +2. ✅ Генерирует безопасный пароль (30 символов) +3. ✅ Настраивает SSH доступ по ключу +4. ✅ Добавляет права sudo без пароля +5. ✅ Создает домашнюю директорию +6. ✅ Автоматически определяет ОС и настраивает группы +7. ✅ Поддерживает все ОС из dockerfiles (Ubuntu, Debian, RHEL, CentOS, Rocky, AlmaLinux, Astra Linux, ALT Linux, RedOS) + +## Быстрый запуск + +### 1. Базовое использование +```bash +ansible-playbook -i inventory/hosts.ini roles/deploy.yml +``` + +### 2. С SSH ключом из vault +```bash +ansible-playbook -i inventory/hosts.ini roles/deploy.yml \ + --ask-vault-pass \ + -e "devops_ssh_public_key={{ devops_ssh_keys.public_key }}" +``` + +### 3. Только роль devops +```bash +ansible-playbook -i inventory/hosts.ini roles/devops/playbook.yml +``` + +## Проверка результата + +После выполнения проверьте: + +```bash +# Проверка пользователя +ansible all -i inventory/hosts.ini -m shell -a "id devops" + +# Проверка sudo прав +ansible all -i inventory/hosts.ini -m shell -a "sudo -l -U devops" + +# Проверка SSH директории +ansible all -i inventory/hosts.ini -m shell -a "ls -la /home/devops/.ssh/" +``` + +## Настройка SSH ключа + +1. Добавьте ваш SSH ключ в `vault/secrets.yml`: +```yaml +devops_ssh_keys: + public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhA... your@email.com" +``` + +2. Запустите playbook с передачей ключа: +```bash +ansible-playbook -i inventory/hosts.ini roles/deploy.yml \ + --ask-vault-pass \ + -e "devops_ssh_public_key={{ devops_ssh_keys.public_key }}" +``` + +## Кастомизация + +### Изменить имя пользователя +```yaml +vars: + devops_user: + name: "myuser" + home: "/home/myuser" +``` + +### Изменить длину пароля +```yaml +vars: + devops_password: + length: 40 +``` + +### Добавить группы +```yaml +vars: + devops_user: + groups: ["sudo", "docker", "wheel", "adm"] +``` + +## Безопасность + +- 🔒 Пароль генерируется автоматически и не сохраняется в логах +- 🔑 SSH доступ только по ключу (если настроен) +- 🛡️ Пользователь добавлен в sudoers с правами NOPASSWD +- 📁 SSH директория имеет правильные права доступа (700) + +## Troubleshooting + +### Проблема: Пользователь не создан +```bash +# Проверьте права sudo +ansible all -i inventory/hosts.ini -m shell -a "sudo whoami" +``` + +### Проблема: SSH не работает +```bash +# Проверьте права на SSH директорию +ansible all -i inventory/hosts.ini -m shell -a "ls -la /home/devops/.ssh/" +``` + +### Проблема: Sudo не работает +```bash +# Проверьте sudoers файл +ansible all -i inventory/hosts.ini -m shell -a "sudo visudo -c" +``` + +## Поддержка + +- 📧 Email: через сайт https://devops.org.ru +- 📖 Документация: `roles/devops/README.md` +- 🧪 Тесты: `roles/devops/tests/test.yml` diff --git a/roles/devops/README.md b/roles/devops/README.md new file mode 100644 index 0000000..4c384e9 --- /dev/null +++ b/roles/devops/README.md @@ -0,0 +1,177 @@ +# Роль devops + +Роль для создания пользователя devops с безопасным паролем, SSH доступом и правами sudo. + +## Автор +Сергей Антропов +Сайт: https://devops.org.ru + +## Описание + +Эта роль выполняет следующие функции: +1. Создание пользователя `devops` +2. Генерация безопасного пароля длиной 30 символов +3. Назначение пароля пользователю +4. Добавление пользователя в sudoers с правами выполнения команд без пароля +5. Настройка SSH доступа через публичный ключ + +## Требования + +- Ansible >= 2.9 +- Python >= 3.6 +- Права root/sudo для выполнения задач + +## Переменные + +### Основные переменные (defaults/main.yml) + +```yaml +# Настройки пользователя devops +devops_user: + name: "devops" + home: "/home/devops" + shell: "/bin/bash" + groups: ["sudo", "docker"] + create_home: true + state: "present" + +# Настройки пароля +devops_password: + length: 30 + special_chars: true + min_special: 4 + min_upper: 4 + min_lower: 4 + min_digits: 4 + +# Настройки sudo +devops_sudo: + nopasswd: true + commands: "ALL" + +# SSH настройки +devops_ssh: + authorized_keys_file: "/home/devops/.ssh/authorized_keys" + ssh_dir: "/home/devops/.ssh" + ssh_dir_mode: "0700" + authorized_keys_mode: "0600" +``` + +### Переменные из vault/secrets.yml + +```yaml +# SSH ключи для пользователя devops +devops_ssh_keys: + public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhA... devops@example.com" +``` + +## Использование + +### Базовое использование + +```yaml +- hosts: all + become: true + roles: + - devops +``` + +### С передачей SSH ключа + +```yaml +- hosts: all + become: true + vars: + devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" + roles: + - devops +``` + +### С кастомными настройками + +```yaml +- hosts: all + become: true + vars: + devops_user: + name: "mydevops" + home: "/home/mydevops" + devops_password: + length: 40 + roles: + - devops +``` + +## Безопасность + +- Пароль генерируется автоматически с использованием криптографически стойкого алгоритма +- Пароль содержит минимум 4 символа каждого типа (специальные, заглавные, строчные, цифры) +- SSH ключи добавляются в authorized_keys для безопасного доступа +- Пользователь добавляется в sudoers с правами NOPASSWD для удобства использования + +## Поддерживаемые ОС + +- **Ubuntu** (focal, jammy) +- **Debian** (bullseye, bookworm) +- **RHEL** (8, 9) +- **CentOS** (8, 9) +- **Rocky Linux** (8, 9) +- **AlmaLinux** (8, 9) +- **Astra Linux** (1.7) +- **ALT Linux** (p9) +- **RedOS** (9) + +### Автоматическое определение ОС + +Роль автоматически определяет операционную систему и настраивает: +- **Группы пользователя**: `sudo` для Ubuntu/Debian, `wheel` для RHEL-семейства +- **Путь к sudoers**: `/etc/sudoers.d/devops` +- **Валидация sudoers**: `visudo -cf %s` + +## Теги + +- `devops` - основная функциональность +- `user-management` - управление пользователями +- `security` - настройки безопасности +- `ssh` - SSH конфигурация +- `sudo` - настройки sudo + +## Примеры + +### Создание пользователя с SSH ключом + +```bash +ansible-playbook -i inventory/hosts.ini playbook.yml \ + --ask-vault-pass \ + -e "devops_ssh_public_key={{ devops_ssh_keys.public_key }}" +``` + +### Проверка создания пользователя + +```bash +ansible all -i inventory/hosts.ini -m shell -a "id devops" +``` + +## Troubleshooting + +### Проблема с sudoers + +Если возникают проблемы с sudoers, проверьте синтаксис: + +```bash +sudo visudo -c +``` + +### Проблема с SSH + +Проверьте права доступа к SSH директории: + +```bash +ls -la /home/devops/.ssh/ +``` + +Должны быть права 700 для директории и 600 для authorized_keys. + +## Лицензия + +MIT \ No newline at end of file diff --git a/roles/devops/defaults/main.yml b/roles/devops/defaults/main.yml new file mode 100644 index 0000000..d538a0c --- /dev/null +++ b/roles/devops/defaults/main.yml @@ -0,0 +1,82 @@ +--- +# Переменные по умолчанию для роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Настройки пользователя devops +devops_user: + name: "devops" + home: "/home/devops" + shell: "/bin/bash" + groups: [] + create_home: true + state: "present" + +# Настройки пароля +devops_password: + length: 30 + special_chars: true + min_special: 4 + min_upper: 4 + min_lower: 4 + min_digits: 4 + +# Настройки sudo +devops_sudo: + nopasswd: true + commands: "ALL" + +# SSH настройки +devops_ssh: + authorized_keys_file: "/home/devops/.ssh/authorized_keys" + ssh_dir: "/home/devops/.ssh" + ssh_dir_mode: "0700" + authorized_keys_mode: "0600" + +# Настройки для разных ОС +devops_os_config: + # Ubuntu/Debian + ubuntu: + groups: ["sudo", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + debian: + groups: ["sudo", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + + # RHEL/CentOS/Rocky/AlmaLinux + rhel: + groups: ["wheel", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + centos: + groups: ["wheel", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + rocky: + groups: ["wheel", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + alma: + groups: ["wheel", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + + # Astra Linux + astra: + groups: ["sudo", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + + # ALT Linux + alt: + groups: ["wheel", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" + + # RedOS + redos: + groups: ["wheel", "docker"] + sudo_file: "/etc/sudoers.d/devops" + sudo_validate: "visudo -cf %s" diff --git a/roles/devops/examples.yml b/roles/devops/examples.yml new file mode 100644 index 0000000..896b97e --- /dev/null +++ b/roles/devops/examples.yml @@ -0,0 +1,85 @@ +--- +# Примеры использования роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Пример 1: Базовое использование +- name: "Базовое создание пользователя devops" + hosts: all + become: true + roles: + - devops + +# Пример 2: С передачей SSH ключа из vault +- name: "Создание пользователя devops с SSH ключом" + hosts: all + become: true + vars: + devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" + roles: + - devops + +# Пример 3: С кастомными настройками +- name: "Создание пользователя с кастомными настройками" + hosts: all + become: true + vars: + devops_user: + name: "mydevops" + home: "/home/mydevops" + devops_password: + length: 40 + min_special: 6 + min_upper: 6 + min_lower: 6 + min_digits: 6 + devops_ssh: + ssh_dir: "/home/mydevops/.ssh" + authorized_keys_file: "/home/mydevops/.ssh/authorized_keys" + roles: + - devops + +# Пример 4: Для конкретной ОС (RHEL/CentOS) +- name: "Создание пользователя для RHEL/CentOS" + hosts: rhel_servers + become: true + vars: + devops_os_config: + rhel: + groups: ["wheel", "docker", "adm"] + roles: + - devops + +# Пример 5: Для Ubuntu/Debian +- name: "Создание пользователя для Ubuntu/Debian" + hosts: ubuntu_servers + become: true + vars: + devops_os_config: + ubuntu: + groups: ["sudo", "docker", "adm"] + roles: + - devops + +# Пример 4: С дополнительными группами +- name: "Создание пользователя с дополнительными группами" + hosts: all + become: true + vars: + devops_user: + groups: ["sudo", "docker", "wheel", "adm", "systemd-journal"] + roles: + - devops + +# Пример 5: Только для определенных хостов +- name: "Создание пользователя на серверах разработки" + hosts: dev_servers + become: true + vars: + devops_user: + name: "developer" + home: "/home/developer" + devops_sudo: + commands: "ALL, !/usr/bin/passwd root" + roles: + - devops diff --git a/roles/devops/handlers/main.yml b/roles/devops/handlers/main.yml new file mode 100644 index 0000000..d5081d3 --- /dev/null +++ b/roles/devops/handlers/main.yml @@ -0,0 +1,25 @@ +--- +# Обработчики для роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Обработчик для перезапуска SSH сервиса после изменения authorized_keys +- name: "Перезапуск SSH сервиса" + service: + name: ssh + state: restarted + become: true + when: ansible_os_family != "RedHat" + +- name: "Перезапуск SSH сервиса (RedHat/CentOS)" + service: + name: sshd + state: restarted + become: true + when: ansible_os_family == "RedHat" + +# Обработчик для проверки sudo конфигурации +- name: "Проверка sudo конфигурации" + command: visudo -c + become: true + changed_when: false \ No newline at end of file diff --git a/roles/devops/meta/main.yml b/roles/devops/meta/main.yml new file mode 100644 index 0000000..e7ead9d --- /dev/null +++ b/roles/devops/meta/main.yml @@ -0,0 +1,35 @@ +--- +galaxy_info: + author: Сергей Антропов + description: Роль для создания пользователя devops с безопасным паролем и SSH доступом + company: https://devops.org.ru + license: MIT + min_ansible_version: "2.9" + platforms: + - name: Ubuntu + versions: + - focal + - jammy + - name: Debian + versions: + - bullseye + - bookworm + - name: EL + versions: + - "8" + - "9" + - name: Rocky + versions: + - "8.0" + - "9.0" + - name: "Astra Linux" + versions: + - "1.7" + galaxy_tags: + - devops + - usermanagement + - security + - ssh + - sudo + +dependencies: [] diff --git a/roles/devops/playbook.yml b/roles/devops/playbook.yml new file mode 100644 index 0000000..71908db --- /dev/null +++ b/roles/devops/playbook.yml @@ -0,0 +1,50 @@ +--- +# Пример playbook для роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: "Создание пользователя devops с безопасным паролем и SSH доступом" + hosts: all + become: true + gather_facts: true + + vars: + # Переменная для SSH ключа (должна быть передана из vault) + devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" + + roles: + - devops + + post_tasks: + - name: "Проверка создания пользователя devops" + command: "id {{ devops_user.name }}" + register: user_check + failed_when: user_check.rc != 0 + changed_when: false + + - name: "Проверка SSH директории" + stat: + path: "{{ devops_ssh.ssh_dir }}" + register: ssh_dir_check + + - name: "Проверка authorized_keys" + stat: + path: "{{ devops_ssh.authorized_keys_file }}" + register: auth_keys_check + when: devops_ssh_public_key is defined + + - name: "Проверка sudo прав" + command: "sudo -l -U {{ devops_user.name }}" + register: sudo_check + become: true + changed_when: false + + - name: "Вывод результатов проверки" + debug: + msg: | + Пользователь {{ devops_user.name }} создан: {{ user_check.rc == 0 }} + SSH директория создана: {{ ssh_dir_check.stat.exists }} + {% if devops_ssh_public_key is defined %} + authorized_keys создан: {{ auth_keys_check.stat.exists }} + {% endif %} + Sudo права настроены: {{ sudo_check.rc == 0 }} diff --git a/roles/devops/tasks/main.yml b/roles/devops/tasks/main.yml new file mode 100644 index 0000000..ba4f102 --- /dev/null +++ b/roles/devops/tasks/main.yml @@ -0,0 +1,111 @@ +--- +# Задачи для роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Определение ОС и настройка переменных +- name: "Определение ОС и настройка переменных" + set_fact: + devops_os_family: "{{ ansible_os_family | lower }}" + devops_distribution: "{{ ansible_distribution | lower }}" + devops_os_name: "{{ ansible_distribution | lower if ansible_distribution is defined else ansible_os_family | lower }}" + when: ansible_os_family is defined + +# Определение групп пользователя в зависимости от ОС +- name: "Определение групп пользователя для {{ devops_os_name }}" + set_fact: + devops_user_groups: "{{ devops_os_config[devops_os_name].groups | default(devops_os_config[devops_os_family].groups | default(['sudo'])) }}" + devops_sudo_file: "{{ devops_os_config[devops_os_name].sudo_file | default(devops_os_config[devops_os_family].sudo_file | default('/etc/sudoers.d/devops')) }}" + devops_sudo_validate: "{{ devops_os_config[devops_os_name].sudo_validate | default(devops_os_config[devops_os_family].sudo_validate | default('visudo -cf %s')) }}" + when: devops_os_name is defined + +# Проверка существования групп перед созданием пользователя +- name: "Проверка существования групп" + getent: + database: "group" + key: "{{ item }}" + register: group_check + failed_when: false + changed_when: false + loop: "{{ devops_user_groups }}" + when: devops_user_groups is defined + +# Фильтрация только существующих групп +- name: "Фильтрация существующих групп" + set_fact: + devops_existing_groups: "{{ group_check.results | selectattr('ansible_facts', 'defined') | map(attribute='item') | list }}" + when: group_check is defined + +# Создание отсутствующих групп (если необходимо) +- name: "Создание группы docker если она не существует" + group: + name: "docker" + state: "present" + become: true + when: + - "'docker' in devops_user_groups" + - "'docker' not in (devops_existing_groups | default([]))" + +# Генерация безопасного пароля для пользователя devops +- name: "Генерация безопасного пароля для пользователя devops" + set_fact: + devops_user_password: "{{ lookup('password', '/tmp/devops_password length=' + devops_password.length | string + ' chars=ascii_letters,digits,punctuation') }}" + no_log: true + +# Создание пользователя devops +- name: "Создание пользователя devops" + user: + name: "{{ devops_user.name }}" + home: "{{ devops_user.home }}" + shell: "{{ devops_user.shell }}" + groups: "{{ devops_existing_groups | default(devops_user_groups) }}" + create_home: "{{ devops_user.create_home }}" + state: "{{ devops_user.state }}" + password: "{{ devops_user_password | password_hash('sha512') }}" + become: true + +# Создание SSH директории для пользователя devops +- name: "Создание SSH директории для пользователя devops" + file: + path: "{{ devops_ssh.ssh_dir }}" + state: directory + owner: "{{ devops_user.name }}" + group: "{{ devops_user.name }}" + mode: "{{ devops_ssh.ssh_dir_mode }}" + become: true + +# Добавление SSH ключа в authorized_keys +- name: "Добавление SSH ключа в authorized_keys" + authorized_key: + user: "{{ devops_user.name }}" + key: "{{ devops_ssh_public_key }}" + state: present + manage_dir: false + become: true + when: devops_ssh_public_key is defined + +# Настройка sudo для пользователя devops (без пароля) +- name: "Настройка sudo для пользователя devops без пароля" + lineinfile: + path: "{{ devops_sudo_file }}" + line: "{{ devops_user.name }} ALL=(ALL) NOPASSWD: {{ devops_sudo.commands }}" + create: true + mode: '0440' + validate: "{{ devops_sudo_validate }}" + become: true + +# Добавление пользователя в группу docker (если группа существует) +- name: "Добавление пользователя в группу docker" + user: + name: "{{ devops_user.name }}" + groups: "{{ devops_user_groups }}" + append: true + become: true + when: + - "'docker' in devops_user_groups" + - "'docker' in (devops_existing_groups | default([]))" + +# Логирование успешного создания пользователя +- name: "Логирование создания пользователя devops" + debug: + msg: "Пользователь {{ devops_user.name }} успешно создан с безопасным паролем и SSH доступом на {{ devops_os_name | default('неизвестная') }} ОС" diff --git a/roles/devops/tests/test.yml b/roles/devops/tests/test.yml new file mode 100644 index 0000000..472fa7e --- /dev/null +++ b/roles/devops/tests/test.yml @@ -0,0 +1,90 @@ +--- +# Тесты для роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: "Тестирование роли devops" + hosts: all + become: true + gather_facts: true + + vars: + devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" + + roles: + - devops + + post_tasks: + # Тест 1: Проверка существования пользователя + - name: "Проверка существования пользователя devops" + command: "id {{ devops_user.name }}" + register: user_exists + failed_when: user_exists.rc != 0 + changed_when: false + + # Тест 2: Проверка домашней директории + - name: "Проверка домашней директории" + stat: + path: "{{ devops_user.home }}" + register: home_dir + failed_when: not home_dir.stat.exists + + # Тест 3: Проверка SSH директории + - name: "Проверка SSH директории" + stat: + path: "{{ devops_ssh.ssh_dir }}" + register: ssh_dir + failed_when: not ssh_dir.stat.exists + + # Тест 4: Проверка authorized_keys (если SSH ключ передан) + - name: "Проверка authorized_keys" + stat: + path: "{{ devops_ssh.authorized_keys_file }}" + register: auth_keys + failed_when: devops_ssh_public_key is defined and not auth_keys.stat.exists + when: devops_ssh_public_key is defined + + # Тест 5: Проверка sudo прав + - name: "Проверка sudo прав" + command: "sudo -l -U {{ devops_user.name }}" + register: sudo_rights + become: true + failed_when: sudo_rights.rc != 0 + changed_when: false + + # Тест 6: Проверка групп пользователя + - name: "Проверка групп пользователя" + command: "groups {{ devops_user.name }}" + register: user_groups + failed_when: user_groups.rc != 0 + changed_when: false + + # Тест 7: Проверка прав на SSH директорию + - name: "Проверка прав на SSH директорию" + stat: + path: "{{ devops_ssh.ssh_dir }}" + register: ssh_dir_perms + failed_when: ssh_dir_perms.stat.mode != "0" + devops_ssh.ssh_dir_mode + + # Тест 8: Проверка shell пользователя + - name: "Проверка shell пользователя" + command: "getent passwd {{ devops_user.name }}" + register: user_shell + failed_when: user_shell.rc != 0 + changed_when: false + + # Вывод результатов тестов + - name: "Результаты тестов" + debug: + msg: | + ✅ Пользователь {{ devops_user.name }} создан + ✅ Домашняя директория {{ devops_user.home }} создана + ✅ SSH директория {{ devops_ssh.ssh_dir }} создана + {% if devops_ssh_public_key is defined %} + ✅ authorized_keys настроен + {% endif %} + ✅ Sudo права настроены + ✅ Группы пользователя: {{ user_groups.stdout }} + ✅ Shell пользователя: {{ user_shell.stdout.split(':')[-1] }} + ✅ ОС: {{ devops_os_name | default('неизвестная') }} + ✅ Группы для ОС: {{ devops_user_groups | default('не определены') }} diff --git a/roles/devops/vars/main.yml b/roles/devops/vars/main.yml new file mode 100644 index 0000000..a476a14 --- /dev/null +++ b/roles/devops/vars/main.yml @@ -0,0 +1,25 @@ +--- +# Переменные для роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Список пакетов, необходимых для роли +devops_required_packages: + - openssh-server + - sudo + - passwd + +# Настройки безопасности для SSH +devops_ssh_security: + permit_root_login: "no" + password_authentication: "yes" + pubkey_authentication: "yes" + authorized_keys_file: ".ssh/authorized_keys" + +# Настройки sudo для безопасности +devops_sudo_security: + requiretty: false + visiblepw: false + always_set_home: true + env_reset: true + env_keep: "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" diff --git a/roles/docker/README.md b/roles/docker/README.md new file mode 100644 index 0000000..ddd410a --- /dev/null +++ b/roles/docker/README.md @@ -0,0 +1,193 @@ +# Роль docker + +## Описание + +Универсальная роль Ansible для установки и настройки Docker и Docker Compose на различных Linux-дистрибутивах. + +Роль автоматически определяет семейство ОС (Debian/Ubuntu или Red Hat/CentOS/AlmaLinux) и использует соответствующий метод установки. + +**Поддерживаемые ОС:** +- Debian 9/10/11/12 +- Ubuntu 20.04/22.04/24.04 +- CentOS 7/8/9 +- AlmaLinux 8/9 +- Rocky Linux 8/9 +- RHEL 8/9 + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## Переменные + +| Переменная | По умолчанию | Описание | +|------------|--------------|----------| +| `docker_version` | `"latest"` | Версия Docker CE для установки | +| `docker_compose_version` | `"latest"` | Версия Docker Compose (для standalone версии) | +| `docker_use_official_repo` | `true` | Использовать официальный репозиторий Docker | +| `docker_use_compose_plugin` | `true` | Использовать docker-compose-plugin вместо standalone | +| `docker_users` | `[]` | Список пользователей для добавления в группу docker | +| `docker_service_enabled` | `true` | Автозапуск Docker при загрузке | +| `docker_service_state` | `started` | Состояние службы Docker | +| `docker_additional_packages` | `[]` | Дополнительные пакеты для установки | +| `docker_install_method` | `"official"` | Метод установки: 'official' или 'get.docker.com' | + +## Примеры использования + +### Базовое использование + +```yaml +- hosts: all + roles: + - docker +``` + +### Установка с добавлением пользователей + +```yaml +- hosts: all + roles: + - role: docker + vars: + docker_users: + - ansible + - deploy +``` + +### Установка через скрипт get.docker.com + +```yaml +- hosts: all + roles: + - role: docker + vars: + docker_install_method: "get.docker.com" + docker_use_official_repo: false +``` + +### Установка standalone Docker Compose + +```yaml +- hosts: all + roles: + - role: docker + vars: + docker_use_compose_plugin: false + docker_compose_version: "2.23.0" +``` + +### Установка с дополнительными пакетами + +```yaml +- hosts: all + roles: + - role: docker + vars: + docker_additional_packages: + - docker-ce-rootless-extras +``` + +## Зависимости + +Нет зависимостей от других ролей. + +## Требования + +- Ansible 2.9+ +- Python 3.6+ +- Права sudo на целевых хостах +- Доступ к интернету для загрузки пакетов + +## Что делает роль + +1. Определяет семейство ОС (Debian или Red Hat) +2. Устанавливает необходимые зависимости +3. Добавляет официальный репозиторий Docker +4. Устанавливает Docker CE и Docker Compose +5. Запускает и включает службу Docker +6. Создает группу docker +7. Добавляет пользователей в группу docker +8. Проверяет корректность установки + +## Проверка установки + +После выполнения роли проверьте установку: + +```bash +# Проверка версии Docker +docker --version + +# Проверка версии Docker Compose +docker compose version +# или +docker-compose --version + +# Проверка статуса службы +systemctl status docker + +# Проверка информации о Docker +docker info +``` + +## Пример playbook для тестирования + +```yaml +--- +- name: Установка Docker на все хосты + hosts: all + become: yes + roles: + - role: docker + vars: + docker_users: + - ansible + docker_use_compose_plugin: true + + post_tasks: + - name: Запуск тестового контейнера + docker_container: + name: hello-world + image: hello-world:latest + state: started + + - name: Проверка запущенных контейнеров + command: docker ps -a + register: docker_ps + changed_when: false + + - name: Вывод списка контейнеров + debug: + var: docker_ps.stdout_lines +``` + +## Troubleshooting + +### Docker не запускается + +Проверьте журналы systemd: +```bash +sudo journalctl -u docker.service +``` + +### Проблемы с репозиторием + +Для Ubuntu/Debian, если репозиторий не добавляется: +```bash +sudo apt-get update +sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release +``` + +### Проблемы с правами + +Если пользователь не может запускать docker без sudo: +```bash +sudo usermod -aG docker $USER +# Выйдите и войдите снова +``` + +## Лицензия + +MIT + +## Автор + +Сергей Антропов - https://devops.org.ru diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml new file mode 100644 index 0000000..517c390 --- /dev/null +++ b/roles/docker/defaults/main.yml @@ -0,0 +1,33 @@ +--- +# Переменные по умолчанию для роли docker +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Версия Docker CE +docker_version: "latest" + +# Версия Docker Compose (если не используется docker-compose-plugin) +docker_compose_version: "latest" + +# Использовать ли официальный репозиторий Docker (рекомендуется) +docker_use_official_repo: true + +# Использовать ли docker-compose-plugin (вместо standalone docker-compose) +docker_use_compose_plugin: true + +# Пользователь для добавления в группу docker +docker_users: [] + # - ansible + # - deploy + +# Автозапуск Docker при загрузке системы +docker_service_enabled: true + +# Автозапуск Docker при загрузке системы +docker_service_state: started + +# Дополнительные пакеты для установки +docker_additional_packages: [] + +# Метод установки: 'official' (официальный репозиторий) или 'get.docker.com' (скрипт) +docker_install_method: "get.docker.com" diff --git a/roles/docker/examples.yml b/roles/docker/examples.yml new file mode 100644 index 0000000..716e218 --- /dev/null +++ b/roles/docker/examples.yml @@ -0,0 +1,104 @@ +--- +# Примеры использования роли docker +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Базовый пример установки Docker + hosts: all + become: yes + roles: + - docker + +- name: Установка Docker с добавлением пользователей + hosts: all + become: yes + roles: + - role: docker + vars: + docker_users: + - ansible + - deploy + - developer + +- name: Установка Docker через скрипт get.docker.com + hosts: all + become: yes + roles: + - role: docker + vars: + docker_install_method: "get.docker.com" + docker_use_official_repo: false + +- name: Установка Docker с standalone Docker Compose + hosts: all + become: yes + roles: + - role: docker + vars: + docker_use_compose_plugin: false + docker_compose_version: "2.23.0" + +- name: Установка Docker с дополнительными пакетами + hosts: all + become: yes + roles: + - role: docker + vars: + docker_additional_packages: + - docker-ce-rootless-extras + +- name: Полный пример с тестированием + hosts: all + become: yes + roles: + - role: docker + vars: + docker_users: + - ansible + docker_use_compose_plugin: true + + post_tasks: + - name: Проверка версии Docker + command: docker --version + register: docker_version + changed_when: false + failed_when: false + + - name: Вывод версии Docker + debug: + msg: "{{ docker_version.stdout }}" + + - name: Проверка версии Docker Compose + shell: | + if command -v docker compose &> /dev/null; then + docker compose version + elif command -v docker-compose &> /dev/null; then + docker-compose --version + fi + register: docker_compose_version + changed_when: false + failed_when: false + + - name: Вывод версии Docker Compose + debug: + msg: "{{ docker_compose_version.stdout }}" + + - name: Запуск тестового контейнера + docker_container: + name: hello-world + image: hello-world:latest + state: started + + - name: Проверка запущенных контейнеров + command: docker ps -a + register: docker_ps + changed_when: false + + - name: Вывод списка контейнеров + debug: + var: docker_ps.stdout_lines + + - name: Удаление тестового контейнера + docker_container: + name: hello-world + state: absent diff --git a/roles/docker/handlers/main.yml b/roles/docker/handlers/main.yml new file mode 100644 index 0000000..268c678 --- /dev/null +++ b/roles/docker/handlers/main.yml @@ -0,0 +1,22 @@ +--- +# Обработчики для роли docker +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Restart docker + become: true + systemd: + name: docker + state: restarted + +- name: Reload docker + become: true + systemd: + name: docker + state: reloaded + +- name: Restart docker socket + become: true + systemd: + name: docker.socket + state: restarted diff --git a/roles/docker/meta/main.yml b/roles/docker/meta/main.yml new file mode 100644 index 0000000..d9fcd73 --- /dev/null +++ b/roles/docker/meta/main.yml @@ -0,0 +1,35 @@ +--- +galaxy_info: + author: Сергей Антропов + description: Универсальная роль Ansible для установки и настройки Docker и Docker Compose на различных Linux-дистрибутивах + company: https://devops.org.ru + license: MIT + min_ansible_version: "2.9" + platforms: + - name: Ubuntu + versions: + - focal + - jammy + - noble + - name: Debian + versions: + - stretch + - buster + - bullseye + - bookworm + - name: EL + versions: + - "7" + - "8" + - "9" + - name: Rocky + versions: + - "8.0" + - "9.0" + galaxy_tags: + - docker + - dockercompose + - container + - virtualization + - linux +dependencies: [] diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml new file mode 100644 index 0000000..43b0abe --- /dev/null +++ b/roles/docker/tasks/main.yml @@ -0,0 +1,250 @@ +--- +# Задачи для роли docker +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Определяем семейство ОС для выбора правильного метода установки +- name: Определение семейства ОС + set_fact: + docker_os_family: "{{ ansible_os_family }}" + docker_pkg_manager: "{{ 'yum' if ansible_pkg_mgr == 'yum' else ('dnf' if ansible_pkg_mgr == 'dnf' else 'apt') }}" + +# Устанавливаем предварительные зависимости +- name: Установка зависимостей для Debian/Ubuntu + become: true + apt: + name: + - apt-transport-https + - ca-certificates + - curl + - gnupg + - lsb-release + - software-properties-common + state: present + update_cache: yes + when: ansible_os_family == "Debian" + +- name: Установка зависимостей для Red Hat + become: true + package: + name: + - yum-utils + - device-mapper-persistent-data + - lvm2 + state: present + when: ansible_os_family == "RedHat" + failed_when: false + +# Добавляем официальный репозиторий Docker для Debian/Ubuntu +- name: Добавление GPG ключа Docker для Debian/Ubuntu + become: true + shell: | + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/{{ (ansible_distribution | lower) }}/gpg -o /etc/apt/keyrings/docker.asc + chmod a+r /etc/apt/keyrings/docker.asc + args: + creates: /etc/apt/keyrings/docker.asc + when: + - ansible_os_family == "Debian" + - docker_use_official_repo + +- name: Добавление репозитория Docker для Debian/Ubuntu + become: true + apt_repository: + repo: "deb [arch={{ ansible_architecture }} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/{{ (ansible_distribution | lower) }} {{ ansible_distribution_release }} stable" + state: present + filename: docker + update_cache: yes + when: + - ansible_os_family == "Debian" + - docker_use_official_repo + +# Добавляем официальный репозиторий Docker для Red Hat +- name: Добавление репозитория Docker для Red Hat через dnf + become: true + shell: | + dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo + args: + creates: /etc/yum.repos.d/docker-ce.repo + when: + - ansible_os_family == "RedHat" + - ansible_pkg_mgr == "dnf" + - docker_use_official_repo + failed_when: false + +- name: Добавление репозитория Docker для Red Hat через yum-config-manager + become: true + shell: | + yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo + args: + creates: /etc/yum.repos.d/docker-ce.repo + when: + - ansible_os_family == "RedHat" + - ansible_pkg_mgr == "yum" + - docker_use_official_repo + failed_when: false + +# Устанавливаем Docker через официальный репозиторий +- name: Установка Docker CE для Debian/Ubuntu (официальный репозиторий) + become: true + apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + state: "{{ 'present' if docker_version == 'latest' else docker_version }}" + update_cache: yes + when: + - ansible_os_family == "Debian" + - docker_use_official_repo + - docker_install_method == "official" + +- name: Установка Docker CE для Red Hat (официальный репозиторий) + become: true + package: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + state: "{{ 'present' if docker_version == 'latest' else docker_version }}" + when: + - ansible_os_family == "RedHat" + - docker_use_official_repo + - docker_install_method == "official" + +# Устанавливаем Docker через скрипт get.docker.com +- name: Проверка наличия Docker + stat: + path: /usr/bin/docker + register: docker_binary + +- name: Скачивание скрипта установки Docker + become: true + get_url: + url: https://get.docker.com + dest: /tmp/get-docker.sh + mode: '0755' + when: + - docker_install_method == "get.docker.com" or docker_use_official_repo == false + - not docker_binary.stat.exists + +- name: Установка Docker через скрипт get.docker.com + become: true + command: /tmp/get-docker.sh + args: + creates: /usr/bin/docker + when: + - docker_install_method == "get.docker.com" or docker_use_official_repo == false + - not docker_binary.stat.exists + +- name: Проверка установки Docker + become: true + command: docker --version + register: docker_version_check + changed_when: false + failed_when: false + +- name: Вывод версии Docker + debug: + msg: "{{ docker_version_check.stdout if docker_version_check.rc == 0 else 'Docker не установлен' }}" + +# Устанавливаем docker-compose-plugin для Debian/Ubuntu +- name: Установка docker-compose-plugin для Debian/Ubuntu + become: true + apt: + name: + - docker-compose-plugin + state: present + when: + - ansible_os_family == "Debian" + - docker_use_compose_plugin + - docker_use_official_repo + +# Устанавливаем docker-compose-plugin для Red Hat +- name: Установка docker-compose-plugin для Red Hat + become: true + package: + name: + - docker-compose-plugin + state: present + when: + - ansible_os_family == "RedHat" + - docker_use_compose_plugin + - docker_use_official_repo + +# Устанавливаем standalone docker-compose +- name: Скачивание docker-compose + become: true + get_url: + url: "https://github.com/docker/compose/releases/{{ 'latest/download' if docker_compose_version == 'latest' else 'download/v' + docker_compose_version }}/docker-compose-{{ ansible_system }}-{{ ansible_machine }}" + dest: /usr/local/bin/docker-compose + mode: '0755' + when: + - not docker_use_compose_plugin or docker_compose_version != 'latest' + +- name: Проверка установки Docker Compose + become: true + shell: | + set -o pipefail + if command -v docker compose &> /dev/null; then + docker compose version + elif command -v docker-compose &> /dev/null; then + docker-compose --version + else + echo "Docker Compose не установлен" + fi + register: docker_compose_version_check + changed_when: false + failed_when: false + +- name: Вывод версии Docker Compose + debug: + msg: "{{ docker_compose_version_check.stdout if docker_compose_version_check.rc == 0 else 'Docker Compose не установлен' }}" + +# Запускаем и включаем службу Docker +- name: Запуск службы Docker + become: true + systemd: + name: docker + state: started + enabled: yes + +# Создаем группу docker +- name: Создание группы docker + become: true + group: + name: docker + state: present + +# Добавляем пользователей в группу docker +- name: Добавление пользователей в группу docker + become: true + user: + name: "{{ item }}" + groups: docker + append: yes + loop: "{{ docker_users }}" + when: docker_users | length > 0 + +# Устанавливаем дополнительные пакеты +- name: Установка дополнительных пакетов + become: true + package: + name: "{{ docker_additional_packages }}" + state: present + when: docker_additional_packages | length > 0 + +# Проверка статуса Docker +- name: Проверка статуса Docker + become: true + command: docker info + register: docker_info + changed_when: false + failed_when: false + +- name: Вывод информации о Docker + debug: + msg: "Docker успешно установлен и запущен" + when: docker_info.rc == 0 diff --git a/roles/docker/tests/test.yml b/roles/docker/tests/test.yml new file mode 100644 index 0000000..a8e007a --- /dev/null +++ b/roles/docker/tests/test.yml @@ -0,0 +1,89 @@ +--- +# Тестовый playbook для роли docker +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Тестирование установки Docker + hosts: all + become: yes + roles: + - role: docker + vars: + docker_users: + - ansible + + post_tasks: + - name: Проверка установки Docker + command: docker --version + register: docker_version_check + changed_when: false + failed_when: false + + - name: Проверка установки Docker Compose + shell: | + if command -v docker compose &> /dev/null; then + docker compose version + elif command -v docker-compose &> /dev/null; then + docker-compose --version + else + echo "Docker Compose не найден" + exit 1 + fi + register: docker_compose_check + changed_when: false + failed_when: false + + - name: Вывод результатов проверки + debug: + msg: + - "Docker: {{ docker_version_check.stdout }}" + - "Docker Compose: {{ docker_compose_check.stdout }}" + + - name: Проверка статуса службы Docker + systemd: + name: docker + register: docker_service + changed_when: false + + - name: Вывод статуса службы + debug: + msg: "Docker service is {{ docker_service.status.ActiveState }}" + + - name: Проверка группы docker + group: + name: docker + register: docker_group_check + + - name: Вывод информации о группе + debug: + msg: "Group docker exists with gid {{ docker_group_check.group.gid }}" + + - name: Запуск тестового контейнера + docker_container: + name: test-container + image: alpine:latest + command: echo "Hello from Docker" + state: started + + - name: Проверка запущенных контейнеров + command: docker ps -a + register: docker_ps + changed_when: false + + - name: Вывод списка контейнеров + debug: + var: docker_ps.stdout_lines + + - name: Удаление тестового контейнера + docker_container: + name: test-container + state: absent + + - name: Проверка успешного завершения теста + assert: + that: + - docker_version_check.rc == 0 + - docker_compose_check.rc == 0 + - docker_service.status.ActiveState == "active" + fail_msg: "Тестирование не пройдено" + success_msg: "Все тесты пройдены успешно" diff --git a/roles/ping/QUICKSTART.md b/roles/ping/QUICKSTART.md new file mode 100644 index 0000000..f148c3d --- /dev/null +++ b/roles/ping/QUICKSTART.md @@ -0,0 +1,66 @@ +# Быстрый старт - Роль Ping + +## Что делает роль? + +Роль выполняет ping yandex.ru из 5 пакетов и выводит результат. + +## Основные задачи роли: + +1. **Выполнение ping** - отправляет 5 пакетов на yandex.ru +2. **Вывод результата** - показывает строки результата ping +3. **Статистика** - выводит статус и время выполнения +4. **Дополнительная информация** - выводит полный вывод команды + +## Как использовать: + +### Вариант 1: Использование в roles/deploy.yml (уже добавлено) + +```bash +# Запуск только роли ping +make role test minimal ping + +# Запуск всех ролей +make role test minimal +``` + +### Вариант 2: Использование через roles/ping/playbook.yml + +```bash +# Запуск напрямую +ansible-playbook -i inventory/hosts.ini roles/ping/playbook.yml +``` + +### Вариант 3: Использование с кастомными параметрами + +```yaml +- name: Тест ping + hosts: all + roles: + - role: ping + vars: + ping_host: google.com + ping_count: 10 +``` + +## Переменные: + +- `ping_host` - хост для ping (по умолчанию: yandex.ru) +- `ping_count` - количество пакетов (по умолчанию: 5) + +## Теги: + +- `ping` - выполнение всех задач +- `test` - тестирование +- `debug` - отладочная информация +- `stats` - статистика + +## Пример вывода: + +``` +========================================= +Результат ping yandex.ru +========================================= +Статус: УСПЕШНО +Время выполнения: 4.234 +========================================= +``` diff --git a/roles/ping/README.md b/roles/ping/README.md new file mode 100644 index 0000000..09947ec --- /dev/null +++ b/roles/ping/README.md @@ -0,0 +1,96 @@ +# Роль Ping + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## Описание + +Роль для выполнения ping проверок подключения к сети. Роль отправляет ping пакеты на указанный хост и выводит результаты выполнения. + +## Требования + +- Ansible >= 2.9 +- Наличие утилиты `ping` на целевых хостах +- Привилегии на выполнение ping (обычно не требуются) + +## Переменные + +| Переменная | Тип | По умолчанию | Описание | +|------------|-----|--------------|----------| +| `ping_host` | string | `yandex.ru` | Целевой хост для ping | +| `ping_count` | integer | `5` | Количество пакетов для отправки | +| `ping_interval` | integer | `1` | Интервал между пакетами (в секундах) | +| `ping_timeout` | integer | `10` | Таймаут (в секундах) | +| `ping_packet_size` | integer | `64` | Размер пакета (в байтах) | + +## Примеры использования + +### Базовое использование + +```yaml +- name: Выполнить ping проверку + hosts: all + roles: + - ping +``` + +### С кастомными параметрами + +```yaml +- name: Выполнить ping проверку с кастомными параметрами + hosts: all + roles: + - role: ping + vars: + ping_host: google.com + ping_count: 10 +``` + +### В playbook + +```yaml +--- +- name: Тестирование сетевого подключения + hosts: servers + become: false + roles: + - role: ping + vars: + ping_host: 8.8.8.8 + ping_count: 3 + tags: + - network + - test +``` + +## Tags + +Роль поддерживает следующие теги: + +- `ping` - выполнение всех задач роли +- `test` - тестирование подключения +- `debug` - вывод отладочной информации +- `stats` - вывод статистики + +Пример использования тегов: + +```bash +ansible-playbook site.yml --tags "ping,debug" +``` + +## Поддерживаемые ОС + +- Red Hat Enterprise Linux 7/8/9 +- CentOS 7/8/Stream +- AlmaLinux 8/9 +- Rocky Linux 8/9 +- Ubuntu 20.04/22.04 +- Debian 10/11/12 + +## Лицензия + +MIT + +## Автор + +Сергей Антропов - https://devops.org.ru diff --git a/roles/ping/defaults/main.yml b/roles/ping/defaults/main.yml new file mode 100644 index 0000000..87bad99 --- /dev/null +++ b/roles/ping/defaults/main.yml @@ -0,0 +1,19 @@ +--- +# Переменные по умолчанию для роли ping +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# Целевой хост для ping +ping_host: yandex.ru + +# Количество пакетов для отправки +ping_count: 5 + +# Интервал между пакетами (в секундах) +ping_interval: 1 + +# Таймаут (в секундах) +ping_timeout: 10 + +# Размер пакета (в байтах) +ping_packet_size: 64 diff --git a/roles/ping/handlers/main.yml b/roles/ping/handlers/main.yml new file mode 100644 index 0000000..bfdec6c --- /dev/null +++ b/roles/ping/handlers/main.yml @@ -0,0 +1,7 @@ +--- +# Handlers для роли ping +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +# В данный момент handlers не требуются для роли ping (пустой файл для совместимости) +[] diff --git a/roles/ping/meta/main.yml b/roles/ping/meta/main.yml new file mode 100644 index 0000000..ed9d93b --- /dev/null +++ b/roles/ping/meta/main.yml @@ -0,0 +1,37 @@ +--- +# Метаданные роли ping +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +galaxy_info: + role_name: ping + namespace: antropov + author: Сергей Антропов + description: Роль для выполнения ping проверок подключения к сети + company: DevOps.org.ru + license: MIT + min_ansible_version: "2.9" + platforms: + - name: EL + versions: + - "7" + - "8" + - "9" + - "all" + - name: Ubuntu + versions: + - jammy + - focal + - noble + - name: Debian + versions: + - bullseye + - bookworm + - trixie + galaxy_tags: + - networking + - ping + - connectivity + - testing + +dependencies: [] diff --git a/roles/ping/playbook.yml b/roles/ping/playbook.yml new file mode 100644 index 0000000..4df0915 --- /dev/null +++ b/roles/ping/playbook.yml @@ -0,0 +1,16 @@ +--- +# Пример playbook для роли ping +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Тестирование ping подключения + hosts: all + become: false + roles: + - role: ping + vars: + ping_host: yandex.ru + ping_count: 5 + tags: + - ping + - test diff --git a/roles/ping/tasks/main.yml b/roles/ping/tasks/main.yml new file mode 100644 index 0000000..3e90a3a --- /dev/null +++ b/roles/ping/tasks/main.yml @@ -0,0 +1,44 @@ +--- +# Основные задачи для роли ping +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Выполнение ping с пакетами + command: ping -c {{ ping_count }} {{ ping_host }} + register: ping_result + changed_when: false + failed_when: false + tags: + - ping + - test + +- name: Вывод результата ping + debug: + msg: "{{ ping_result.stdout_lines }}" + tags: + - ping + - test + - debug + +- name: Статистика ping + debug: + msg: | + ========================================= + Результат ping {{ ping_host }} + ========================================= + Статус: {{ 'УСПЕШНО' if ping_result.rc == 0 else 'ОШИБКА' }} + Код возврата: {{ ping_result.rc }} + ========================================= + tags: + - ping + - test + - stats + +- name: Дополнительная информация о ping + debug: + var: ping_result.stdout + when: ping_result.stdout is defined + tags: + - ping + - test + - debug diff --git a/scripts/generate-role-docs.sh b/scripts/generate-role-docs.sh new file mode 100755 index 0000000..668c3ca --- /dev/null +++ b/scripts/generate-role-docs.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# Автоматическое создание документации для новых ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +set -euo pipefail + +echo "📚 Генерация документации для ролей..." + +# Получаем список всех ролей +ROLES=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||') + +for role in $ROLES; do + echo "📝 Генерация документации для роли: $role" + + # Создаем README.md для роли если его нет + if [ ! -f "roles/$role/README.md" ]; then + cat > "roles/$role/README.md" << EOF +# Роль $role + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## Описание + +Роль для настройки и конфигурации $role сервиса. + +## Требования + +- Ansible >= 2.9 +- Поддерживаемые ОС: Ubuntu, Debian, RHEL, CentOS, AlmaLinux, Rocky Linux + +## Переменные + +| Переменная | Тип | По умолчанию | Описание | +|------------|-----|--------------|----------| +| \`${role}_enabled\` | boolean | \`true\` | Включить роль | +| \`${role}_packages\` | list | \`[]\` | Пакеты для установки | + +## Примеры использования + +\`\`\`yaml +- name: Настройка $role + hosts: all + roles: + - $role +\`\`\` + +## Tags + +- \`$role\` - выполнение всех задач роли +- \`install\` - установка пакетов +- \`config\` - настройка конфигурации +EOF + fi +done + +echo "✅ Документация сгенерирована" diff --git a/scripts/role-manager.sh b/scripts/role-manager.sh new file mode 100755 index 0000000..feadebb --- /dev/null +++ b/scripts/role-manager.sh @@ -0,0 +1,253 @@ +#!/bin/bash +# Интерактивный менеджер ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +set -e + +# Цвета для вывода +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +WHITE='\033[0;37m' +RESET='\033[0m' + +# Функция для вывода заголовков +print_header() { + echo -e "${BLUE}==========================================${RESET}" + echo -e "${BLUE}$1${RESET}" + echo -e "${BLUE}==========================================${RESET}" +} + +# Функция для вывода успеха +print_success() { + echo -e "${GREEN}✅ $1${RESET}" +} + +# Функция для вывода ошибки +print_error() { + echo -e "${RED}❌ $1${RESET}" +} + +# Функция для вывода предупреждения +print_warning() { + echo -e "${YELLOW}⚠️ $1${RESET}" +} + +# Функция для вывода информации +print_info() { + echo -e "${CYAN}💡 $1${RESET}" +} + +# Список всех ролей +list_roles() { + print_header "📋 Список всех ролей" + echo "" + + if [ -d "roles" ]; then + ROLES=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | grep -v '^deploy$' | sort) + if [ -n "$ROLES" ]; then + echo "$ROLES" | sed 's/^/ - /' + echo "" + echo "📊 Всего ролей: $(echo "$ROLES" | wc -l)" + else + print_warning "Роли не найдены" + fi + else + print_error "Директория roles/ не найдена" + fi +} + +# Создание новой роли +create_role() { + print_header "➕ Создание новой роли" + echo "" + + read -p "Введите имя роли: " ROLE_NAME + if [ -z "$ROLE_NAME" ]; then + print_error "Имя роли не может быть пустым" + exit 1 + fi + + if [ -d "roles/$ROLE_NAME" ]; then + print_error "Роль '$ROLE_NAME' уже существует" + exit 1 + fi + + echo "📁 Создание структуры роли '$ROLE_NAME'..." + mkdir -p "roles/$ROLE_NAME"/{tasks,handlers,templates,files,vars,defaults,meta} + + echo "📝 Создание файлов..." + + # tasks/main.yml + cat > "roles/$ROLE_NAME/tasks/main.yml" << EOF +--- +# Задачи для роли $ROLE_NAME +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Пример задачи + debug: + msg: "Роль $ROLE_NAME выполнена" +EOF + + # defaults/main.yml + cat > "roles/$ROLE_NAME/defaults/main.yml" << EOF +--- +# Переменные по умолчанию для роли $ROLE_NAME +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +EOF + + # handlers/main.yml + cat > "roles/$ROLE_NAME/handlers/main.yml" << EOF +--- +# Обработчики для роли $ROLE_NAME +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +EOF + + # meta/main.yml + cat > "roles/$ROLE_NAME/meta/main.yml" << EOF +--- +galaxy_info: + author: Сергей Антропов + description: Роль $ROLE_NAME + company: https://devops.org.ru + license: MIT + min_ansible_version: "2.9" + platforms: + - name: Ubuntu + versions: + - focal + - jammy + - name: Debian + versions: + - bullseye + - bookworm + - name: RHEL + versions: + - "8" + - "9" + - name: CentOS + versions: + - "8" + - "9" + galaxy_tags: + - $ROLE_NAME +EOF + + # README.md + cat > "roles/$ROLE_NAME/README.md" << EOF +# Роль $ROLE_NAME + +## Описание + +Роль для ... + +## Переменные + +| Переменная | По умолчанию | Описание | +|------------|--------------|----------| +| | | | + +## Примеры использования + +\`\`\`yaml +- hosts: all + roles: + - $ROLE_NAME +\`\`\` + +## Автор + +Сергей Антропов - https://devops.org.ru +EOF + + echo "🔄 Обновление roles/deploy.yml..." + ./scripts/update-playbooks.sh + + print_success "Роль '$ROLE_NAME' создана и добавлена в deploy.yml" + echo "" + echo "📁 Структура создана:" + echo " roles/$ROLE_NAME/" + echo " ├── tasks/main.yml" + echo " ├── defaults/main.yml" + echo " ├── handlers/main.yml" + echo " ├── meta/main.yml" + echo " └── README.md" + echo "" + print_info "Следующие шаги:" + echo " 1. Отредактируйте tasks/main.yml" + echo " 2. Добавьте переменные в defaults/main.yml" + echo " 3. Протестируйте: make role test" +} + +# Удаление роли +delete_role() { + print_header "🗑️ Удаление роли" + echo "" + + echo "📋 Доступные роли:" + ROLES=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | grep -v '^deploy$' | sort) + if [ -n "$ROLES" ]; then + echo "$ROLES" | sed 's/^/ - /' + echo "" + read -p "Введите имя роли для удаления: " ROLE_NAME + if [ -z "$ROLE_NAME" ]; then + print_error "Имя роли не может быть пустым" + exit 1 + fi + + if [ ! -d "roles/$ROLE_NAME" ]; then + print_error "Роль '$ROLE_NAME' не найдена" + exit 1 + fi + + print_warning "Вы уверены, что хотите удалить роль '$ROLE_NAME'?" + read -p "Введите 'yes' для подтверждения: " CONFIRM + if [ "$CONFIRM" = "yes" ]; then + echo "🗑️ Удаление роли '$ROLE_NAME'..." + rm -rf "roles/$ROLE_NAME" + echo "🔄 Обновление roles/deploy.yml..." + ./scripts/update-playbooks.sh + print_success "Роль '$ROLE_NAME' удалена и убрана из deploy.yml" + else + print_error "Удаление отменено" + fi + else + print_warning "Роли не найдены" + fi +} + +# Главное меню +main() { + case "${1:-}" in + list) + list_roles + ;; + create) + create_role + ;; + delete) + delete_role + ;; + *) + echo "🎯 Доступные команды:" + echo "" + echo " 📋 ./scripts/role-manager.sh list - показать все роли" + echo " ➕ ./scripts/role-manager.sh create - создать новую роль" + echo " 🗑️ ./scripts/role-manager.sh delete - удалить роль" + echo "" + echo "💡 Или используйте:" + echo " make role list" + echo " make role create" + echo " make role delete" + ;; + esac +} + +main "$@" diff --git a/scripts/setup-cicd.sh b/scripts/setup-cicd.sh new file mode 100755 index 0000000..3431114 --- /dev/null +++ b/scripts/setup-cicd.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# Автоматическая настройка CI/CD для AnsibleLab +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +set -euo pipefail + +echo "🔧 Настройка CI/CD для AnsibleLab..." + +# Создание директории .github/workflows +mkdir -p .github/workflows + +# Создание базового workflow для GitHub Actions +echo "📝 Создание GitHub Actions workflow..." +cat > .github/workflows/ansible-test.yml << 'EOF' +name: Ansible Testing +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + pip install ansible ansible-lint + ansible-galaxy collection install -r requirements.yml + - name: Run lint + run: make role lint + + test: + runs-on: ubuntu-latest + needs: lint + strategy: + matrix: + preset: [minimal, default, performance] + steps: + - uses: actions/checkout@v4 + - name: Setup Docker + run: | + sudo systemctl start docker + sudo usermod -aG docker $USER + - name: Run tests + run: make role test ${{ matrix.preset }} + + deploy-check: + runs-on: ubuntu-latest + needs: [lint, test] + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Check deployment + run: make role deploy + env: + ANSIBLE_HOST_KEY_CHECKING: false +EOF + +# Создание Azure DevOps pipeline +echo "📝 Создание Azure DevOps pipeline..." +cat > azure-pipelines.yml << 'EOF' +trigger: +- main +pool: + vmImage: 'ubuntu-latest' +stages: +- stage: Test + jobs: + - job: TestJob + steps: + - script: make role test +EOF + +# Создание Jenkinsfile +echo "📝 Создание Jenkinsfile..." +cat > Jenkinsfile << 'EOF' +pipeline { + agent any + stages { + stage('Test') { + steps { + sh 'make role test' + } + } + } +} +EOF + +# Создание GitLab CI +echo "📝 Создание GitLab CI..." +cat > .gitlab-ci.yml << 'EOF' +stages: + - test +test: + stage: test + script: + - make role test +EOF + +echo "✅ CI/CD настроен" diff --git a/scripts/test-custom-images.sh b/scripts/test-custom-images.sh new file mode 100755 index 0000000..03b6360 --- /dev/null +++ b/scripts/test-custom-images.sh @@ -0,0 +1,243 @@ +#!/bin/bash +# Скрипт для тестирования собственных образов AnsibleLab +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +set -e + +# Цвета для вывода +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Функция для вывода сообщений +log() { + echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" +} + +success() { + echo -e "${GREEN}✅ $1${NC}" +} + +warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +error() { + echo -e "${RED}❌ $1${NC}" +} + +# Проверка наличия Docker +check_docker() { + log "Проверка Docker..." + if ! command -v docker &> /dev/null; then + error "Docker не установлен!" + exit 1 + fi + success "Docker доступен" +} + +# Проверка наличия образов +check_images() { + log "Проверка наличия собственных образов..." + + local images=( + "inecs/ansible-lab:ansible-controller-latest" + "inecs/ansible-lab:alt-linux-latest" + "inecs/ansible-lab:astra-linux-latest" + "inecs/ansible-lab:redos-latest" + "inecs/ansible-lab:rhel-latest" + "inecs/ansible-lab:centos-latest" + "inecs/ansible-lab:alma-latest" + "inecs/ansible-lab:rocky-latest" + "inecs/ansible-lab:ubuntu-latest" + "inecs/ansible-lab:debian-latest" + ) + + local missing_images=() + + for image in "${images[@]}"; do + if ! docker image inspect "$image" &> /dev/null; then + missing_images+=("$image") + else + success "Образ $image найден" + fi + done + + if [ ${#missing_images[@]} -gt 0 ]; then + warning "Отсутствующие образы:" + for image in "${missing_images[@]}"; do + echo " - $image" + done + echo "" + echo "Для сборки образов выполните:" + echo " make docker build" + echo "" + echo "Или соберите отдельные образы:" + for image in "${missing_images[@]}"; do + # Маппинг образов на имена для сборки + case "$image" in + "inecs/ansible-lab:ansible-controller-latest") + echo " make docker build-image IMAGE=ansible-controller" + ;; + "inecs/ansible-lab:alt-linux-latest") + echo " make docker build-image IMAGE=alt-linux" + ;; + "inecs/ansible-lab:astra-linux-latest") + echo " make docker build-image IMAGE=astra-linux" + ;; + "inecs/ansible-lab:redos-latest") + echo " make docker build-image IMAGE=redos" + ;; + "inecs/ansible-lab:rhel-latest") + echo " make docker build-image IMAGE=rhel" + ;; + "inecs/ansible-lab:centos-latest") + echo " make docker build-image IMAGE=centos" + ;; + "inecs/ansible-lab:alma-latest") + echo " make docker build-image IMAGE=alma" + ;; + "inecs/ansible-lab:rocky-latest") + echo " make docker build-image IMAGE=rocky" + ;; + "inecs/ansible-lab:ubuntu-latest") + echo " make docker build-image IMAGE=ubuntu" + ;; + "inecs/ansible-lab:debian-latest") + echo " make docker build-image IMAGE=debian" + ;; + *) + echo " # Неизвестный образ: $image" + ;; + esac + done + return 1 + fi + + success "Все образы найдены" + return 0 +} + +# Тестирование с минимальным пресетом +test_minimal() { + log "Тестирование с минимальным пресетом (custom-minimal)..." + + if [ -f "molecule/presets/custom-minimal.yml" ]; then + log "Запуск molecule test с пресетом custom-minimal..." + if molecule test --scenario-name custom-minimal; then + success "Тест с custom-minimal прошел успешно" + else + error "Тест с custom-minimal завершился с ошибкой" + return 1 + fi + else + error "Файл molecule/presets/custom-minimal.yml не найден" + return 1 + fi +} + +# Тестирование с полным пресетом +test_full() { + log "Тестирование с полным пресетом (custom-images)..." + + if [ -f "molecule/presets/custom-images.yml" ]; then + log "Запуск molecule test с пресетом custom-images..." + if molecule test --scenario-name custom-images; then + success "Тест с custom-images прошел успешно" + else + error "Тест с custom-images завершился с ошибкой" + return 1 + fi + else + error "Файл molecule/presets/custom-images.yml не найден" + return 1 + fi +} + +# Тестирование производительности +test_performance() { + log "Тестирование производительности (custom-performance)..." + + if [ -f "molecule/presets/custom-performance.yml" ]; then + log "Запуск molecule test с пресетом custom-performance..." + if molecule test --scenario-name custom-performance; then + success "Тест производительности прошел успешно" + else + error "Тест производительности завершился с ошибкой" + return 1 + fi + else + error "Файл molecule/presets/custom-performance.yml не найден" + return 1 + fi +} + +# Очистка после тестов +cleanup() { + log "Очистка после тестов..." + + # Остановка и удаление контейнеров + docker ps -a --filter "name=molecule" --format "{{.Names}}" | xargs -r docker rm -f 2>/dev/null || true + + # Удаление сетей + docker network ls --filter "name=ansible-lab" --format "{{.Name}}" | xargs -r docker network rm 2>/dev/null || true + + success "Очистка завершена" +} + +# Основная функция +main() { + log "🚀 Тестирование собственных образов AnsibleLab" + echo "==========================================" + + # Проверки + check_docker + + if ! check_images; then + error "Не все образы найдены. Завершение." + exit 1 + fi + + # Выбор типа тестирования + case "${1:-minimal}" in + "check") + success "Проверка образов завершена" + ;; + "minimal") + test_minimal + ;; + "full") + test_full + ;; + "performance") + test_performance + ;; + "all") + test_minimal && test_full && test_performance + ;; + *) + echo "Использование: $0 [check|minimal|full|performance|all]" + echo "" + echo " check - проверка наличия образов" + echo " minimal - минимальный тест (4 хоста)" + echo " full - полный тест (все образы)" + echo " performance - тест производительности (8 хостов)" + echo " all - все тесты" + exit 1 + ;; + esac + + # Очистка + cleanup + + success "🎉 Тестирование завершено успешно!" +} + +# Обработка сигналов +trap cleanup EXIT INT TERM + +# Запуск +main "$@" diff --git a/scripts/update-playbooks.sh b/scripts/update-playbooks.sh new file mode 100755 index 0000000..bf0b4a5 --- /dev/null +++ b/scripts/update-playbooks.sh @@ -0,0 +1,222 @@ +#!/bin/bash +# Автоматическое обновление playbook'ов при добавлении новых ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +set -euo pipefail + +echo "🔍 Обнаружение новых ролей..." + +# Получаем список всех ролей +ROLES=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | sed 's|^/||' | grep -v '^$' | tr '\n' ' ') + +echo "📋 Найденные роли: $ROLES" + +# Обновляем molecule/default/site.yml (только если файл не существует) +if [ ! -f "molecule/default/site.yml" ]; then + echo "📝 Создание molecule/default/site.yml..." + cat > molecule/default/site.yml << 'EOF' +--- +# Универсальный playbook для тестирования Ansible ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# +# Этот файл отвечает за: +# 1. Обновление пакетов в контейнерах при запуске тестов +# 2. Установку common tools для корректной работы тестов +# 3. Подготовку окружения для тестирования ролей +# 4. Импорт roles/deploy.yml для запуска ролей + +- name: Подготовка окружения для тестирования + hosts: all + become: true + tasks: + # Обновление кеша пакетов для Debian/Ubuntu + - name: Update package cache (Debian/Ubuntu) + apt: + update_cache: true + cache_valid_time: 3600 + when: ansible_os_family == 'Debian' + changed_when: false + tags: + - setup + - update + + # Обновление кеша пакетов для RHEL/CentOS/AlmaLinux/Rocky + - name: Update package cache (RHEL/CentOS/AlmaLinux/Rocky) + yum: + update_cache: true + when: ansible_os_family == 'RedHat' + changed_when: false + tags: + - setup + - update + + # Обновление кеша пакетов для Alt Linux + - name: Update package cache (Alt Linux) + apt: + update_cache: true + when: ansible_distribution == 'Alt' + changed_when: false + tags: + - setup + - update + + # Установка common tools для всех ОС + - name: Install common tools (Debian/Ubuntu) + apt: + name: + - curl + - jq + - ca-certificates + - iproute2 + - iputils-ping + - procps + - net-tools + - sudo + - vim + - wget + - unzip + - git + state: present + update_cache: false + when: ansible_os_family == 'Debian' + tags: + - setup + - tools + + - name: Install common tools (RHEL/CentOS/AlmaLinux/Rocky) + yum: + name: + - curl + - jq + - ca-certificates + - iproute + - iputils + - procps-ng + - net-tools + - sudo + - vim + - wget + - unzip + - git + state: present + when: ansible_os_family == 'RedHat' + tags: + - setup + - tools + + - name: Install common tools (Alt Linux) + apt: + name: + - curl + - jq + - ca-certificates + - iproute2 + - iputils + - procps + - net-tools + - sudo + - vim + - wget + - unzip + - git + state: present + when: ansible_distribution == 'Alt' + tags: + - setup + - tools + + # Установка Python для Ansible (если не установлен) + - name: Install Python (Debian/Ubuntu) + apt: + name: + - python3 + - python3-pip + - python3-venv + state: present + when: ansible_os_family == 'Debian' + tags: + - setup + - python + + - name: Install Python (RHEL/CentOS/AlmaLinux/Rocky) + yum: + name: + - python3 + - python3-pip + state: present + when: ansible_os_family == 'RedHat' + tags: + - setup + - python + + - name: Install Python (Alt Linux) + apt: + name: + - python3 + - python3-pip + state: present + when: ansible_distribution == 'Alt' + tags: + - setup + - python + + # Создание пользователя для тестирования + - name: Create test user + user: + name: testuser + shell: /bin/bash + create_home: yes + state: present + tags: + - setup + - user + + # Настройка sudo для тестового пользователя + - name: Configure sudo for test user + lineinfile: + path: /etc/sudoers + line: "testuser ALL=(ALL) NOPASSWD:ALL" + state: present + validate: 'visudo -cf %s' + tags: + - setup + - sudo + + # Создание директории для тестов + - name: Create test directory + file: + path: /tmp/ansible-test + state: directory + mode: '0755' + owner: testuser + group: testuser + tags: + - setup + - directory + +- import_playbook: ../../roles/deploy.yml +EOF +else + echo "📝 Файл molecule/default/site.yml уже существует, пропускаем создание" +fi + +# Обновляем roles/deploy.yml +echo "📝 Обновление roles/deploy.yml..." +cat > roles/deploy.yml << EOF +--- +# Playbook для развертывания на продакшн серверах +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Развертывание всех ролей + hosts: all + roles: +EOF + +for role in $ROLES; do + echo " - $role" >> roles/deploy.yml +done + +echo "✅ Playbook'и обновлены" diff --git a/vars/.gitkeep b/vars/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/vault-password.txt b/vault-password.txt deleted file mode 100644 index 2d27916..0000000 --- a/vault-password.txt +++ /dev/null @@ -1 +0,0 @@ -password123 \ No newline at end of file diff --git a/default/files/.gitkeep b/vault/.gitkeep similarity index 100% rename from default/files/.gitkeep rename to vault/.gitkeep diff --git a/vault/secrets.yml b/vault/secrets.yml new file mode 100644 index 0000000..83ad49e --- /dev/null +++ b/vault/secrets.yml @@ -0,0 +1,80 @@ +$ANSIBLE_VAULT;1.1;AES256 +35343565303431363831646439663864653034633332396533656362393138666235353365613631 +6633313964346463653166333131316161643064626539300a366366383264653236643366343861 +36643265643338346263663332663961613132613662303033386563356235666334613763303232 +3332636435353130380a643031343335306330643964363230333363653761376333306232663263 +37613937376662386563366237666630623935653663316235363037613962616663373534633066 +36356639656662653339613534373630326164303536633466613238306530326661343065376632 +63646330376662643836636539333837313366656237626264336130636139376665346162303834 +39366235333833303839646530663963346234316661306663356261316537663333326363326333 +34386536343137333736356139636461653737353062613730326665383761356337663264356539 +64623962363631356131373735643639333065663861336262346366313163303739306663616635 +63386534333936356636623532653339366464346531326562623062353839333563346562383832 +38656166626366653930343436633338363530313138323862353563323033306333353130383732 +63323931336338663663383532313635373166616631333832666330393933646165336164353634 +30666137626131636162333335373961343763383434386166346363626162663538653239633563 +64316539626632346133346339616164646336306331393466306333623638366137613866663263 +37623663316462376330643866303464366236613965663561383561643162393032663266383661 +63643466396433366530613830636666393862383134313165313162663262623536306164313633 +65383031646562356535626363326135656366323462383364306138626163363236333036316534 +36353364626130633965353036636430393035316434393063373062363362663430633462313631 +65373330646531333334623738653537623963663237663137306430656438316665623534313362 +36303934306331393365363866393265646263653830666234333234623266353634393239633337 +32663938613831656138376266333835613561643534663463373238323532313237336132613239 +31383665373964623362623561313161363831316361626432636665343938633437336561363161 +30366136383766356261396533356134326532353938326439303334396333363036363563653030 +33353538316363353637313835636535653136346234316636626533663331653163643466633164 +35633630316162396665626632363036373331343230306665313037336666663066653763653835 +34643532386138363665663238393336356431353464613031336334623761613732646565363730 +34353866616339616164663934626632663130393563646265343461303533653139653137303661 +30663539616162333739313366363861336562346132373861393734323366663863333063396232 +34373435306161383462306136333734303339353231386432313637343236356439626537663530 +33633331376439643732306365366530636134366431396566376330663162336334353031353834 +32636435656131616133643636363965316634626231356630323237613261663665393061616432 +35333031306562626234363061316562373964386236636464633939343437396234313036383561 +31646463313037323133616561633562323765303361346430313134316337626139663665326436 +31616334356663346234663833396635373162346136663062363138373034356638636537353737 +62336563333338343731626665323336386632303162383166346338373864613463326466386361 +37356135376430363038656439376366646238383736636461613034666163623838393236346464 +34356563366234306465366438326265366133663934323663313934313037313663633833343533 +38326163323438376336313065313338303239303766326636326433366566643935626530643537 +61313738313361353835373430386430343738356461633335396165323337623832663330383834 +61666363663939353238623861653962636638303138626435373366336130653565333532616664 +61643734393733646364623937356264306262366266396536656338343366306364663339656236 +63316635623037616266613739326335353066373463643132393331626232303134346233303833 +61303738383961636235616634356435313165613734336438333730353463313366653332626263 +61353731323133393735333664366134633434346130646164336665386264376265316266386665 +65613431303733376637643536646561636163633065393966333161313930356636353936663239 +36326561653132373335616237303764333661303961373139646663653431346338356331373765 +37333865333563333338666338633665316238396438333630306663383164383234636237393562 +32356130653538383632633462303665333733333365343237626262636563346361363764313663 +34306337636665633431353438373661306336396533613936313866623337343538613036353233 +66623936343762383033323830333266643463376138643133643434353135656261393733313433 +38303264303332643361376162303330343666636162396163366365353465623132663831323530 +33346565353262376131623431343538616533326564383637396538343336626336646633353934 +61376462656263663965383137376131643536336539613532373536376231626364643866646535 +38646430326138643339396464366438393263313665636562356631326133313734343562363065 +61663766616633333262623633396363336536373666316536363931333939383838663131613439 +66616663383334363330646638393139313330363533306639623437663763623333343038373838 +63303932663436636361663338346665386531333533633730323735333734376662383835343163 +38623435333662333634376361303734653130663833376264376336663363623966363939623336 +66656532663431333132663734386538663066323230356166356238333564336230633030353233 +61333933333763666564313233333432366231383666333832393035656234326161323332653135 +34323032613535336666633830373866383832393166636565646132633763616230326530346462 +63653638383263323532653261353365313433346534323865616336383864363530643237613061 +32613737353431626366643066663864663866323363396230333335346362373262393332333939 +34393539363836656539623766346336383834323831346261343635346466383164376135353136 +33366333323765616330333735383163663736646466653265326335306366663832643162363035 +39326661313732303830333236653134346534656433366366663539626364663362626135666438 +32356635386262336635396162666334616139353134323366633165626363336338393165663933 +62643431616632653838376239326531643733303636323236613561626534343535383130623766 +66343734396561386661306235393865336236323261356461356264326535316437653131326435 +38663866383332393033356165663032656433383763656431323836353961633437623662303135 +61373836626564373331303362313062313235373731646234393532343430363235326630373831 +35313635643936663438316132623265306531383838633266336563613662386233663937616230 +33333933353831396534356461653537616536633365323364326666323833346432636536643737 +31663065303933316438653864313734366464616137333838643839313437623532333766373763 +35346237383433643032613630396364386464316133343764666431636330333463333037306431 +35353232633463363732346462663230376631363832363239396262643531393831306633663966 +64333136343662343564653935306438663233623332626337613931353861396562663334346537 +353330613139383830303838353838356233