Compare commits

...

5 Commits

Author SHA1 Message Date
8071fba25f feat: Создана полная документация проекта с централизованным хранением
- Создан новый README.md с полной документацией проекта
- Перемещены все MD файлы в папку /docs
- Создана структура документации:
  - docs/universal-lab.md - руководство по лаборатории
  - docs/presets.md - описание всех 21 пресета
  - docs/roles.md - структура и создание Ansible ролей
  - docs/examples.md - практические примеры использования
  - docs/troubleshooting.md - решение проблем
  - docs/api.md - справочник по API

Основные возможности документации:
- Полное описание всех возможностей лаборатории
- 21 готовый пресет для различных сценариев
- Подробные инструкции по использованию
- Примеры создания собственных пресетов
- Руководство по созданию Ansible ролей
- Troubleshooting для решения проблем
- API Reference для всех команд и параметров

Структура проекта:
- README.md - основная документация с ссылками
- docs/ - централизованное хранение документации
- molecule/presets/ - 21 готовый пресет
- files/ - файлы для ролей и playbooks
- scripts/ - скрипты для управления лабораторией

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-10-22 13:29:47 +03:00
d32ca54f7b feat: Добавлены расширенные пресеты для Kubernetes, DinD и DOoD
- Создано 11 новых пресетов для различных конфигураций
- Kubernetes пресеты: single, multi-cluster, istio-full
- DinD пресеты: simple, swarm, compose
- DOoD пресеты: simple, mixed
- Смешанные пресеты: k8s+dind, k8s+dood, full-stack

Kubernetes пресеты:
- k8s-single.yml - одиночный Kind кластер
- k8s-multi.yml - мульти-кластерная конфигурация (dev/staging/prod)
- k8s-istio-full.yml - полный стек Istio с мониторингом

DinD пресеты:
- dind-simple.yml - 3 изолированных Docker среды
- dind-swarm.yml - Docker Swarm кластер (1 manager + 4 workers)
- dind-compose.yml - 4 DinD контейнера для Compose стека

DOoD пресеты:
- dood-simple.yml - 3 DOoD контейнера с доступом к Docker daemon
- dood-mixed.yml - смешанная конфигурация DOoD + systemd

Смешанные пресеты:
- mixed-k8s-dind.yml - Kubernetes + DinD
- mixed-k8s-dood.yml - Kubernetes + DOoD
- mixed-full.yml - полная гибридная конфигурация

Обновлена документация:
- README с описанием всех 21 пресета
- Категоризация по типам (классические, k8s, dind, dood, смешанные)
- Примеры использования для каждого пресета
- Рекомендации по выбору подходящего пресета

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-10-22 13:23:01 +03:00
b1bae8af9f feat: Добавлены пресеты для различных сценариев тестирования (1-20 машин)
- Создано 10 готовых пресетов для разных типов инфраструктуры
- Минимальная лаборатория (1-3 машины) - базовое тестирование
- Веб-приложение (3-5 машин) - классическая архитектура
- Микросервисы (5-8 машин) - современная архитектура
- Высокая доступность (6-10 машин) - отказоустойчивость
- Kubernetes кластер (8-12 машин) - контейнерная оркестрация
- CI/CD пайплайн (10-15 машин) - автоматизация разработки
- Big Data кластер (12-18 машин) - обработка больших данных
- Service Mesh (15-20 машин) - микросервисная архитектура
- Enterprise (18-20 машин) - корпоративная инфраструктура
- Максимальный (20 машин) - экстремальные условия

Каждый пресет включает:
- Подробное описание архитектуры
- Различные группы хостов (webservers, databases, monitoring)
- Смешанные семейства ОС (debian/rhel)
- Настроенные порты и сервисы
- Готовые команды для запуска

Документация:
- README с описанием всех пресетов
- Примеры использования
- Рекомендации по выбору
- Troubleshooting

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-10-22 13:15:11 +03:00
33ada54c12 feat: Завершена реализация универсальной лаборатории
- Добавлена полная поддержка Istio service mesh с Kiali
- Интегрированы Helm charts (nginx, prometheus-stack)
- Созданы Grafana дашборды для Istio мониторинга
- Добавлен HTML генератор отчетов с красивым дизайном
- Созданы скрипты для снапшотов и восстановления
- Добавлена поддержка Istio Bookinfo demo
- Обновлена документация с полным описанием возможностей

Компоненты:
- Istio с Telemetry и Traffic Policy
- Prometheus + Grafana с автопровижинингом дашбордов
- HTML отчеты с анализом статусов
- Снапшоты и восстановление состояния
- Полная интеграция с Kubernetes

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-10-22 13:08:55 +03:00
b4881da7c5 feat: Добавлена универсальная лаборатория для тестирования Ansible ролей
- Создана структура molecule/universal/ с поддержкой DinD и DOoD
- Добавлена поддержка Kind кластеров для Kubernetes тестирования
- Интегрированы Helm charts (nginx, prometheus-stack)
- Добавлена поддержка Istio service mesh с Kiali
- Создан Makefile с lab-целями для управления лабораторией
- Добавлена поддержка Prometheus + Grafana с автопровижинингом
- Создан README с подробной документацией

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-10-22 13:01:53 +03:00
50 changed files with 6370 additions and 61 deletions

0
.cursor/commands/docs.md Normal file
View File

114
Makefile
View File

@@ -155,3 +155,117 @@ git:
echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \
*) echo "Unknown action. Available actions: push, pull, cluster-branch";; \
esac
# ====== УНИВЕРСАЛЬНАЯ ЛАБОРАТОРИЯ (Molecule universal) ======
SCENARIO ?= universal
COMPOSE ?= docker compose
lab-up: ## Поднять контроллер
$(COMPOSE) up -d
lab-down: ## Погасить контроллер
$(COMPOSE) down -v
lab-sh: ## Войти в контроллер
docker exec -it ansible-controller bash
lab-test: lab-up ## Полный цикл Molecule (create+converge+verify+destroy)
docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \
bash -lc 'cd /ansible && molecule test -s $(SCENARIO)'
lab-create: lab-up ## Создать инфраструктуру лаборатории
docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \
bash -lc 'cd /ansible && molecule create -s $(SCENARIO)'
lab-converge: ## Запустить роли в лаборатории
docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \
bash -lc 'cd /ansible && molecule converge -s $(SCENARIO)'
lab-verify: ## Проверить работу лаборатории
docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \
bash -lc 'cd /ansible && molecule verify -s $(SCENARIO)'
lab-destroy: ## Уничтожить инфраструктуру лаборатории
docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \
bash -lc 'cd /ansible && molecule destroy -s $(SCENARIO)'
lab-reset: lab-destroy lab-down lab-up ## Полный сброс лаборатории
# ====== K8S ХЕЛПЕРЫ ======
kube-sh: ## Shell с kubectl/helm/istioctl внутри контейнера
docker exec -it ansible-controller bash
kube-cmd: ## make kube-cmd CLUSTER=lab CMD="get pods -A"
ifeq ($(strip $(CLUSTER)),)
@echo "Usage: make kube-cmd CLUSTER=lab CMD=\"get pods -A\""; exit 1
endif
docker exec -it ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) $(CMD)'
kube-enter: ## make kube-enter CLUSTER=lab
ifeq ($(strip $(CLUSTER)),)
@echo "Usage: make kube-enter CLUSTER=lab"; exit 1
endif
docker exec -it ansible-controller bash -lc '\
POD=$$(kubectl --context kind-$(CLUSTER) -n lab-demo get pod -l app=toolbox -o jsonpath="{.items[0].metadata.name}"); \
[ -n "$$POD" ] || { echo "toolbox pod not found"; exit 1; }; \
kubectl --context kind-$(CLUSTER) -n lab-demo exec -it $$POD -- /bin/sh'
# Port-forward Kiali (http://localhost:20001)
kiali-port-forward: ## make kiali-port-forward CLUSTER=lab
ifeq ($(strip $(CLUSTER)),)
@echo "Usage: make kiali-port-forward CLUSTER=lab"; exit 1
endif
docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n istio-system port-forward svc/kiali 20001:20001'
# Port-forward Istio IngressGateway (HTTP 8082, HTTPS 8444)
istio-gw-port-forward: ## make istio-gw-port-forward CLUSTER=lab
ifeq ($(strip $(CLUSTER)),)
@echo "Usage: make istio-gw-port-forward CLUSTER=lab"; exit 1
endif
docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n istio-system port-forward svc/istio-ingressgateway 8082:80 8444:443'
@echo "Istio GW forwarded: http://localhost:8082 https://localhost:8444"
# Port-forward Grafana (http://localhost:3000)
grafana-port-forward: ## make grafana-port-forward CLUSTER=lab
ifeq ($(strip $(CLUSTER)),)
@echo "Usage: make grafana-port-forward CLUSTER=lab"; exit 1
endif
docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n monitoring port-forward svc/monitoring-grafana 3000:80'
@echo "Grafana: http://localhost:3000 (admin/admin)"
# Port-forward Prometheus (http://localhost:9090)
prom-port-forward: ## make prom-port-forward CLUSTER=lab
ifeq ($(strip $(CLUSTER)),)
@echo "Usage: make prom-port-forward CLUSTER=lab"; exit 1
endif
docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n monitoring port-forward svc/monitoring-kube-prometheus-prometheus 9090:9090'
@echo "Prometheus: http://localhost:9090"
# Stop all port-forwards
kube-pf-stop: ## убить все port-forward в контроллере
docker exec -it ansible-controller bash -lc 'pkill -f "kubectl .* port-forward" || true'
# ====== ОТЧЕТЫ ======
lab-report: ## Сгенерировать HTML отчет
docker exec ansible-controller bash -lc 'python3 /ansible/scripts/report_html.py /ansible/reports/lab-health.json /ansible/reports/lab-report.html'
@echo "HTML report: reports/lab-report.html"
# ====== ДОПОЛНИТЕЛЬНЫЕ ХЕЛПЕРЫ ======
bookinfo-url: ## echo productpage URL via Istio Gateway (needs istio-gw-port-forward first)
@echo "Open: http://localhost:8082/productpage"
grafana-open: ## echo URL to Grafana + hint dashboards
@echo "Grafana: http://localhost:3000 (admin/admin)"
@echo "Dashboards:"
@echo " - Istio • Overview (uid: istio-overview)"
@echo " - Service • SLI (uid: service-sli)"
# ====== СНАПШОТЫ И ОЧИСТКА ======
lab-snapshot: ## Сохранить снапшот лаборатории
bash scripts/snapshot.sh
lab-restore: ## Восстановить из снапшота
bash scripts/restore.sh
lab-cleanup: ## Очистить лабораторию
bash scripts/cleanup.sh

454
README.md
View File

@@ -1,62 +1,418 @@
# AnsibleTemplate
# Ansible Template - Универсальная лаборатория для тестирования Ansible ролей
Темплейт для создания, проверки и тестирование ролей Ansible с помощью контейнеров Docker.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Ansible](https://img.shields.io/badge/Ansible-2.15+-blue.svg)](https://www.ansible.com/)
[![Molecule](https://img.shields.io/badge/Molecule-5.0+-green.svg)](https://molecule.readthedocs.io/)
[![Docker](https://img.shields.io/badge/Docker-20.0+-blue.svg)](https://www.docker.com/)
### С чего начать?
## 📋 Описание
На вашей машине вам необходимо сбилдить образ, где будут запускаться все роли через docker-compose.
**Ansible Template** - это универсальная лаборатория для тестирования Ansible ролей в различных конфигурациях. Проект предоставляет гибкую и мощную среду для тестирования Ansible ролей, включая Docker-in-Docker (DinD), Docker-outside-of-Docker (DOoD), кластеры Kubernetes (Kind), Istio, Kiali, Prometheus и Grafana.
Это можно сделать самостоятельно:
### 🎯 Основные возможности
- **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)
- **Динамическое создание инфраструктуры** - автоматическое развертывание Docker контейнеров и Kind кластеров
- **Поддержка различных ОС** - тестирование ролей на Debian и RHEL-подобных системах
- **Docker-in-Docker (DinD)** - изолированные Docker-среды внутри контейнеров
- **Docker-outside-of-Docker (DOoD)** - использование Docker-демона хоста из контейнера
- **Kubernetes кластеры** - полноценные Kind кластеры с аддонами
- **Service Mesh** - Istio с Kiali для визуализации
- **Мониторинг** - Prometheus, Grafana, Jaeger для полной наблюдаемости
- **21 готовый пресет** - от простых до экстремально сложных сценариев
- **HTML отчеты** - красивые отчеты о результатах тестирования
- **Снапшоты** - сохранение и восстановление состояния лаборатории
Или ввести команду:
## 🚀 Быстрый старт
- **make init** - которая создаст файл секретов с паролем. Сбилдит образ. И создаст новую роль.
### Предварительные требования
### Работа с ролью
- **make role new** - создать новую роль из шаблона. Название роли пишется на английском, описание роли на любом языке
- **make role lint** - проверяет все роли в папке roles/* на наличие ошибок
- **make role test** - позволяет тестировать роль, указанную в molecule/default/converge.yml
сразу на двух контейнерах (RedHat и Ubuntu)
- **make role deploy** - запускает роль в продакшен. Все хосты берет из файла inventory/hosts
- Docker 20.0+
- Docker Compose 2.0+
- Make
- Git
### Работа с файлом переменных
### Установка
Все переменные защищены через **Ansible-Vault** и находятся в папке vars/secrets.yml
```bash
# Клонировать репозиторий
git clone https://github.com/your-username/ansible-template.git
cd ansible-template
Для смены пароля измените его в файле **./vault-password.txt**
# Создать необходимые файлы
echo "your-vault-password" > vault-password.txt
mkdir -p roles
mkdir -p files/playbooks
- **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
# Установить pre-commit хуки (опционально)
make pre-commit-install
```
Помните, что образ обязательно должен содержать python не ниже версии 3.12 и systemd для нормального тестирования ролей.
### Первый запуск
```bash
# Поднять контроллер
make lab-up
# Запустить минимальную лабораторию
make lab-test LAB_SPEC=molecule/presets/minimal.yml
# Посмотреть отчет
make lab-report
```
## 📚 Документация
### Основные разделы
- **[Универсальная лаборатория](docs/universal-lab.md)** - полное руководство по работе с лабораторией
- **[Пресеты](docs/presets.md)** - описание всех 21 готового пресета
- **[Роли](docs/roles.md)** - структура и создание Ansible ролей
### Дополнительные материалы
- **[Примеры использования](docs/examples.md)** - практические примеры
- **[Troubleshooting](docs/troubleshooting.md)** - решение проблем
- **[API Reference](docs/api.md)** - справочник по API
## 🎛️ Пресеты
### Классические пресеты (systemd контейнеры)
| Пресет | Машины | Описание | Команда |
|--------|--------|----------|---------|
| `minimal.yml` | 1-3 | Базовая конфигурация | `make lab-test LAB_SPEC=molecule/presets/minimal.yml` |
| `webapp.yml` | 3-5 | Веб-приложение | `make lab-test LAB_SPEC=molecule/presets/webapp.yml` |
| `microservices.yml` | 5-8 | Микросервисы | `make lab-test LAB_SPEC=molecule/presets/microservices.yml` |
| `ha.yml` | 6-10 | Высокая доступность | `make lab-test LAB_SPEC=molecule/presets/ha.yml` |
| `k8s-cluster.yml` | 8-12 | Kubernetes кластер | `make lab-test LAB_SPEC=molecule/presets/k8s-cluster.yml` |
| `cicd.yml` | 10-15 | CI/CD пайплайн | `make lab-test LAB_SPEC=molecule/presets/cicd.yml` |
| `bigdata.yml` | 12-18 | Big Data кластер | `make lab-test LAB_SPEC=molecule/presets/bigdata.yml` |
| `servicemesh.yml` | 15-20 | Service Mesh | `make lab-test LAB_SPEC=molecule/presets/servicemesh.yml` |
| `enterprise.yml` | 18-20 | Enterprise | `make lab-test LAB_SPEC=molecule/presets/enterprise.yml` |
| `maximum.yml` | 20 | Максимальный | `make lab-test LAB_SPEC=molecule/presets/maximum.yml` |
### Kubernetes пресеты
| Пресет | Описание | Команда |
|--------|----------|---------|
| `k8s-single.yml` | Одиночный Kind кластер | `make lab-test LAB_SPEC=molecule/presets/k8s-single.yml` |
| `k8s-multi.yml` | Мульти-кластер (dev/staging/prod) | `make lab-test LAB_SPEC=molecule/presets/k8s-multi.yml` |
| `k8s-istio-full.yml` | Полный стек Istio | `make lab-test LAB_SPEC=molecule/presets/k8s-istio-full.yml` |
### Docker пресеты
| Пресет | Тип | Описание | Команда |
|--------|-----|----------|---------|
| `dind-simple.yml` | DinD | 3 изолированных Docker среды | `make lab-test LAB_SPEC=molecule/presets/dind-simple.yml` |
| `dind-swarm.yml` | DinD | Docker Swarm кластер | `make lab-test LAB_SPEC=molecule/presets/dind-swarm.yml` |
| `dind-compose.yml` | DinD | Docker Compose стеки | `make lab-test LAB_SPEC=molecule/presets/dind-compose.yml` |
| `dood-simple.yml` | DOoD | 3 DOoD контейнера | `make lab-test LAB_SPEC=molecule/presets/dood-simple.yml` |
| `dood-mixed.yml` | DOoD | Смешанная конфигурация | `make lab-test LAB_SPEC=molecule/presets/dood-mixed.yml` |
### Смешанные пресеты
| Пресет | Описание | Команда |
|--------|----------|---------|
| `mixed-k8s-dind.yml` | Kubernetes + DinD | `make lab-test LAB_SPEC=molecule/presets/mixed-k8s-dind.yml` |
| `mixed-k8s-dood.yml` | Kubernetes + DOoD | `make lab-test LAB_SPEC=molecule/presets/mixed-k8s-dood.yml` |
| `mixed-full.yml` | Полная гибридная конфигурация | `make lab-test LAB_SPEC=molecule/presets/mixed-full.yml` |
## 🛠️ Основные команды
### Управление лабораторией
```bash
# Поднять контроллер
make lab-up
# Погасить контроллер
make lab-down
# Полный цикл тестирования
make lab-test
# Создать инфраструктуру
make lab-create
# Запустить роли
make lab-converge
# Проверить работу
make lab-verify
# Уничтожить инфраструктуру
make lab-destroy
# Полный сброс
make lab-reset
```
### Снапшоты и восстановление
```bash
# Сохранить снапшот
make lab-snapshot
# Восстановить из снапшота
make lab-restore
# Очистить лабораторию
make lab-cleanup
```
### Kubernetes команды
```bash
# Войти в контейнер с kubectl
make kube-sh
# Выполнить kubectl команду
make kube-cmd CLUSTER=lab CMD="get pods -A"
# Войти в кластер
make kube-enter CLUSTER=lab
# Port-forward Kiali
make kiali-port-forward CLUSTER=lab
# Port-forward Istio Gateway
make istio-gw-port-forward CLUSTER=lab
# Port-forward Grafana
make grafana-port-forward CLUSTER=lab
# Port-forward Prometheus
make prom-port-forward CLUSTER=lab
# Остановить все port-forward
make kube-pf-stop
```
### Отчеты и мониторинг
```bash
# Сгенерировать HTML отчет
make lab-report
# Открыть Grafana
make grafana-open
# Получить URL Bookinfo
make bookinfo-url
```
## 🔧 Создание собственных пресетов
### Структура пресета
```yaml
---
# ПРЕСЕТ: Название (количество машин)
#
# Описание: Подробное описание пресета
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/your-preset.yml
#
# Автор: Ваше имя
# Сайт: https://your-site.com
docker_network: labnet
# Kind кластеры (опционально)
kind_clusters:
- name: your-cluster
workers: 2
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
prometheus_stack: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
# Образы для разных семейств ОС
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
# Настройки по умолчанию для 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: host1
family: debian
group: webservers
publish:
- "8080:80"
- name: host2
type: dind
group: dind
publish:
- "2375:2375"
- name: host3
type: dood
family: rhel
group: dood
publish:
- "8081:80"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
```
### Типы хостов
- **systemd** - обычные контейнеры с systemd (по умолчанию)
- **dind** - Docker-in-Docker контейнеры
- **dood** - Docker-outside-of-Docker контейнеры
### Семейства ОС
- **debian** - Debian/Ubuntu системы
- **rhel** - RHEL/CentOS системы
### Группы хостов
Можно создавать любые группы для организации хостов:
```yaml
hosts:
- name: web1
group: webservers
- name: db1
group: databases
- name: cache1
group: caches
```
### Публикация портов
```yaml
publish:
- "8080:80" # HTTP
- "8443:443" # HTTPS
- "3306:3306" # MySQL
- "5432:5432" # PostgreSQL
```
### Переменные окружения
```yaml
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
DATABASE_URL: "postgresql://user:pass@db:5432/mydb"
DEBUG: "true"
```
## 📁 Структура проекта
```
ansible-template/
├── README.md # Основная документация
├── Makefile # Команды управления
├── docker-compose.yaml # Docker Compose конфигурация
├── vault-password.txt # Пароль для Ansible Vault
├── docs/ # Документация
│ ├── universal-lab.md # Руководство по лаборатории
│ ├── presets.md # Описание пресетов
│ ├── roles.md # Структура ролей
│ ├── examples.md # Примеры использования
│ ├── troubleshooting.md # Решение проблем
│ └── api.md # API Reference
├── molecule/ # Molecule конфигурация
│ ├── universal/ # Универсальный сценарий
│ │ ├── molecule.yml # Конфигурация Molecule
│ │ ├── vars.yml # Переменные по умолчанию
│ │ ├── create.yml # Создание инфраструктуры
│ │ └── verify.yml # Проверка работы
│ └── presets/ # Готовые пресеты
│ ├── minimal.yml # Минимальная лаборатория
│ ├── webapp.yml # Веб-приложение
│ ├── k8s-single.yml # Kubernetes single
│ ├── dind-simple.yml # DinD simple
│ ├── dood-simple.yml # DOoD simple
│ └── ... # Другие пресеты
├── files/ # Файлы для ролей
│ ├── playbooks/ # Ansible playbooks
│ ├── k8s/ # Kubernetes манифесты
│ ├── grafana/ # Grafana дашборды
│ └── requirements.yml # Ansible коллекции
├── roles/ # Ansible роли
│ └── your_role/ # Ваши роли
├── scripts/ # Скрипты
│ ├── report_html.py # Генератор HTML отчетов
│ ├── snapshot.sh # Создание снапшотов
│ ├── restore.sh # Восстановление снапшотов
│ └── cleanup.sh # Очистка лаборатории
└── .pre-commit-config.yaml # Pre-commit конфигурация
```
## 🤝 Участие в разработке
### Установка для разработки
```bash
# Клонировать репозиторий
git clone https://github.com/your-username/ansible-template.git
cd ansible-template
# Установить pre-commit хуки
make pre-commit-install
# Запустить тесты
make lab-test
```
### Создание нового пресета
1. Создать файл в `molecule/presets/your-preset.yml`
2. Добавить описание в `docs/presets.md`
3. Протестировать: `make lab-test LAB_SPEC=molecule/presets/your-preset.yml`
4. Создать Pull Request
### Создание новой роли
1. Создать структуру роли в `roles/your-role/`
2. Добавить описание в `docs/roles.md`
3. Протестировать с подходящим пресетом
4. Создать Pull Request
## 📄 Лицензия
Этот проект распространяется под лицензией MIT. См. файл [LICENSE](LICENSE) для подробностей.
## 👥 Авторы
- **Сергей Антропов** - *Основной разработчик* - [devops.org.ru](https://devops.org.ru)
## 🙏 Благодарности
- [Ansible](https://www.ansible.com/) - за отличный инструмент автоматизации
- [Molecule](https://molecule.readthedocs.io/) - за фреймворк тестирования
- [Docker](https://www.docker.com/) - за контейнеризацию
- [Kubernetes](https://kubernetes.io/) - за оркестрацию
- [Istio](https://istio.io/) - за service mesh
## 📞 Поддержка
- **Документация**: [docs/](docs/)
- **Issues**: [GitHub Issues](https://github.com/your-username/ansible-template/issues)
- **Discussions**: [GitHub Discussions](https://github.com/your-username/ansible-template/discussions)
- **Сайт**: [devops.org.ru](https://devops.org.ru)
---
**Сделано с ❤️ для сообщества DevOps**

View File

@@ -1,12 +1,32 @@
version: "3.9"
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
ansible-controller:
image: quay.io/ansible/creator-ee:latest
container_name: ansible-controller
privileged: true
command: sleep infinity
environment:
DOCKER_HOST: unix:///var/run/docker.sock
ANSIBLE_VAULT_PASSWORD_FILE: /ansible/vault-password.txt
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./molecule:/ansible/molecule
- ./files:/ansible/files
- ./vault-password.txt:/ansible/vault-password.txt
# каталог с ролями (локальный или внешний)
- ${ROLES_DIR:-./roles}:/ansible/roles:ro
working_dir: /ansible
# Обратная совместимость
# 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

572
docs/api.md Normal file
View File

@@ -0,0 +1,572 @@
# API Reference
## Автор
Сергей Антропов
Сайт: https://devops.org.ru
## Описание
Этот документ содержит справочник по API универсальной лаборатории, включая все доступные команды, параметры и конфигурации.
## Содержание
- [Makefile команды](#makefile-команды)
- [Пресеты API](#пресеты-api)
- [Kubernetes API](#kubernetes-api)
- [Docker API](#docker-api)
- [Molecule API](#molecule-api)
- [Отчеты API](#отчеты-api)
- [Скрипты API](#скрипты-api)
## Makefile команды
### Основные команды
| Команда | Описание | Параметры |
|---------|----------|-----------|
| `make lab-up` | Поднять контроллер | - |
| `make lab-down` | Погасить контроллер | - |
| `make lab-sh` | Войти в контроллер | - |
| `make lab-test` | Полный цикл Molecule | `SCENARIO=universal` |
| `make lab-create` | Создать инфраструктуру | - |
| `make lab-converge` | Запустить роли | - |
| `make lab-verify` | Проверить работу | - |
| `make lab-destroy` | Уничтожить инфраструктуру | - |
| `make lab-reset` | Полный сброс | - |
### Kubernetes команды
| Команда | Описание | Параметры |
|---------|----------|-----------|
| `make kube-sh` | Shell с kubectl | - |
| `make kube-cmd` | Выполнить kubectl команду | `CLUSTER=lab CMD="get pods"` |
| `make kube-enter` | Войти в кластер | `CLUSTER=lab` |
| `make kiali-port-forward` | Port-forward Kiali | `CLUSTER=lab` |
| `make istio-gw-port-forward` | Port-forward Istio Gateway | `CLUSTER=lab` |
| `make grafana-port-forward` | Port-forward Grafana | `CLUSTER=lab` |
| `make prom-port-forward` | Port-forward Prometheus | `CLUSTER=lab` |
| `make kube-pf-stop` | Остановить все port-forward | - |
### Отчеты и мониторинг
| Команда | Описание | Параметры |
|---------|----------|-----------|
| `make lab-report` | Сгенерировать HTML отчет | - |
| `make lab-snapshot` | Сохранить снапшот | - |
| `make lab-restore` | Восстановить из снапшота | - |
| `make lab-cleanup` | Очистить лабораторию | - |
| `make bookinfo-url` | Получить URL Bookinfo | - |
| `make grafana-open` | Открыть Grafana | - |
### Pre-commit команды
| Команда | Описание | Параметры |
|---------|----------|-----------|
| `make pre-commit-install` | Установить pre-commit хуки | - |
| `make pre-commit-run` | Запустить pre-commit | - |
## Пресеты API
### Структура пресета
```yaml
---
# ПРЕСЕТ: Название (количество машин)
#
# Описание: Подробное описание пресета
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/your-preset.yml
#
# Автор: Ваше имя
# Сайт: https://your-site.com
# Сеть для лаборатории
docker_network: labnet
# Kind кластеры (опционально)
kind_clusters:
- name: cluster-name
workers: 2
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
prometheus_stack: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
# Образы для разных семейств ОС
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
# Настройки по умолчанию для 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: host-name
family: debian|rhel
type: systemd|dind|dood
group: group-name
publish:
- "host-port:container-port"
env:
KEY: value
volumes:
- "host-path:container-path"
tmpfs:
- "/tmp"
capabilities:
- "SYS_ADMIN"
```
### Параметры хостов
| Параметр | Тип | Описание | Обязательный |
|----------|-----|----------|--------------|
| `name` | string | Имя хоста | Да |
| `family` | string | Семейство ОС (debian/rhel) | Нет |
| `type` | string | Тип контейнера (systemd/dind/dood) | Нет |
| `group` | string | Группа хоста | Нет |
| `publish` | array | Публикация портов | Нет |
| `env` | object | Переменные окружения | Нет |
| `volumes` | array | Монтирование томов | Нет |
| `tmpfs` | array | Временные файловые системы | Нет |
| `capabilities` | array | Capabilities | Нет |
### Параметры Kind кластеров
| Параметр | Тип | Описание | Обязательный |
|----------|-----|----------|--------------|
| `name` | string | Имя кластера | Да |
| `workers` | integer | Количество worker узлов | Нет |
| `api_port` | integer | Порт API сервера | Нет |
| `addons` | object | Включенные аддоны | Нет |
| `ingress_host_http_port` | integer | HTTP порт для ingress | Нет |
| `ingress_host_https_port` | integer | HTTPS порт для ingress | Нет |
### Аддоны Kind кластеров
| Аддон | Тип | Описание |
|-------|-----|----------|
| `ingress_nginx` | boolean | Ingress NGINX контроллер |
| `metrics_server` | boolean | Metrics Server для метрик |
| `istio` | boolean | Istio service mesh |
| `kiali` | boolean | Kiali для визуализации |
| `prometheus_stack` | boolean | Prometheus + Grafana |
## Kubernetes API
### kubectl команды
```bash
# Получить информацию о кластере
kubectl cluster-info
# Получить ноды
kubectl get nodes
# Получить поды
kubectl get pods -A
# Получить сервисы
kubectl get svc -A
# Получить события
kubectl get events --sort-by=.metadata.creationTimestamp
# Описать ресурс
kubectl describe pod <pod-name>
# Логи пода
kubectl logs <pod-name>
# Войти в под
kubectl exec -it <pod-name> -- /bin/sh
```
### Port-forward команды
```bash
# Port-forward сервиса
kubectl port-forward svc/<service-name> <local-port>:<remote-port>
# Port-forward пода
kubectl port-forward pod/<pod-name> <local-port>:<remote-port>
# Port-forward в фоне
kubectl port-forward svc/<service-name> <local-port>:<remote-port> &
# Остановить все port-forward
pkill -f "kubectl .* port-forward"
```
### Istio команды
```bash
# Проверить Istio
istioctl version
# Установить Istio
istioctl install --set profile=demo
# Удалить Istio
istioctl uninstall --purge
# Проверить статус
istioctl proxy-status
# Получить конфигурацию
istioctl proxy-config cluster <pod-name>
```
## Docker API
### Docker команды
```bash
# Список контейнеров
docker ps
# Список образов
docker images
# Список сетей
docker network ls
# Список томов
docker volume ls
# Информация о контейнере
docker inspect <container-name>
# Логи контейнера
docker logs <container-name>
# Войти в контейнер
docker exec -it <container-name> /bin/sh
```
### Docker Compose команды
```bash
# Запустить стек
docker-compose up -d
# Остановить стек
docker-compose down
# Логи стека
docker-compose logs
# Масштабирование
docker-compose up --scale service=3
```
### Docker Swarm команды
```bash
# Инициализировать Swarm
docker swarm init
# Присоединиться к Swarm
docker swarm join --token <token> <manager-ip>:2377
# Список нод
docker node ls
# Создать сервис
docker service create --name <service-name> <image>
# Масштабировать сервис
docker service scale <service-name>=3
```
## Molecule API
### Molecule команды
```bash
# Создать сценарий
molecule init scenario <scenario-name>
# Создать роль
molecule init role <role-name>
# Проверить синтаксис
molecule syntax
# Проверить конфигурацию
molecule lint
# Валидация
molecule validate
# Создать инфраструктуру
molecule create
# Запустить роли
molecule converge
# Проверить работу
molecule verify
# Уничтожить инфраструктуру
molecule destroy
# Полный цикл
molecule test
```
### Конфигурация molecule.yml
```yaml
---
driver:
name: docker
platforms:
- name: instance
image: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
privileged: true
pre_build_image: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
capabilities:
- "SYS_ADMIN"
tmpfs:
- "/run"
- "/run/lock"
provisioner:
name: ansible
config_options:
defaults:
stdout_callback: default
callbacks_enabled: profile_tasks
env:
ANSIBLE_STDOUT_CALLBACK: default
dependency:
name: galaxy
enabled: false
verifier:
name: ansible
lint: |-
set -e
ansible-lint
```
## Отчеты API
### HTML отчет
```bash
# Генерация отчета
python3 scripts/report_html.py <input.json> <output.html>
# Параметры
# input.json - JSON файл с данными
# output.html - HTML файл для вывода
```
### JSON структура
```json
{
"timestamp": "2024-01-01T00:00:00Z",
"idempotence_raw": "changed=0",
"haproxy_select1": "1",
"helm_ingress_toolbox_raw": "ingress ready",
"istio_kiali_raw": "istio-system pods running",
"istio_bookinfo_raw": "bookinfo deployed",
"k8s_overview_raw": "nodes ready"
}
```
### HTML структура
```html
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Lab Report</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
/* CSS стили */
</style>
</head>
<body>
<div class="container">
<div class="hdr">
<h1>Ansible Lab Report</h1>
<div class="time">generated: timestamp</div>
</div>
<div class="grid">
<!-- Отчеты -->
</div>
</div>
</body>
</html>
```
## Скрипты API
### snapshot.sh
```bash
#!/usr/bin/env bash
# Создание снапшотов лаборатории
# Параметры
OUT_DIR="snapshots"
# Создать директорию
mkdir -p "$OUT_DIR"
# Получить ID контейнеров
ids=$(docker ps -q --filter "label=ansible.lab=true")
# Создать снапшоты
for id in $ids; do
name=$(docker inspect --format '{{.Name}}' "$id" | sed 's#^/##')
img="lab-snap-$name:latest"
echo "[snapshot] $name -> $img"
docker commit "$id" "$img" >/dev/null
echo "$img" > "$OUT_DIR/$name.image"
done
```
### restore.sh
```bash
#!/usr/bin/env bash
# Восстановление из снапшотов
# Параметры
IN_DIR="snapshots"
# Проверить директорию
[ -d "$IN_DIR" ] || { echo "No snapshots dir"; exit 1; }
# Восстановить контейнеры
for f in "$IN_DIR"/*.image; do
[ -f "$f" ] || continue
name=$(basename "$f" .image)
img=$(cat "$f")
echo "[restore] $name from $img"
docker rm -f "$name" >/dev/null 2>&1 || true
docker run -d --name "$name" "$img" >/dev/null
done
```
### cleanup.sh
```bash
#!/usr/bin/env bash
# Очистка лаборатории
echo "[cleanup] removing lab containers/volumes/networks"
# Удалить контейнеры
docker ps -aq --filter "label=ansible.lab=true" | xargs -r docker rm -f
# Удалить тома
docker volume ls -q --filter "name=_docker$" | xargs -r docker volume rm
# Удалить сеть
docker network rm labnet >/dev/null 2>&1 || true
echo "done."
```
## Переменные окружения
### Основные переменные
| Переменная | Описание | Значение по умолчанию |
|------------|----------|----------------------|
| `LAB_SPEC` | Путь к пресету | `molecule/presets/minimal.yml` |
| `SCENARIO` | Сценарий Molecule | `universal` |
| `COMPOSE` | Docker Compose команда | `docker compose` |
| `ROLES_DIR` | Директория с ролями | `./roles` |
| `LAB_PAUSE_MINUTES` | Пауза для ручной проверки | `10` |
### Kubernetes переменные
| Переменная | Описание | Значение по умолчанию |
|------------|----------|----------------------|
| `KUBECONFIG` | Путь к kubeconfig | `~/.kube/config` |
| `KUBE_CONTEXT` | Контекст Kubernetes | `kind-lab` |
| `ISTIO_VERSION` | Версия Istio | `1.22.1` |
| `KIND_VERSION` | Версия Kind | `v0.23.0` |
### Docker переменные
| Переменная | Описание | Значение по умолчанию |
|------------|----------|----------------------|
| `DOCKER_HOST` | Docker daemon адрес | `unix:///var/run/docker.sock` |
| `DOCKER_TLS_CERTDIR` | Директория TLS сертификатов | `""` |
| `DOCKER_BUILDKIT` | Использовать BuildKit | `1` |
## Конфигурационные файлы
### docker-compose.yaml
```yaml
version: "3.9"
services:
ansible-controller:
image: quay.io/ansible/creator-ee:latest
container_name: ansible-controller
privileged: true
command: sleep infinity
environment:
DOCKER_HOST: unix:///var/run/docker.sock
ANSIBLE_VAULT_PASSWORD_FILE: /ansible/vault-password.txt
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./molecule:/ansible/molecule
- ./files:/ansible/files
- ./vault-password.txt:/ansible/vault-password.txt
- ${ROLES_DIR:-./roles}:/ansible/roles:ro
working_dir: /ansible
```
### .pre-commit-config.yaml
```yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/ansible/ansible-lint
rev: v6.17.2
hooks:
- id: ansible-lint
```
## Заключение
Этот справочник содержит все необходимые API для работы с универсальной лабораторией. Для получения дополнительной информации обратитесь к [основной документации](universal-lab.md) и [примерам использования](examples.md).

462
docs/examples.md Normal file
View File

@@ -0,0 +1,462 @@
# Примеры использования
## Автор
Сергей Антропов
Сайт: https://devops.org.ru
## Описание
Этот документ содержит практические примеры использования универсальной лаборатории для различных сценариев тестирования Ansible ролей.
## Содержание
- [Базовые примеры](#базовые-примеры)
- [Kubernetes примеры](#kubernetes-примеры)
- [Docker примеры](#docker-примеры)
- [Смешанные примеры](#смешанные-примеры)
- [Мониторинг и отчеты](#мониторинг-и-отчеты)
- [Troubleshooting](#troubleshooting)
## Базовые примеры
### Пример 1: Тестирование веб-сервера
```bash
# Запустить веб-приложение пресет
make lab-test LAB_SPEC=molecule/presets/webapp.yml
# Проверить статус
make lab-verify
# Посмотреть отчет
make lab-report
```
### Пример 2: Тестирование базы данных
```bash
# Запустить пресет с базой данных
make lab-test LAB_SPEC=molecule/presets/ha.yml
# Проверить подключение к БД
make kube-cmd CLUSTER=lab CMD="exec -it postgres-0 -- psql -U postgres -c 'SELECT 1;'"
```
### Пример 3: Тестирование микросервисов
```bash
# Запустить микросервисный пресет
make lab-test LAB_SPEC=molecule/presets/microservices.yml
# Проверить API Gateway
curl http://localhost:8000/health
```
## Kubernetes примеры
### Пример 1: Простой Kubernetes кластер
```bash
# Запустить одиночный Kind кластер
make lab-test LAB_SPEC=molecule/presets/k8s-single.yml
# Войти в кластер
make kube-sh
# Проверить ноды
kubectl get nodes
# Проверить поды
kubectl get pods -A
```
### Пример 2: Мульти-кластерная конфигурация
```bash
# Запустить мульти-кластер
make lab-test LAB_SPEC=molecule/presets/k8s-multi.yml
# Переключиться между кластерами
kubectl config use-context kind-dev
kubectl get nodes
kubectl config use-context kind-staging
kubectl get nodes
kubectl config use-context kind-prod
kubectl get nodes
```
### Пример 3: Istio Service Mesh
```bash
# Запустить полный Istio стек
make lab-test LAB_SPEC=molecule/presets/k8s-istio-full.yml
# Port-forward Kiali
make kiali-port-forward CLUSTER=istio-full
# Port-forward Istio Gateway
make istio-gw-port-forward CLUSTER=istio-full
# Открыть Kiali
open http://localhost:20001
# Открыть Bookinfo
open http://localhost:8082/productpage
```
### Пример 4: Мониторинг Kubernetes
```bash
# Port-forward Grafana
make grafana-port-forward CLUSTER=istio-full
# Port-forward Prometheus
make prom-port-forward CLUSTER=istio-full
# Открыть Grafana
open http://localhost:3000
# Открыть Prometheus
open http://localhost:9090
```
## Docker примеры
### Пример 1: Docker-in-Docker
```bash
# Запустить DinD пресет
make lab-test LAB_SPEC=molecule/presets/dind-simple.yml
# Войти в DinD контейнер
docker exec -it dind1 sh
# Внутри контейнера проверить Docker
docker ps
docker images
```
### Пример 2: Docker Swarm
```bash
# Запустить Docker Swarm пресет
make lab-test LAB_SPEC=molecule/presets/dind-swarm.yml
# Войти в manager
docker exec -it swarm-manager sh
# Инициализировать Swarm
docker swarm init
# Присоединить workers
docker node ls
```
### Пример 3: Docker Compose
```bash
# Запустить Compose пресет
make lab-test LAB_SPEC=molecule/presets/dind-compose.yml
# Войти в compose контейнер
docker exec -it compose-web sh
# Создать docker-compose.yml
cat > docker-compose.yml << EOF
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
api:
image: node:alpine
ports:
- "3000:3000"
EOF
# Запустить стек
docker-compose up -d
```
### Пример 4: Docker-outside-of-Docker
```bash
# Запустить DOoD пресет
make lab-test LAB_SPEC=molecule/presets/dood-simple.yml
# Войти в DOoD контейнер
docker exec -it dood1 sh
# Проверить доступ к Docker daemon хоста
docker ps
docker images
```
## Смешанные примеры
### Пример 1: Kubernetes + DinD
```bash
# Запустить смешанный пресет
make lab-test LAB_SPEC=molecule/presets/mixed-k8s-dind.yml
# Проверить Kubernetes
make kube-cmd CLUSTER=hybrid CMD="get nodes"
# Проверить DinD
docker exec -it dind-dev sh
docker ps
```
### Пример 2: Kubernetes + DOoD
```bash
# Запустить смешанный пресет
make lab-test LAB_SPEC=molecule/presets/mixed-k8s-dood.yml
# Проверить Kubernetes
make kube-cmd CLUSTER=hybrid CMD="get pods -A"
# Проверить DOoD
docker exec -it dood-web sh
docker ps
```
### Пример 3: Полная гибридная конфигурация
```bash
# Запустить полный смешанный пресет
make lab-test LAB_SPEC=molecule/presets/mixed-full.yml
# Проверить все компоненты
make kube-cmd CLUSTER=full-stack CMD="get nodes"
docker exec -it dind-dev sh
docker exec -it dood-web sh
```
## Мониторинг и отчеты
### Пример 1: Генерация HTML отчета
```bash
# Запустить тест
make lab-test LAB_SPEC=molecule/presets/enterprise.yml
# Сгенерировать отчет
make lab-report
# Открыть отчет
open reports/lab-report.html
```
### Пример 2: Снапшоты
```bash
# Создать снапшот
make lab-snapshot
# Восстановить из снапшота
make lab-restore
# Очистить лабораторию
make lab-cleanup
```
### Пример 3: Мониторинг в реальном времени
```bash
# Port-forward всех сервисов мониторинга
make grafana-port-forward CLUSTER=lab
make prom-port-forward CLUSTER=lab
make kiali-port-forward CLUSTER=lab
# Открыть все дашборды
open http://localhost:3000 # Grafana
open http://localhost:9090 # Prometheus
open http://localhost:20001 # Kiali
```
## Troubleshooting
### Пример 1: Проблемы с портами
```bash
# Проверить занятые порты
netstat -tulpn | grep :8080
# Остановить все port-forward
make kube-pf-stop
# Перезапустить лабораторию
make lab-reset
```
### Пример 2: Проблемы с Docker
```bash
# Проверить Docker daemon
docker ps
# Перезапустить Docker
sudo systemctl restart docker
# Очистить Docker
docker system prune -a
```
### Пример 3: Проблемы с Kubernetes
```bash
# Проверить Kind кластеры
kind get clusters
# Удалить проблемный кластер
kind delete cluster --name lab
# Пересоздать кластер
make lab-create
```
### Пример 4: Проблемы с ресурсами
```bash
# Проверить использование ресурсов
docker stats
# Ограничить ресурсы
docker run --memory=512m --cpus=1.0 your-image
# Очистить неиспользуемые ресурсы
make lab-cleanup
```
## Продвинутые примеры
### Пример 1: Создание собственного пресета
```bash
# Создать новый пресет
cat > molecule/presets/my-custom.yml << EOF
---
# ПРЕСЕТ: Мой кастомный пресет
#
# Описание: Кастомная конфигурация для моих нужд
#
# Использование: make lab-test LAB_SPEC=molecule/presets/my-custom.yml
docker_network: labnet
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: my-web
family: debian
group: webservers
publish:
- "8080:80"
- name: my-db
family: rhel
group: databases
publish:
- "5432:5432"
EOF
# Протестировать пресет
make lab-test LAB_SPEC=molecule/presets/my-custom.yml
```
### Пример 2: Создание собственной роли
```bash
# Создать структуру роли
mkdir -p roles/my-role/{tasks,handlers,templates,files,vars,defaults,meta}
# Создать основной task
cat > roles/my-role/tasks/main.yml << EOF
---
- name: Install nginx
package:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
enabled: true
EOF
# Создать playbook
cat > files/playbooks/my-playbook.yml << EOF
---
- name: Deploy my role
hosts: webservers
become: true
roles:
- my-role
EOF
# Протестировать роль
make lab-test LAB_SPEC=molecule/presets/webapp.yml
```
### Пример 3: Интеграция с CI/CD
```bash
# Создать GitHub Actions workflow
cat > .github/workflows/test.yml << EOF
name: Test Ansible Roles
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Docker
run: |
docker-compose up -d
- name: Run tests
run: |
make lab-test LAB_SPEC=molecule/presets/minimal.yml
- name: Generate report
run: |
make lab-report
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: lab-report
path: reports/lab-report.html
EOF
```
## Заключение
Эти примеры демонстрируют основные возможности универсальной лаборатории. Для получения дополнительной информации обратитесь к [основной документации](universal-lab.md) и [описанию пресетов](presets.md).

196
docs/presets.md Normal file
View File

@@ -0,0 +1,196 @@
# Пресеты универсальной лаборатории
## Автор
Сергей Антропов
Сайт: https://devops.org.ru
## Описание
Этот каталог содержит готовые пресеты для различных сценариев тестирования Ansible ролей. Каждый пресет оптимизирован для определенного типа инфраструктуры и количества машин.
## Доступные пресеты
### 🏗️ Классические пресеты (systemd контейнеры)
#### 1. Минимальная лаборатория (1-3 машины)
**Файл:** `minimal.yml`
**Описание:** Базовая конфигурация для простых тестов Ansible ролей
**Компоненты:** 1 контроллер, 1 веб-сервер, 1 база данных
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/minimal.yml`
### 2. Веб-приложение (3-5 машин)
**Файл:** `webapp.yml`
**Описание:** Классическая архитектура веб-приложения
**Компоненты:** 2 веб-сервера, 1 БД, 1 кэш, 1 балансировщик
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/webapp.yml`
### 3. Микросервисы (5-8 машин)
**Файл:** `microservices.yml`
**Описание:** Архитектура микросервисов с разделением ответственности
**Компоненты:** API Gateway, микросервисы, БД, кэш, очередь, мониторинг
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/microservices.yml`
### 4. Высокая доступность (6-10 машин)
**Файл:** `ha.yml`
**Описание:** Кластер высокой доступности с репликацией
**Компоненты:** 2 веб-сервера, 2 БД, 2 кэша, балансировщик, мониторинг
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/ha.yml`
### 5. Kubernetes кластер (8-12 машин)
**Файл:** `k8s-cluster.yml`
**Описание:** Полноценный Kubernetes кластер с различными ролями
**Компоненты:** 3 master, 3 worker, 3 etcd, ingress, мониторинг
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-cluster.yml`
### 6. CI/CD пайплайн (10-15 машин)
**Файл:** `cicd.yml`
**Описание:** Полноценный CI/CD пайплайн с различными инструментами
**Компоненты:** Git, Jenkins, Nexus, Docker Registry, среды, мониторинг, ELK
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/cicd.yml`
### 7. Big Data кластер (12-18 машин)
**Файл:** `bigdata.yml`
**Описание:** Кластер для обработки больших данных
**Компоненты:** Hadoop, Spark, Kafka, Zookeeper, Elasticsearch, Kibana
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/bigdata.yml`
### 8. Service Mesh (15-20 машин)
**Файл:** `servicemesh.yml`
**Описание:** Полноценный service mesh с Istio и множественными сервисами
**Компоненты:** Istio, Frontend, Backend, БД, кэш, мониторинг, трассировка
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/servicemesh.yml`
### 9. Enterprise (18-20 машин)
**Файл:** `enterprise.yml`
**Описание:** Полноценная enterprise инфраструктура с высокой доступностью
**Компоненты:** LB, Web, API Gateway, App, БД, кэш, очереди, поиск, мониторинг, логи, backup
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/enterprise.yml`
### 10. Максимальный (20 машин)
**Файл:** `maximum.yml`
**Описание:** Максимально сложная инфраструктура для экстремальных условий
**Компоненты:** Все компоненты enterprise + трассировка + визуализация
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/maximum.yml`
### ☸️ Kubernetes пресеты
#### 11. Kubernetes Single Node (1 кластер)
**Файл:** `k8s-single.yml`
**Описание:** Одиночный Kind кластер для простого тестирования K8s ролей
**Компоненты:** 1 Kind кластер с 1 worker, базовые аддоны
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-single.yml`
#### 12. Kubernetes Multi-Cluster (3 кластера)
**Файл:** `k8s-multi.yml`
**Описание:** Несколько Kind кластеров для тестирования мульти-кластерных сценариев
**Компоненты:** 3 кластера (dev, staging, prod) с различными конфигурациями
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-multi.yml`
#### 13. Kubernetes + Istio Full Stack (1 кластер с полным стеком)
**Файл:** `k8s-istio-full.yml`
**Описание:** Полноценный Kubernetes кластер с полным стеком Istio
**Компоненты:** 1 Kind кластер с 3 workers, Istio, Kiali, Prometheus, Grafana, Jaeger
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-istio-full.yml`
### 🐳 Docker-in-Docker (DinD) пресеты
#### 14. DinD Simple (3 DinD контейнера)
**Файл:** `dind-simple.yml`
**Описание:** Простая конфигурация DinD для тестирования Docker ролей
**Компоненты:** 3 DinD контейнера с изолированными Docker средами
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dind-simple.yml`
#### 15. DinD Swarm (5 DinD контейнеров)
**Файл:** `dind-swarm.yml`
**Описание:** Docker Swarm кластер для тестирования оркестрации
**Компоненты:** 1 Manager + 4 Worker узла в Docker Swarm режиме
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dind-swarm.yml`
#### 16. DinD Compose (4 DinD контейнера)
**Файл:** `dind-compose.yml`
**Описание:** DinD контейнеры для тестирования Docker Compose стека
**Компоненты:** 4 DinD контейнера с различными стеками
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dind-compose.yml`
### 🔗 Docker-outside-of-Docker (DOoD) пресеты
#### 17. DOoD Simple (3 DOoD контейнера)
**Файл:** `dood-simple.yml`
**Описание:** Простая конфигурация DOoD для тестирования Docker ролей
**Компоненты:** 3 DOoD контейнера с доступом к Docker daemon хоста
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dood-simple.yml`
#### 18. DOoD Mixed (5 DOoD + 2 systemd)
**Файл:** `dood-mixed.yml`
**Описание:** Смешанная конфигурация DOoD и systemd контейнеров
**Компоненты:** 5 DOoD контейнеров для Docker операций + 2 systemd для системных ролей
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dood-mixed.yml`
### 🔀 Смешанные пресеты
#### 19. Mixed Kubernetes + DinD (1 K8s + 3 DinD)
**Файл:** `mixed-k8s-dind.yml`
**Описание:** Смешанная конфигурация Kubernetes и Docker-in-Docker
**Компоненты:** 1 Kind кластер + 3 DinD контейнера
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/mixed-k8s-dind.yml`
#### 20. Mixed Kubernetes + DOoD (1 K8s + 3 DOoD)
**Файл:** `mixed-k8s-dood.yml`
**Описание:** Смешанная конфигурация Kubernetes и Docker-outside-of-Docker
**Компоненты:** 1 Kind кластер + 3 DOoD контейнера
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/mixed-k8s-dood.yml`
#### 21. Mixed Full Stack (1 K8s + 2 DinD + 2 DOoD + 2 systemd)
**Файл:** `mixed-full.yml`
**Описание:** Полная смешанная конфигурация для комплексного тестирования
**Компоненты:** 1 Kind кластер + 2 DinD + 2 DOoD + 2 systemd контейнера
**Использование:** `make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/mixed-full.yml`
## Использование
### Быстрый старт
```bash
# Выбрать пресет
export LAB_SPEC=molecule/presets/minimal.yml
# Запустить тестирование
make lab-test
```
### Создание собственного пресета
1. Скопировать существующий пресет: `cp minimal.yml my-preset.yml`
2. Отредактировать под ваши нужды
3. Использовать: `make lab-test LAB_SPEC=molecule/presets/my-preset.yml`
### Переменные окружения
```bash
# Установить пресет по умолчанию
export LAB_SPEC=molecule/presets/webapp.yml
# Или использовать в команде
make lab-test LAB_SPEC=molecule/presets/ha.yml
```
## Рекомендации
- **Для начинающих:** используйте `minimal.yml` или `webapp.yml`
- **Для микросервисов:** `microservices.yml` или `servicemesh.yml`
- **Для Kubernetes:** `k8s-cluster.yml`
- **Для enterprise:** `enterprise.yml` или `maximum.yml`
- **Для Big Data:** `bigdata.yml`
## Кастомизация
Каждый пресет можно настроить под ваши нужды:
- Изменить количество машин
- Добавить/убрать группы
- Изменить семейства ОС (debian/rhel)
- Настроить порты и переменные
## Troubleshooting
Если пресет не работает:
1. Проверьте доступность Docker образов
2. Убедитесь в достаточности ресурсов
3. Проверьте логи: `make lab-verify`
4. Очистите лабораторию: `make lab-cleanup`

420
docs/roles.md Normal file
View File

@@ -0,0 +1,420 @@
# Ansible Роли
## Автор
Сергей Антропов
Сайт: https://devops.org.ru
## Описание
Этот документ описывает структуру, создание и использование Ansible ролей в универсальной лаборатории.
## Содержание
- [Структура роли](#структура-роли)
- [Создание роли](#создание-роли)
- [Использование роли](#использование-роли)
- [Тестирование роли](#тестирование-роли)
- [Лучшие практики](#лучшие-практики)
- [Примеры ролей](#примеры-ролей)
## Структура роли
```
roles/
└── your_role/
├── tasks/ # Основные задачи
│ └── main.yml
├── handlers/ # Обработчики событий
│ └── main.yml
├── templates/ # Jinja2 шаблоны
│ └── config.j2
├── files/ # Статические файлы
│ └── config.conf
├── vars/ # Переменные роли
│ └── main.yml
├── defaults/ # Переменные по умолчанию
│ └── main.yml
├── meta/ # Метаданные роли
│ └── main.yml
└── tests/ # Тесты роли
├── inventory
└── test.yml
```
### Описание директорий
| Директория | Описание | Обязательная |
|------------|----------|--------------|
| `tasks/` | Основные задачи роли | Да |
| `handlers/` | Обработчики событий | Нет |
| `templates/` | Jinja2 шаблоны | Нет |
| `files/` | Статические файлы | Нет |
| `vars/` | Переменные роли | Нет |
| `defaults/` | Переменные по умолчанию | Нет |
| `meta/` | Метаданные роли | Нет |
| `tests/` | Тесты роли | Нет |
## Создание роли
### Автоматическое создание
```bash
# Создать роль с помощью ansible-galaxy
ansible-galaxy init your_role
# Создать роль в определенной директории
ansible-galaxy init your_role --init-path roles/
```
### Ручное создание
```bash
# Создать структуру роли
mkdir -p roles/your_role/{tasks,handlers,templates,files,vars,defaults,meta,tests}
# Создать основной task
cat > roles/your_role/tasks/main.yml << EOF
---
- name: Install package
package:
name: "{{ package_name }}"
state: present
- name: Start service
service:
name: "{{ service_name }}"
state: started
enabled: true
EOF
# Создать переменные по умолчанию
cat > roles/your_role/defaults/main.yml << EOF
---
package_name: nginx
service_name: nginx
EOF
```
## Использование роли
### В playbook
```yaml
---
- name: Deploy web server
hosts: webservers
become: true
roles:
- your_role
```
### С переменными
```yaml
---
- name: Deploy web server
hosts: webservers
become: true
roles:
- role: your_role
vars:
package_name: apache2
service_name: apache2
```
### С условиями
```yaml
---
- name: Deploy web server
hosts: webservers
become: true
roles:
- role: your_role
when: ansible_os_family == "Debian"
```
## Тестирование роли
### Создание тестов
```bash
# Создать тестовый playbook
cat > roles/your_role/tests/test.yml << EOF
---
- name: Test role
hosts: all
become: true
roles:
- your_role
EOF
# Создать инвентарь для тестов
cat > roles/your_role/tests/inventory << EOF
[webservers]
localhost ansible_connection=local
EOF
```
### Запуск тестов
```bash
# Запустить тест роли
ansible-playbook -i roles/your_role/tests/inventory roles/your_role/tests/test.yml
# Запустить тест с Molecule
molecule test
```
## Лучшие практики
### Структура задач
```yaml
---
# tasks/main.yml
- name: Install package
package:
name: "{{ package_name }}"
state: present
notify: restart service
- name: Configure service
template:
src: config.j2
dest: /etc/service/config.conf
notify: restart service
- name: Start service
service:
name: "{{ service_name }}"
state: started
enabled: true
```
### Обработчики
```yaml
---
# handlers/main.yml
- name: restart service
service:
name: "{{ service_name }}"
state: restarted
```
### Переменные
```yaml
---
# defaults/main.yml
package_name: nginx
service_name: nginx
config_file: /etc/nginx/nginx.conf
port: 80
# vars/main.yml
service_user: nginx
service_group: nginx
```
### Метаданные
```yaml
---
# meta/main.yml
galaxy_info:
author: Your Name
description: Your role description
company: Your Company
license: MIT
min_ansible_version: "2.9"
platforms:
- name: Ubuntu
versions:
- focal
- jammy
- name: CentOS
versions:
- 8
- 9
galaxy_tags:
- web
- nginx
dependencies: []
```
## Примеры ролей
### Роль для веб-сервера
```yaml
---
# tasks/main.yml
- name: Install nginx
package:
name: nginx
state: present
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: Start nginx
service:
name: nginx
state: started
enabled: true
```
```yaml
---
# defaults/main.yml
nginx_port: 80
nginx_ssl_port: 443
nginx_user: www-data
nginx_worker_processes: auto
```
### Роль для базы данных
```yaml
---
# tasks/main.yml
- name: Install PostgreSQL
package:
name: postgresql
state: present
- name: Start PostgreSQL
service:
name: postgresql
state: started
enabled: true
- name: Create database
postgresql_db:
name: "{{ db_name }}"
state: present
- name: Create user
postgresql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
state: present
```
### Роль для мониторинга
```yaml
---
# tasks/main.yml
- name: Install Prometheus
package:
name: prometheus
state: present
- name: Configure Prometheus
template:
src: prometheus.yml.j2
dest: /etc/prometheus/prometheus.yml
notify: restart prometheus
- name: Start Prometheus
service:
name: prometheus
state: started
enabled: true
```
## Интеграция с лабораторией
### Использование в пресетах
```yaml
---
# molecule/presets/webapp.yml
hosts:
- name: web1
group: webservers
family: debian
publish:
- "8080:80"
- name: db1
group: databases
family: rhel
publish:
- "5432:5432"
```
### Playbook для ролей
```yaml
---
# files/playbooks/site.yml
- name: Deploy web servers
hosts: webservers
become: true
roles:
- nginx
- ssl
- name: Deploy databases
hosts: databases
become: true
roles:
- postgresql
- backup
- name: Deploy monitoring
hosts: monitoring
become: true
roles:
- prometheus
- grafana
```
### Тестирование с различными пресетами
```bash
# Тестирование с минимальным пресетом
make lab-test LAB_SPEC=molecule/presets/minimal.yml
# Тестирование с веб-приложением
make lab-test LAB_SPEC=molecule/presets/webapp.yml
# Тестирование с микросервисами
make lab-test LAB_SPEC=molecule/presets/microservices.yml
```
## Публикация роли
### В Ansible Galaxy
```bash
# Установить ansible-galaxy
pip install ansible-galaxy
# Публиковать роль
ansible-galaxy import your-username your-role
# Или через GitHub
ansible-galaxy import your-username your-role --github-user your-username
```
### В приватном репозитории
```bash
# Установить роль из Git
ansible-galaxy install git+https://github.com/your-username/your-role.git
# Установить роль из файла
ansible-galaxy install your-role.tar.gz
```
## Заключение
Этот документ описывает основные принципы создания и использования Ansible ролей в универсальной лаборатории. Для получения дополнительной информации обратитесь к [основной документации](universal-lab.md) и [примерам использования](examples.md).

652
docs/troubleshooting.md Normal file
View File

@@ -0,0 +1,652 @@
# Troubleshooting
## Автор
Сергей Антропов
Сайт: https://devops.org.ru
## Описание
Этот документ содержит решения наиболее распространенных проблем при работе с универсальной лабораторией.
## Содержание
- [Общие проблемы](#общие-проблемы)
- [Проблемы с Docker](#проблемы-с-docker)
- [Проблемы с Kubernetes](#проблемы-с-kubernetes)
- [Проблемы с портами](#проблемы-с-портами)
- [Проблемы с ресурсами](#проблемы-с-ресурсами)
- [Проблемы с сетью](#проблемы-с-сетью)
- [Проблемы с Ansible](#проблемы-с-ansible)
- [Проблемы с Molecule](#проблемы-с-molecule)
- [Проблемы с пресетами](#проблемы-с-пресетами)
- [Проблемы с отчетами](#проблемы-с-отчетами)
## Общие проблемы
### Проблема: Лаборатория не запускается
**Симптомы:**
- Команда `make lab-up` завершается с ошибкой
- Контейнеры не создаются
- Ошибки в логах Docker
**Решение:**
```bash
# Проверить статус Docker
docker ps
docker version
# Перезапустить Docker
sudo systemctl restart docker
# Очистить Docker
docker system prune -a
# Перезапустить лабораторию
make lab-reset
```
### Проблема: Команды Make не работают
**Симптомы:**
- `make: command not found`
- Ошибки в Makefile
**Решение:**
```bash
# Установить Make
# Ubuntu/Debian
sudo apt-get install make
# CentOS/RHEL
sudo yum install make
# macOS
brew install make
# Проверить версию
make --version
```
### Проблема: Недостаточно прав
**Симптомы:**
- `Permission denied`
- Ошибки доступа к файлам
**Решение:**
```bash
# Проверить права на файлы
ls -la
# Установить права
chmod +x scripts/*.sh
chmod 644 *.yml
# Добавить пользователя в группу docker
sudo usermod -aG docker $USER
newgrp docker
```
## Проблемы с Docker
### Проблема: Docker daemon не запущен
**Симптомы:**
- `Cannot connect to the Docker daemon`
- `docker: command not found`
**Решение:**
```bash
# Запустить Docker daemon
sudo systemctl start docker
sudo systemctl enable docker
# Проверить статус
sudo systemctl status docker
# Проверить доступ
docker ps
```
### Проблема: Недостаточно места на диске
**Симптомы:**
- `No space left on device`
- Ошибки создания контейнеров
**Решение:**
```bash
# Проверить использование диска
df -h
# Очистить Docker
docker system prune -a
docker volume prune
docker network prune
# Удалить неиспользуемые образы
docker image prune -a
```
### Проблема: Конфликты портов
**Симптомы:**
- `Port is already in use`
- Ошибки привязки портов
**Решение:**
```bash
# Найти процесс, использующий порт
sudo netstat -tulpn | grep :8080
sudo lsof -i :8080
# Убить процесс
sudo kill -9 <PID>
# Или изменить порт в пресете
publish:
- "8081:80" # Вместо 8080:80
```
### Проблема: DinD контейнеры не работают
**Симптомы:**
- DinD контейнеры не запускаются
- Ошибки Docker-in-Docker
**Решение:**
```bash
# Проверить privileged режим
docker run --privileged -d docker:dind
# Проверить доступ к Docker socket
docker run -v /var/run/docker.sock:/var/run/docker.sock docker:latest ps
# Перезапустить с правильными параметрами
make lab-reset
make lab-create
```
## Проблемы с Kubernetes
### Проблема: Kind кластер не создается
**Симптомы:**
- `kind create cluster` завершается с ошибкой
- Кластер не доступен
**Решение:**
```bash
# Проверить Kind
kind version
# Удалить существующие кластеры
kind delete cluster --name lab
# Очистить Docker
docker system prune -a
# Пересоздать кластер
make lab-create
```
### Проблема: kubectl не работает
**Симптомы:**
- `kubectl: command not found`
- Ошибки подключения к кластеру
**Решение:**
```bash
# Установить kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# Проверить конфигурацию
kubectl config get-contexts
# Переключиться на правильный контекст
kubectl config use-context kind-lab
```
### Проблема: Pods не запускаются
**Симптомы:**
- Pods в состоянии Pending
- Ошибки в логах pods
**Решение:**
```bash
# Проверить статус pods
kubectl get pods -A
kubectl describe pod <pod-name>
# Проверить события
kubectl get events --sort-by=.metadata.creationTimestamp
# Проверить ресурсы
kubectl top nodes
kubectl top pods
```
### Проблема: Istio не устанавливается
**Симптомы:**
- Istio компоненты не запускаются
- Ошибки в Istio логах
**Решение:**
```bash
# Проверить Istio
istioctl version
# Переустановить Istio
istioctl uninstall --purge
istioctl install --set profile=demo
# Проверить статус
kubectl get pods -n istio-system
```
## Проблемы с портами
### Проблема: Порт уже используется
**Симптомы:**
- `bind: address already in use`
- Ошибки привязки портов
**Решение:**
```bash
# Найти процесс
sudo lsof -i :8080
# Убить процесс
sudo kill -9 <PID>
# Или изменить порт в пресете
publish:
- "8081:80"
```
### Проблема: Port-forward не работает
**Симптомы:**
- Port-forward не устанавливается
- Ошибки подключения
**Решение:**
```bash
# Остановить все port-forward
make kube-pf-stop
# Проверить доступность сервиса
kubectl get svc -n istio-system
# Перезапустить port-forward
make kiali-port-forward CLUSTER=lab
```
## Проблемы с ресурсами
### Проблема: Недостаточно памяти
**Симптомы:**
- `Out of memory`
- Контейнеры завершаются
**Решение:**
```bash
# Проверить память
free -h
docker stats
# Ограничить ресурсы
docker run --memory=512m your-image
# Или уменьшить количество контейнеров в пресете
```
### Проблема: Недостаточно CPU
**Симптомы:**
- Медленная работа
- Высокая нагрузка на CPU
**Решение:**
```bash
# Проверить CPU
top
htop
# Ограничить CPU
docker run --cpus=1.0 your-image
# Или использовать более легкие образы
```
### Проблема: Недостаточно места на диске
**Симптомы:**
- `No space left on device`
- Ошибки записи
**Решение:**
```bash
# Проверить место
df -h
# Очистить Docker
docker system prune -a
docker volume prune
# Удалить неиспользуемые образы
docker image prune -a
```
## Проблемы с сетью
### Проблема: Контейнеры не могут связаться
**Симптомы:**
- Ping не работает между контейнерами
- Ошибки сети
**Решение:**
```bash
# Проверить сеть
docker network ls
docker network inspect labnet
# Пересоздать сеть
docker network rm labnet
docker network create labnet
# Перезапустить лабораторию
make lab-reset
```
### Проблема: DNS не работает
**Симптомы:**
- Не удается разрешить имена
- Ошибки DNS
**Решение:**
```bash
# Проверить DNS
nslookup google.com
# Перезапустить Docker
sudo systemctl restart docker
# Проверить resolv.conf
cat /etc/resolv.conf
```
## Проблемы с Ansible
### Проблема: Ansible не найден
**Симптомы:**
- `ansible: command not found`
- Ошибки выполнения playbook
**Решение:**
```bash
# Установить Ansible
pip install ansible
# Или через пакетный менеджер
sudo apt-get install ansible
# Проверить версию
ansible --version
```
### Проблема: Ошибки в playbook
**Симптомы:**
- Синтаксические ошибки
- Ошибки выполнения задач
**Решение:**
```bash
# Проверить синтаксис
ansible-playbook --syntax-check playbook.yml
# Запустить в режиме отладки
ansible-playbook -vvv playbook.yml
# Проверить инвентарь
ansible-inventory --list
```
### Проблема: Ошибки подключения
**Симптомы:**
- `Connection refused`
- Ошибки SSH
**Решение:**
```bash
# Проверить подключение
ansible all -m ping
# Проверить SSH ключи
ssh-keygen -t rsa -b 4096
ssh-copy-id user@host
# Или использовать пароль
ansible all -m ping -k
```
## Проблемы с Molecule
### Проблема: Molecule не найден
**Симптомы:**
- `molecule: command not found`
- Ошибки выполнения molecule
**Решение:**
```bash
# Установить Molecule
pip install molecule
# Или через пакетный менеджер
sudo apt-get install molecule
# Проверить версию
molecule --version
```
### Проблема: Ошибки в molecule.yml
**Симптомы:**
- Синтаксические ошибки в конфигурации
- Ошибки валидации
**Решение:**
```bash
# Проверить синтаксис
molecule syntax
# Проверить конфигурацию
molecule lint
# Исправить ошибки
molecule validate
```
### Проблема: Ошибки драйвера
**Симптомы:**
- Ошибки Docker драйвера
- Проблемы с контейнерами
**Решение:**
```bash
# Проверить драйвер
molecule driver list
# Установить Docker драйвер
pip install molecule-docker
# Перезапустить Molecule
molecule destroy
molecule create
```
## Проблемы с пресетами
### Проблема: Пресет не найден
**Симптомы:**
- `File not found`
- Ошибки загрузки пресета
**Решение:**
```bash
# Проверить путь
ls -la molecule/presets/
# Проверить синтаксис YAML
yamllint molecule/presets/your-preset.yml
# Исправить ошибки
molecule validate
```
### Проблема: Ошибки в пресете
**Симптомы:**
- Синтаксические ошибки
- Ошибки валидации
**Решение:**
```bash
# Проверить синтаксис
yamllint molecule/presets/your-preset.yml
# Проверить структуру
molecule validate
# Исправить ошибки
molecule syntax
```
## Проблемы с отчетами
### Проблема: HTML отчет не генерируется
**Симптомы:**
- `File not found`
- Ошибки генерации отчета
**Решение:**
```bash
# Проверить JSON файл
ls -la reports/
cat reports/lab-health.json
# Перезапустить верификацию
make lab-verify
# Сгенерировать отчет
make lab-report
```
### Проблема: Отчет пустой
**Симптомы:**
- Отчет не содержит данных
- Ошибки в JSON
**Решение:**
```bash
# Проверить JSON
jq . reports/lab-health.json
# Перезапустить тест
make lab-test
# Проверить логи
make lab-verify
```
## Полезные команды для диагностики
### Общие команды
```bash
# Проверить статус системы
docker ps
docker images
docker network ls
docker volume ls
# Проверить ресурсы
free -h
df -h
top
# Проверить сеть
netstat -tulpn
ss -tulpn
```
### Команды для Kubernetes
```bash
# Проверить кластеры
kind get clusters
kubectl config get-contexts
# Проверить ресурсы
kubectl get nodes
kubectl get pods -A
kubectl get svc -A
# Проверить события
kubectl get events --sort-by=.metadata.creationTimestamp
```
### Команды для Ansible
```bash
# Проверить инвентарь
ansible-inventory --list
ansible all -m ping
# Проверить playbook
ansible-playbook --syntax-check playbook.yml
ansible-playbook --check playbook.yml
```
## Получение помощи
Если проблема не решается:
1. **Проверьте логи:**
```bash
docker logs <container-name>
kubectl logs <pod-name>
```
2. **Создайте issue:**
- Опишите проблему
- Приложите логи
- Укажите версии компонентов
3. **Обратитесь к сообществу:**
- GitHub Discussions
- Discord/Slack каналы
- Форумы Ansible
4. **Проверьте документацию:**
- [Основная документация](universal-lab.md)
- [Примеры использования](examples.md)
- [API Reference](api.md)

295
docs/universal-lab.md Normal file
View File

@@ -0,0 +1,295 @@
# Универсальная лаборатория для тестирования Ansible ролей
## Автор
Сергей Антропов
Сайт: https://devops.org.ru
## Описание
Это универсальная лаборатория для тестирования Ansible ролей, созданная на основе предложений ChatGPT. Лаборатория поддерживает:
- **Docker-in-Docker (DinD)** - полная изоляция контейнеров
- **Docker-outside-of-Docker (DOoD)** - использование хостового Docker
- **Kind кластеры** - локальные Kubernetes кластеры
- **Helm charts** - nginx, prometheus-stack
- **Istio service mesh** - с Kiali для мониторинга
- **Prometheus + Grafana** - с автопровижинингом дашбордов
- **HTML отчеты** - красивые отчеты о результатах тестирования
## Структура проекта
```
molecule/
├── universal/ # Универсальная лаборатория
│ ├── molecule.yml # Конфигурация Molecule
│ ├── vars.yml # Переменные лаборатории
│ ├── create.yml # Создание инфраструктуры
│ ├── converge.yml # Запуск ролей
│ ├── verify.yml # Проверка работы
│ └── destroy.yml # Очистка
├── presets/ # Пресеты для разных сценариев
│ └── k8s-kind.yml # Пресет для Kubernetes
└── default/ # Старый сценарий (для совместимости)
files/
├── requirements.yml # Коллекции Ansible
├── playbooks/
│ └── site.yml # Основной playbook
└── k8s/ # Kubernetes манифесты
└── istio/ # Istio конфигурации
roles/ # Ваши Ansible роли
```
## Использование
### 1. Подготовка
```bash
# Создать файл с паролем для vault
echo "test" > vault-password.txt
# Создать каталог для ролей
mkdir -p roles
# Скопировать переменные окружения
cp env.example .env
# Отредактировать .env под ваши нужды
```
### 2. Запуск лаборатории
```bash
# Поднять контроллер
make lab-up
# Создать инфраструктуру
make lab-create
# Запустить роли
make lab-converge
# Проверить работу
make lab-verify
# Сгенерировать HTML отчет
make lab-report
# Уничтожить лабораторию
make lab-destroy
```
### 3. Управление лабораторией
```bash
# Полный цикл тестирования
make lab-test
# Снапшоты и восстановление
make lab-snapshot # Сохранить состояние
make lab-restore # Восстановить из снапшота
make lab-cleanup # Очистить все
# Сброс лаборатории
make lab-reset
```
### 4. Пресеты для разных сценариев
#### 🏗️ Классические пресеты (systemd контейнеры)
```bash
# Минимальная лаборатория (1-3 машины)
make lab-test LAB_SPEC=molecule/presets/minimal.yml
# Веб-приложение (3-5 машин)
make lab-test LAB_SPEC=molecule/presets/webapp.yml
# Микросервисы (5-8 машин)
make lab-test LAB_SPEC=molecule/presets/microservices.yml
# Высокая доступность (6-10 машин)
make lab-test LAB_SPEC=molecule/presets/ha.yml
# Kubernetes кластер (8-12 машин)
make lab-test LAB_SPEC=molecule/presets/k8s-cluster.yml
# CI/CD пайплайн (10-15 машин)
make lab-test LAB_SPEC=molecule/presets/cicd.yml
# Big Data кластер (12-18 машин)
make lab-test LAB_SPEC=molecule/presets/bigdata.yml
# Service Mesh (15-20 машин)
make lab-test LAB_SPEC=molecule/presets/servicemesh.yml
# Enterprise (18-20 машин)
make lab-test LAB_SPEC=molecule/presets/enterprise.yml
# Максимальный (20 машин)
make lab-test LAB_SPEC=molecule/presets/maximum.yml
```
#### ☸️ Kubernetes пресеты
```bash
# Kubernetes Single Node (1 кластер)
make lab-test LAB_SPEC=molecule/presets/k8s-single.yml
# Kubernetes Multi-Cluster (3 кластера)
make lab-test LAB_SPEC=molecule/presets/k8s-multi.yml
# Kubernetes + Istio Full Stack (1 кластер с полным стеком)
make lab-test LAB_SPEC=molecule/presets/k8s-istio-full.yml
```
#### 🐳 Docker-in-Docker (DinD) пресеты
```bash
# DinD Simple (3 DinD контейнера)
make lab-test LAB_SPEC=molecule/presets/dind-simple.yml
# DinD Swarm (5 DinD контейнеров)
make lab-test LAB_SPEC=molecule/presets/dind-swarm.yml
# DinD Compose (4 DinD контейнера)
make lab-test LAB_SPEC=molecule/presets/dind-compose.yml
```
#### 🔗 Docker-outside-of-Docker (DOoD) пресеты
```bash
# DOoD Simple (3 DOoD контейнера)
make lab-test LAB_SPEC=molecule/presets/dood-simple.yml
# DOoD Mixed (5 DOoD + 2 systemd)
make lab-test LAB_SPEC=molecule/presets/dood-mixed.yml
```
#### 🔀 Смешанные пресеты
```bash
# Mixed Kubernetes + DinD (1 K8s + 3 DinD)
make lab-test LAB_SPEC=molecule/presets/mixed-k8s-dind.yml
# Mixed Kubernetes + DOoD (1 K8s + 3 DOoD)
make lab-test LAB_SPEC=molecule/presets/mixed-k8s-dood.yml
# Mixed Full Stack (1 K8s + 2 DinD + 2 DOoD + 2 systemd)
make lab-test LAB_SPEC=molecule/presets/mixed-full.yml
```
### 3. Работа с Kubernetes
```bash
# Войти в контейнер с kubectl
make kube-sh
# Выполнить команду kubectl
make kube-cmd CLUSTER=lab CMD="get pods -A"
# Войти в toolbox pod
make kube-enter CLUSTER=lab
# Port-forward для Kiali
make kiali-port-forward CLUSTER=lab
# Port-forward для Istio Gateway
make istio-gw-port-forward CLUSTER=lab
```
## Конфигурация
### Переменные лаборатории (molecule/universal/vars.yml)
```yaml
# Сеть для лаборатории
docker_network: labnet
# Образы для разных семейств ОС
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
# Определение хостов
hosts:
- name: etcd1
group: etcd
family: debian
- name: app-dind
group: apps
type: dind
publish:
- "8080:8080"
# Kind кластеры
kind_clusters:
- name: lab
workers: 2
addons:
ingress_nginx: true
istio: true
kiali: true
```
## Особенности
### 1. Автогенерация инвентаря
Инвентарь генерируется автоматически на основе определения хостов в `vars.yml`.
### 2. Поддержка DinD и DOoD
- **DinD**: Полная изоляция, каждый хост имеет свой Docker daemon
- **DOoD**: Использование хостового Docker, меньше ресурсов
### 3. Kubernetes интеграция
- Автоматическое создание Kind кластеров
- Установка Ingress NGINX, Metrics Server
- Поддержка Istio и Kiali
- Prometheus Stack с Grafana
### 4. Мониторинг и отчеты
- Автоматическая генерация HTML отчетов
- Интеграция с Prometheus и Grafana
- Дашборды для Istio
## Troubleshooting
### Проблемы с образами
Если возникают проблемы с загрузкой образов, обновите `vars.yml`:
```yaml
images:
debian: "ubuntu:22.04" # Используйте стандартные образы
rhel: "centos:8"
```
### Проблемы с Docker
Убедитесь, что Docker socket доступен:
```bash
ls -la /var/run/docker.sock
```
### Проблемы с Molecule
Если возникают проблемы с Molecule, попробуйте:
```bash
# Очистить кэш
make lab-reset
# Проверить конфигурацию
docker exec ansible-controller bash -lc 'molecule lint -s universal'
```
## Дальнейшее развитие
1. **Добавить поддержку Terraform** для создания инфраструктуры
2. **Интегрировать с GitLab CI/CD** для автоматического тестирования
3. **Добавить поддержку ARM64** для тестирования на Apple Silicon
4. **Создать веб-интерфейс** для управления лабораторией
5. **Добавить поддержку OpenShift** для enterprise сценариев
## Лицензия
MIT License
## Контакты
- Автор: Сергей Антропов
- Сайт: https://devops.org.ru
- Email: [ваш email]

16
env.example Normal file
View File

@@ -0,0 +1,16 @@
# Переменные окружения для универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Путь к каталогу с Ansible ролями (вне этого репозитория)
ROLES_DIR=/path/to/your/ansible/roles
# Telegram уведомления (опционально)
TG_TOKEN=your_telegram_bot_token
TG_CHAT=your_telegram_chat_id
# Пауза для ручной проверки (минуты)
LAB_PAUSE_MINUTES=10
# Сценарий Molecule
SCENARIO=universal

View File

@@ -0,0 +1,69 @@
{
"id": null,
"uid": "istio-overview",
"title": "Istio • Overview",
"schemaVersion": 36,
"version": 1,
"timezone": "browser",
"tags": ["istio", "sre", "mesh"],
"panels": [
{
"type": "stat",
"title": "Global RPS",
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 0},
"targets": [
{
"expr": "sum(rate(istio_requests_total{reporter=\"destination\"}[5m]))",
"legendFormat": "rps"
}
]
},
{
"type": "stat",
"title": "Success Rate",
"gridPos": {"h": 4, "w": 6, "x": 6, "y": 0},
"targets": [
{
"expr": "sum(rate(istio_requests_total{reporter=\"destination\",response_code!~\"5..\"}[5m])) / sum(rate(istio_requests_total{reporter=\"destination\"}[5m]))",
"legendFormat": "success"
}
],
"options": {"reduceOptions":{"calcs":["lastNotNull"]},"colorMode":"value","graphMode":"none"},
"fieldConfig":{"defaults":{"unit":"percentunit","min":0,"max":1}}
},
{
"type": "timeseries",
"title": "Latency (ms) p50/p95/p99",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 4},
"targets": [
{
"expr": "histogram_quantile(0.5, sum(rate(istio_request_duration_milliseconds_bucket{reporter=\"destination\"}[5m])) by (le))",
"legendFormat": "p50"
},
{
"expr": "histogram_quantile(0.95, sum(rate(istio_request_duration_milliseconds_bucket{reporter=\"destination\"}[5m])) by (le))",
"legendFormat": "p95"
},
{
"expr": "histogram_quantile(0.99, sum(rate(istio_request_duration_milliseconds_bucket{reporter=\"destination\"}[5m])) by (le))",
"legendFormat": "p99"
}
],
"fieldConfig":{"defaults":{"unit":"ms"}}
},
{
"type": "timeseries",
"title": "RPS by Workload",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 12},
"targets": [
{
"expr": "sum by (destination_workload) (rate(istio_requests_total{reporter=\"destination\"}[5m]))",
"legendFormat": "{{destination_workload}}"
}
]
}
],
"templating": {
"list": []
}
}

View File

@@ -0,0 +1,80 @@
{
"id": null,
"uid": "service-sli",
"title": "Service • SLI",
"schemaVersion": 36,
"version": 1,
"timezone": "browser",
"tags": ["istio", "sre", "sli"],
"templating": {
"list": [
{
"name": "namespace",
"type": "query",
"datasource": "${DS_PROMETHEUS}",
"query": "label_values(istio_requests_total, destination_namespace)",
"refresh": 1
},
{
"name": "workload",
"type": "query",
"datasource": "${DS_PROMETHEUS}",
"query": "label_values(istio_requests_total{destination_namespace=\"$namespace\"}, destination_workload)",
"refresh": 1
}
]
},
"panels": [
{
"type": "stat",
"title": "Success Rate",
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 0},
"targets": [
{
"expr": "sum(rate(istio_requests_total{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\",response_code!~\"5..\"}[5m])) / sum(rate(istio_requests_total{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\"}[5m]))",
"legendFormat": "success"
}
],
"fieldConfig":{"defaults":{"unit":"percentunit","min":0,"max":1}}
},
{
"type": "timeseries",
"title": "Latency (ms) p50/p95/p99",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 4},
"targets": [
{
"expr": "histogram_quantile(0.5, sum by (le) (rate(istio_request_duration_milliseconds_bucket{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\"}[5m])))",
"legendFormat": "p50"
},
{
"expr": "histogram_quantile(0.95, sum by (le) (rate(istio_request_duration_milliseconds_bucket{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\"}[5m])))",
"legendFormat": "p95"
},
{
"expr": "histogram_quantile(0.99, sum by (le) (rate(istio_request_duration_milliseconds_bucket{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\"}[5m])))",
"legendFormat": "p99"
}
],
"fieldConfig":{"defaults":{"unit":"ms"}}
},
{
"type": "timeseries",
"title": "RPS (2xx/4xx/5xx)",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 12},
"targets": [
{
"expr": "sum(rate(istio_requests_total{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\",response_code=~\"2..\"}[5m]))",
"legendFormat": "2xx"
},
{
"expr": "sum(rate(istio_requests_total{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\",response_code=~\"4..\"}[5m]))",
"legendFormat": "4xx"
},
{
"expr": "sum(rate(istio_requests_total{reporter=\"destination\",destination_namespace=\"$namespace\",destination_workload=\"$workload\",response_code=~\"5..\"}[5m]))",
"legendFormat": "5xx"
}
]
}
]
}

View File

@@ -0,0 +1,39 @@
---
# Istio Telemetry для сбора метрик
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
selector: {}
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_DURATION
tagOverrides:
"destination_workload": { operation: UPSERT, value: "%DESTINATION_WORKLOAD%" }
"destination_namespace": { operation: UPSERT, value: "%DESTINATION_NAMESPACE%" }
"request_host": { operation: UPSERT, value: "%REQUEST_HOST%" }
histogram:
buckets:
- 1
- 5
- 10
- 25
- 50
- 100
- 250
- 500
- 1000
- 2000
- 5000
- match:
metric: REQUEST_COUNT
tagOverrides:
"response_code": { operation: UPSERT, value: "%RESPONSE_CODE%" }

View File

@@ -0,0 +1,66 @@
---
# Istio Traffic Policy для управления трафиком
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# mesh-wide mTLS STRICT
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT
---
# Пример строгой политики для bookinfo (pool + outlier)
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: productpage-policy
namespace: bookinfo
spec:
host: productpage.bookinfo.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 1000
maxRequestsPerConnection: 100
outlierDetection:
consecutive5xx: 5
interval: 5s
baseEjectionTime: 30s
maxEjectionPercent: 50
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: reviews-policy
namespace: bookinfo
spec:
host: reviews.bookinfo.svc.cluster.local
subsets:
- name: v1
labels: { version: v1 }
- name: v2
labels: { version: v2 }
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 1000
maxRequestsPerConnection: 100
outlierDetection:
consecutive5xx: 3
interval: 5s
baseEjectionTime: 30s
maxEjectionPercent: 50

100
files/playbooks/site.yml Normal file
View File

@@ -0,0 +1,100 @@
---
# Основной playbook для универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- name: Base deps
hosts: all
become: true
tasks:
- name: Update apt cache (Debian)
apt:
update_cache: true
when: ansible_os_family == 'Debian'
changed_when: false
- name: Update yum cache (RHEL)
yum:
update_cache: true
when: ansible_os_family == 'RedHat'
changed_when: false
- name: Common tools
package:
name:
- curl
- jq
- ca-certificates
- iproute2
- iputils-ping
- procps
- net-tools
- sudo
- vim
- wget
- unzip
state: present
# Под каждую группу — свои роли. Подставь свои имена.
- name: ETCD
hosts: etcd
become: true
roles:
# - role: your_role_etcd
tasks:
- name: ETCD placeholder
debug:
msg: "ETCD группа готова для настройки"
- name: Patroni
hosts: patroni
become: true
roles:
# - role: your_role_patroni
tasks:
- name: Patroni placeholder
debug:
msg: "Patroni группа готова для настройки"
- name: HAProxy
hosts: haproxy
become: true
roles:
# - role: your_role_haproxy
tasks:
- name: HAProxy placeholder
debug:
msg: "HAProxy группа готова для настройки"
# Пример: развернуть docker-compose прямо внутри DinD хоста(ов)
- name: DinD stack deploy
hosts: apps
gather_facts: false
vars:
docker_host: "tcp://{{ inventory_hostname }}:2375"
stack_dir: /root/stack
tasks:
- name: Create stack directory
file:
path: "{{ stack_dir }}"
state: directory
- name: Copy demo docker-compose.yml
copy:
dest: "{{ stack_dir }}/docker-compose.yml"
content: |
version: "3.9"
services:
web:
image: nginx:alpine
ports: ["8080:80"]
cache:
image: redis:7-alpine
- name: Deploy stack on DinD
community.docker.docker_compose_v2:
project_src: "{{ stack_dir }}"
state: present
docker_host: "{{ docker_host }}"
when: item.type is defined and item.type == 'dind'
loop: "{{ groups['apps'] | map('extract', hostvars) | list }}"

8
files/requirements.yml Normal file
View File

@@ -0,0 +1,8 @@
---
# Коллекции Ansible для универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
collections:
- name: community.docker
- name: community.general

View File

@@ -0,0 +1,120 @@
---
# ПРЕСЕТ: Big Data кластер (12-18 машин)
#
# Описание: Кластер для обработки больших данных с различными компонентами
# - 3 Hadoop NameNode (активный/резервный/журнал) - метаданные
# - 3 Hadoop DataNode - хранение данных
# - 1 Hive Metastore - метаданные таблиц
# - 1 Spark Master - управление Spark
# - 2 Spark Worker - обработка данных
# - 1 Kafka Broker - потоковая обработка
# - 1 Zookeeper - координация сервисов
# - 1 Elasticsearch - поиск и аналитика
# - 1 Kibana - визуализация данных
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/bigdata.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: namenode1
group: namenodes
family: debian
publish:
- "9870:9870"
- name: namenode2
group: namenodes
family: rhel
publish:
- "9871:9870"
- name: namenode3
group: namenodes
family: debian
publish:
- "9872:9870"
- name: datanode1
group: datanodes
family: rhel
publish:
- "9864:9864"
- name: datanode2
group: datanodes
family: debian
publish:
- "9865:9864"
- name: datanode3
group: datanodes
family: rhel
publish:
- "9866:9864"
- name: hive-metastore
group: metastores
family: debian
publish:
- "9083:9083"
- name: spark-master
group: spark
family: rhel
publish:
- "8080:8080"
- name: spark-worker1
group: spark
family: debian
publish:
- "8081:8080"
- name: spark-worker2
group: spark
family: rhel
publish:
- "8082:8080"
- name: kafka
group: streaming
family: debian
publish:
- "9092:9092"
- name: zookeeper
group: coordination
family: rhel
publish:
- "2181:2181"
- name: elasticsearch
group: search
family: debian
publish:
- "9200:9200"
- name: kibana
group: visualization
family: rhel
publish:
- "5601:5601"

100
molecule/presets/cicd.yml Normal file
View File

@@ -0,0 +1,100 @@
---
# ПРЕСЕТ: CI/CD пайплайн (10-15 машин)
#
# Описание: Полноценный CI/CD пайплайн с различными инструментами
# - 1 Git сервер (Gitea) - управление кодом
# - 2 CI сервера (Jenkins) - сборка и тестирование
# - 1 артефакт репозиторий (Nexus) - хранение артефактов
# - 1 Docker registry - хранение образов
# - 2 тестовые среды (staging, production) - развертывание
# - 1 мониторинг (Prometheus) - метрики пайплайна
# - 1 логирование (ELK Stack) - централизованные логи
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/cicd.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: git-server
group: scm
family: debian
publish:
- "3000:3000"
- name: jenkins1
group: ci
family: rhel
publish:
- "8080:8080"
- name: jenkins2
group: ci
family: debian
publish:
- "8081:8080"
- name: nexus
group: artifacts
family: rhel
publish:
- "8081:8081"
- name: docker-registry
group: registries
family: debian
publish:
- "5000:5000"
- name: staging
group: environments
family: rhel
publish:
- "8082:80"
- name: production
group: environments
family: debian
publish:
- "8083:80"
- name: monitoring
group: monitoring
family: rhel
publish:
- "9090:9090"
- name: elasticsearch
group: logging
family: debian
publish:
- "9200:9200"
- name: kibana
group: logging
family: rhel
publish:
- "5601:5601"
- name: logstash
group: logging
family: debian
publish:
- "5044:5044"

View File

@@ -0,0 +1,58 @@
---
# ПРЕСЕТ: Docker-in-Docker Compose (4 DinD контейнера)
#
# Описание: DinD контейнеры для тестирования Docker Compose стека
# - 4 DinD контейнера с различными стеками
# - Тестирование multi-container приложений
# - Различные версии Docker Compose
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dind-compose.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: compose-web
type: dind
group: compose
publish:
- "2375:2375" # Docker API
- "8080:80" # Web port
- name: compose-api
type: dind
group: compose
publish:
- "2376:2375" # Docker API
- "8081:3000" # API port
- name: compose-db
type: dind
group: compose
publish:
- "2377:2375" # Docker API
- "8082:5432" # DB port
- name: compose-cache
type: dind
group: compose
publish:
- "2378:2375" # Docker API
- "8083:6379" # Cache port

View File

@@ -0,0 +1,51 @@
---
# ПРЕСЕТ: Docker-in-Docker Simple (3 DinD контейнера)
#
# Описание: Простая конфигурация DinD для тестирования Docker ролей
# - 3 DinD контейнера с различными конфигурациями
# - Изолированные Docker среды
# - Тестирование Docker Compose, Docker Swarm
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dind-simple.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: dind1
type: dind
group: dind
publish:
- "2375:2375" # Docker API
- "8080:8080" # App port
- name: dind2
type: dind
group: dind
publish:
- "2376:2375" # Docker API
- "8081:8080" # App port
- name: dind3
type: dind
group: dind
publish:
- "2377:2375" # Docker API
- "8082:8080" # App port

View File

@@ -0,0 +1,65 @@
---
# ПРЕСЕТ: Docker-in-Docker Swarm (5 DinD контейнеров)
#
# Описание: Docker Swarm кластер для тестирования оркестрации
# - 1 Manager + 4 Worker узла
# - Docker Swarm режим
# - Тестирование сервисов, стеков, секретов
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dind-swarm.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: swarm-manager
type: dind
group: swarm
publish:
- "2375:2375" # Docker API
- "8080:8080" # App port
- name: swarm-worker1
type: dind
group: swarm
publish:
- "2376:2375" # Docker API
- "8081:8080" # App port
- name: swarm-worker2
type: dind
group: swarm
publish:
- "2377:2375" # Docker API
- "8082:8080" # App port
- name: swarm-worker3
type: dind
group: swarm
publish:
- "2378:2375" # Docker API
- "8083:8080" # App port
- name: swarm-worker4
type: dind
group: swarm
publish:
- "2379:2375" # Docker API
- "8084:8080" # App port

View File

@@ -0,0 +1,89 @@
---
# ПРЕСЕТ: Docker-outside-of-Docker Mixed (5 DOoD + 2 systemd)
#
# Описание: Смешанная конфигурация DOoD и systemd контейнеров
# - 5 DOoD контейнеров для Docker операций
# - 2 systemd контейнера для системных ролей
# - Тестирование гибридных сценариев
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dood-mixed.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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:
# DOoD контейнеры
- name: dood-web
type: dood
family: debian
group: dood
publish:
- "8080:80"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood-api
type: dood
family: rhel
group: dood
publish:
- "8081:3000"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood-db
type: dood
family: debian
group: dood
publish:
- "8082:5432"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood-cache
type: dood
family: rhel
group: dood
publish:
- "8083:6379"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood-queue
type: dood
family: debian
group: dood
publish:
- "8084:5672"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
# Systemd контейнеры
- name: systemd-monitor
family: rhel
group: monitoring
publish:
- "9090:9090"
- name: systemd-logs
family: debian
group: logging
publish:
- "5601:5601"

View File

@@ -0,0 +1,57 @@
---
# ПРЕСЕТ: Docker-outside-of-Docker Simple (3 DOoD контейнера)
#
# Описание: Простая конфигурация DOoD для тестирования Docker ролей
# - 3 DOoD контейнера с доступом к Docker daemon хоста
# - Тестирование Docker ролей без изоляции
# - Различные семейства ОС
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/dood-simple.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: dood1
type: dood
family: debian
group: dood
publish:
- "8080:8080" # App port
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood2
type: dood
family: rhel
group: dood
publish:
- "8081:8080" # App port
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood3
type: dood
family: debian
group: dood
publish:
- "8082:8080" # App port
env:
DOCKER_HOST: "unix:///var/run/docker.sock"

View File

@@ -0,0 +1,167 @@
---
# ПРЕСЕТ: Enterprise (18-20 машин)
#
# Описание: Полноценная enterprise инфраструктура с высокой доступностью
# - 2 Load Balancer (HAProxy) - балансировка нагрузки
# - 3 Web сервера (nginx) - веб-приложения
# - 2 API Gateway (Kong) - управление API
# - 3 Application сервера - бизнес-логика
# - 2 Database Master/Slave (PostgreSQL) - основная БД
# - 2 Cache кластер (Redis) - кэширование
# - 1 Message Queue (RabbitMQ) - асинхронная обработка
# - 1 Search Engine (Elasticsearch) - поиск
# - 1 Monitoring (Prometheus) - метрики
# - 1 Logging (ELK Stack) - централизованные логи
# - 1 Backup сервер - резервное копирование
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/enterprise.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: lb1
group: loadbalancers
family: debian
publish:
- "80:80"
- "443:443"
- name: lb2
group: loadbalancers
family: rhel
publish:
- "8080:80"
- "8443:443"
- name: web1
group: webservers
family: rhel
publish:
- "8081:80"
- name: web2
group: webservers
family: debian
publish:
- "8082:80"
- name: web3
group: webservers
family: rhel
publish:
- "8083:80"
- name: api-gateway1
group: gateways
family: debian
publish:
- "8001:8000"
- name: api-gateway2
group: gateways
family: rhel
publish:
- "8002:8000"
- name: app1
group: applications
family: rhel
publish:
- "9001:9000"
- name: app2
group: applications
family: debian
publish:
- "9002:9000"
- name: app3
group: applications
family: rhel
publish:
- "9003:9000"
- name: db-master
group: databases
family: debian
publish:
- "5432:5432"
- name: db-slave
group: databases
family: rhel
publish:
- "5433:5432"
- name: cache1
group: caches
family: debian
publish:
- "6379:6379"
- name: cache2
group: caches
family: rhel
publish:
- "6380:6379"
- name: message-queue
group: queues
family: debian
publish:
- "5672:5672"
- "15672:15672"
- name: elasticsearch
group: search
family: rhel
publish:
- "9200:9200"
- name: monitoring
group: monitoring
family: debian
publish:
- "9090:9090"
- name: elasticsearch-logs
group: logging
family: rhel
publish:
- "9201:9200"
- name: kibana
group: logging
family: debian
publish:
- "5601:5601"
- name: logstash
group: logging
family: rhel
publish:
- "5044:5044"
- name: backup
group: backup
family: debian
publish:
- "22:22"

88
molecule/presets/ha.yml Normal file
View File

@@ -0,0 +1,88 @@
---
# ПРЕСЕТ: Высокая доступность (6-10 машин)
#
# Описание: Кластер высокой доступности с репликацией и отказоустойчивостью
# - 2 веб-сервера (nginx) - активный/резервный
# - 2 базы данных (PostgreSQL) - мастер/слейв репликация
# - 2 кэш-сервера (Redis) - кластер с репликацией
# - 1 балансировщик (HAProxy) - с проверками здоровья
# - 1 мониторинг (Prometheus) - контроль состояния
# - 1 резервный мониторинг (Grafana) - визуализация
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/ha.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: haproxy
group: loadbalancers
family: rhel
publish:
- "80:80"
- "443:443"
- name: web1
group: webservers
family: debian
publish:
- "8081:80"
- name: web2
group: webservers
family: rhel
publish:
- "8082:80"
- name: db-master
group: databases
family: debian
publish:
- "5432:5432"
- name: db-slave
group: databases
family: rhel
publish:
- "5433:5432"
- name: cache1
group: caches
family: debian
publish:
- "6379:6379"
- name: cache2
group: caches
family: rhel
publish:
- "6380:6379"
- name: monitoring
group: monitoring
family: debian
publish:
- "9090:9090"
- name: grafana
group: monitoring
family: rhel
publish:
- "3000:3000"

View File

@@ -0,0 +1,99 @@
---
# ПРЕСЕТ: Kubernetes кластер (8-12 машин)
#
# Описание: Полноценный Kubernetes кластер с различными ролями
# - 3 master ноды (control-plane) - управление кластером
# - 3 worker ноды - выполнение workload
# - 1 etcd кластер (3 ноды) - хранение состояния
# - 1 ingress контроллер - маршрутизация трафика
# - 1 мониторинг (Prometheus) - метрики кластера
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-cluster.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: master1
group: masters
family: debian
publish:
- "6443:6443"
- name: master2
group: masters
family: rhel
publish:
- "6444:6443"
- name: master3
group: masters
family: debian
publish:
- "6445:6443"
- name: worker1
group: workers
family: rhel
publish:
- "30000:30000"
- name: worker2
group: workers
family: debian
publish:
- "30001:30000"
- name: worker3
group: workers
family: rhel
publish:
- "30002:30000"
- name: etcd1
group: etcd
family: debian
publish:
- "2379:2379"
- name: etcd2
group: etcd
family: rhel
publish:
- "2380:2379"
- name: etcd3
group: etcd
family: debian
publish:
- "2381:2379"
- name: ingress
group: ingress
family: rhel
publish:
- "80:80"
- "443:443"
- name: monitoring
group: monitoring
family: debian
publish:
- "9090:9090"

View File

@@ -0,0 +1,55 @@
---
# ПРЕСЕТ: Kubernetes + Istio Full Stack (1 кластер с полным стеком)
#
# Описание: Полноценный Kubernetes кластер с полным стеком Istio
# - 1 Kind кластер с 3 workers
# - Полный Istio service mesh с Kiali
# - Prometheus + Grafana для мониторинга
# - Jaeger для трассировки
# - Все аддоны включены
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-istio-full.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
kind_clusters:
- name: istio-full
workers: 3
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
prometheus_stack: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
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: k8s-controller
group: controllers
family: debian
publish:
- "6443:6443"
- "9090:9090" # Prometheus
- "3000:3000" # Grafana
- "16686:16686" # Jaeger
- "20001:20001" # Kiali

View File

@@ -0,0 +1,46 @@
---
# Пресет для Kubernetes лаборатории с Kind кластерами
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Сеть для лаборатории
docker_network: labnet
# Kind кластеры
kind_clusters:
- name: lab
workers: 2
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
prometheus_stack: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
# Образы для разных семейств ОС
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
# Настройки по умолчанию для systemd контейнеров
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs:
- "/run"
- "/run/lock"
capabilities:
- "SYS_ADMIN"
# Определение хостов лаборатории (минимальный набор для k8s)
hosts:
- name: k8s-controller
group: controllers
family: debian
publish:
- "6443:6443"

View File

@@ -0,0 +1,81 @@
---
# ПРЕСЕТ: Kubernetes Multi-Cluster (3 кластера)
#
# Описание: Несколько Kind кластеров для тестирования мульти-кластерных сценариев
# - 3 Kind кластера: dev, staging, prod
# - Различные конфигурации для каждого окружения
# - Полный стек мониторинга и service mesh
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-multi.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
kind_clusters:
- name: dev
workers: 1
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
- name: staging
workers: 2
api_port: 6444
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
ingress_host_http_port: 8082
ingress_host_https_port: 8444
- name: prod
workers: 3
api_port: 6445
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
prometheus_stack: true
ingress_host_http_port: 8083
ingress_host_https_port: 8445
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: k8s-dev-controller
group: controllers
family: debian
publish:
- "6443:6443"
- name: k8s-staging-controller
group: controllers
family: rhel
publish:
- "6444:6444"
- name: k8s-prod-controller
group: controllers
family: debian
publish:
- "6445:6445"

View File

@@ -0,0 +1,46 @@
---
# ПРЕСЕТ: Kubernetes Single Node (1 кластер)
#
# Описание: Одиночный Kind кластер для простого тестирования K8s ролей
# - 1 Kind кластер с 1 worker
# - Базовые аддоны: Ingress NGINX, Metrics Server
# - Простая конфигурация для быстрого старта
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/k8s-single.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
kind_clusters:
- name: single
workers: 1
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
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: k8s-controller
group: controllers
family: debian
publish:
- "6443:6443"

View File

@@ -0,0 +1,181 @@
---
# ПРЕСЕТ: Максимальный (20 машин)
#
# Описание: Максимально сложная инфраструктура для тестирования в экстремальных условиях
# - 2 Load Balancer (HAProxy) - балансировка
# - 3 Web сервера (nginx) - веб-слой
# - 2 API Gateway (Kong) - API управление
# - 3 Application сервера - бизнес-логика
# - 2 Database Master/Slave (PostgreSQL) - основная БД
# - 2 Cache сервера (Redis) - кэширование
# - 1 Message Queue (RabbitMQ) - очереди
# - 1 Search Engine (Elasticsearch) - поиск
# - 1 Monitoring (Prometheus) - метрики
# - 1 Logging (ELK Stack) - логи
# - 1 Tracing (Jaeger) - трассировка
# - 1 Visualization (Grafana) - визуализация
# - 1 Backup сервер - резервное копирование
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/maximum.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: lb1
group: loadbalancers
family: debian
publish:
- "80:80"
- "443:443"
- name: lb2
group: loadbalancers
family: rhel
publish:
- "8080:80"
- "8443:443"
- name: web1
group: webservers
family: rhel
publish:
- "8081:80"
- name: web2
group: webservers
family: debian
publish:
- "8082:80"
- name: web3
group: webservers
family: rhel
publish:
- "8083:80"
- name: api-gateway1
group: gateways
family: debian
publish:
- "8001:8000"
- name: api-gateway2
group: gateways
family: rhel
publish:
- "8002:8000"
- name: app1
group: applications
family: rhel
publish:
- "9001:9000"
- name: app2
group: applications
family: debian
publish:
- "9002:9000"
- name: app3
group: applications
family: rhel
publish:
- "9003:9000"
- name: db-master
group: databases
family: debian
publish:
- "5432:5432"
- name: db-slave
group: databases
family: rhel
publish:
- "5433:5432"
- name: cache1
group: caches
family: debian
publish:
- "6379:6379"
- name: cache2
group: caches
family: rhel
publish:
- "6380:6379"
- name: message-queue
group: queues
family: debian
publish:
- "5672:5672"
- "15672:15672"
- name: elasticsearch
group: search
family: rhel
publish:
- "9200:9200"
- name: monitoring
group: monitoring
family: debian
publish:
- "9090:9090"
- name: elasticsearch-logs
group: logging
family: rhel
publish:
- "9201:9200"
- name: kibana
group: logging
family: debian
publish:
- "5601:5601"
- name: logstash
group: logging
family: rhel
publish:
- "5044:5044"
- name: tracing
group: tracing
family: debian
publish:
- "16686:16686"
- name: grafana
group: visualization
family: rhel
publish:
- "3000:3000"
- name: backup
group: backup
family: debian
publish:
- "22:22"

View File

@@ -0,0 +1,77 @@
---
# ПРЕСЕТ: Микросервисы (5-8 машин)
#
# Описание: Архитектура микросервисов с разделением ответственности
# - 1 API Gateway (Kong/Nginx) - единая точка входа
# - 2 микросервиса (User Service, Order Service) - бизнес-логика
# - 1 база данных (PostgreSQL) - основная БД
# - 1 кэш (Redis) - для сессий
# - 1 очередь сообщений (RabbitMQ) - асинхронная обработка
# - 1 мониторинг (Prometheus) - метрики
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/microservices.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: api-gateway
group: gateways
family: rhel
publish:
- "80:80"
- "443:443"
- name: user-service
group: microservices
family: debian
publish:
- "8081:8080"
- name: order-service
group: microservices
family: rhel
publish:
- "8082:8080"
- name: database
group: databases
family: debian
publish:
- "5432:5432"
- name: cache
group: caches
family: rhel
publish:
- "6379:6379"
- name: message-queue
group: queues
family: debian
publish:
- "5672:5672"
- "15672:15672"
- name: monitoring
group: monitoring
family: rhel
publish:
- "9090:9090"

View File

@@ -0,0 +1,48 @@
---
# ПРЕСЕТ: Минимальная лаборатория (1-3 машины)
#
# Описание: Базовая конфигурация для простых тестов Ansible ролей
# - 1 контроллер (Debian)
# - 1 веб-сервер (RHEL)
# - 1 база данных (Debian)
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/minimal.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: controller
group: controllers
family: debian
publish:
- "8080:80"
- name: webserver
group: webservers
family: rhel
publish:
- "80:80"
- name: database
group: databases
family: debian
publish:
- "5432:5432"

View File

@@ -0,0 +1,102 @@
---
# ПРЕСЕТ: Mixed Full Stack (1 K8s + 2 DinD + 2 DOoD + 2 systemd)
#
# Описание: Полная смешанная конфигурация для комплексного тестирования
# - 1 Kind кластер с полным стеком
# - 2 DinD контейнера для изолированных сред
# - 2 DOoD контейнера для Docker операций
# - 2 systemd контейнера для системных ролей
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/mixed-full.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
kind_clusters:
- name: full-stack
workers: 3
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
prometheus_stack: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
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:
# Kubernetes контроллер
- name: k8s-controller
group: controllers
family: debian
publish:
- "6443:6443"
- "9090:9090" # Prometheus
- "3000:3000" # Grafana
- "16686:16686" # Jaeger
- "20001:20001" # Kiali
# DinD контейнеры
- name: dind-dev
type: dind
group: dind
publish:
- "2375:2375"
- "8080:8080"
- name: dind-prod
type: dind
group: dind
publish:
- "2376:2375"
- "8081:8080"
# DOoD контейнеры
- name: dood-web
type: dood
family: debian
group: dood
publish:
- "8082:80"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood-api
type: dood
family: rhel
group: dood
publish:
- "8083:3000"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
# Systemd контейнеры
- name: systemd-monitor
family: rhel
group: monitoring
publish:
- "9091:9090"
- name: systemd-logs
family: debian
group: logging
publish:
- "5601:5601"

View File

@@ -0,0 +1,69 @@
---
# ПРЕСЕТ: Mixed Kubernetes + DinD (1 K8s + 3 DinD)
#
# Описание: Смешанная конфигурация Kubernetes и Docker-in-Docker
# - 1 Kind кластер для оркестрации
# - 3 DinD контейнера для изолированных Docker сред
# - Тестирование гибридных сценариев
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/mixed-k8s-dind.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
kind_clusters:
- name: hybrid
workers: 2
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
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:
# Kubernetes контроллер
- name: k8s-controller
group: controllers
family: debian
publish:
- "6443:6443"
# DinD контейнеры
- name: dind-dev
type: dind
group: dind
publish:
- "2375:2375"
- "8080:8080"
- name: dind-staging
type: dind
group: dind
publish:
- "2376:2375"
- "8081:8080"
- name: dind-prod
type: dind
group: dind
publish:
- "2377:2375"
- "8082:8080"

View File

@@ -0,0 +1,75 @@
---
# ПРЕСЕТ: Mixed Kubernetes + DOoD (1 K8s + 3 DOoD)
#
# Описание: Смешанная конфигурация Kubernetes и Docker-outside-of-Docker
# - 1 Kind кластер для оркестрации
# - 3 DOoD контейнера для Docker операций
# - Тестирование гибридных сценариев
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/mixed-k8s-dood.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
kind_clusters:
- name: hybrid
workers: 2
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
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:
# Kubernetes контроллер
- name: k8s-controller
group: controllers
family: debian
publish:
- "6443:6443"
# DOoD контейнеры
- name: dood-web
type: dood
family: debian
group: dood
publish:
- "8080:80"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood-api
type: dood
family: rhel
group: dood
publish:
- "8081:3000"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
- name: dood-db
type: dood
family: debian
group: dood
publish:
- "8082:5432"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"

View File

@@ -0,0 +1,135 @@
---
# ПРЕСЕТ: Service Mesh (15-20 машин)
#
# Описание: Полноценный service mesh с Istio и множественными сервисами
# - 1 Istio Control Plane - управление mesh
# - 1 Istio Ingress Gateway - входная точка
# - 1 Istio Egress Gateway - выходная точка
# - 3 Frontend сервиса - пользовательский интерфейс
# - 3 Backend API сервиса - бизнес-логика
# - 2 Database сервиса - хранение данных
# - 1 Cache сервис - кэширование
# - 1 Message Queue - асинхронная обработка
# - 1 Monitoring (Prometheus) - метрики mesh
# - 1 Tracing (Jaeger) - трассировка запросов
# - 1 Visualization (Kiali) - визуализация mesh
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/servicemesh.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: istio-control
group: istio
family: debian
publish:
- "15010:15010"
- name: istio-ingress
group: istio
family: rhel
publish:
- "80:80"
- "443:443"
- name: istio-egress
group: istio
family: debian
publish:
- "15443:15443"
- name: frontend1
group: frontend
family: rhel
publish:
- "3001:3000"
- name: frontend2
group: frontend
family: debian
publish:
- "3002:3000"
- name: frontend3
group: frontend
family: rhel
publish:
- "3003:3000"
- name: api1
group: backend
family: debian
publish:
- "8001:8000"
- name: api2
group: backend
family: rhel
publish:
- "8002:8000"
- name: api3
group: backend
family: debian
publish:
- "8003:8000"
- name: database1
group: databases
family: rhel
publish:
- "5432:5432"
- name: database2
group: databases
family: debian
publish:
- "5433:5432"
- name: cache
group: caches
family: rhel
publish:
- "6379:6379"
- name: message-queue
group: queues
family: debian
publish:
- "5672:5672"
- name: monitoring
group: monitoring
family: rhel
publish:
- "9090:9090"
- name: tracing
group: tracing
family: debian
publish:
- "16686:16686"
- name: kiali
group: visualization
family: rhel
publish:
- "20001:20001"

View File

@@ -0,0 +1,62 @@
---
# ПРЕСЕТ: Веб-приложение (3-5 машин)
#
# Описание: Классическая архитектура веб-приложения
# - 2 веб-сервера (nginx/apache) - балансировка нагрузки
# - 1 база данных (PostgreSQL) - основная БД
# - 1 кэш-сервер (Redis) - для сессий и кэширования
# - 1 обратный прокси (HAProxy) - балансировщик
#
# Использование: make lab-test SCENARIO=universal LAB_SPEC=molecule/presets/webapp.yml
#
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
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: haproxy
group: loadbalancers
family: rhel
publish:
- "80:80"
- "443:443"
- name: web1
group: webservers
family: debian
publish:
- "8081:80"
- name: web2
group: webservers
family: rhel
publish:
- "8082:80"
- name: database
group: databases
family: debian
publish:
- "5432:5432"
- name: cache
group: caches
family: rhel
publish:
- "6379:6379"

View File

@@ -0,0 +1,21 @@
---
# Запуск ролей в универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- hosts: localhost
gather_facts: false
tasks:
- name: Install collections in controller
community.docker.docker_container_exec:
container: ansible-controller
command: bash -lc "ansible-galaxy collection install -r /ansible/files/requirements.yml || true"
- name: Run external playbook (your roles live in /ansible/roles)
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc "
ANSIBLE_ROLES_PATH=/ansible/roles
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/files/playbooks/site.yml
"

View File

@@ -0,0 +1,271 @@
---
# Создание инфраструктуры универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- hosts: localhost
gather_facts: false
vars_files:
- vars.yml
tasks:
- name: Ensure network exists
community.docker.docker_network:
name: "{{ docker_network }}"
state: present
- name: Pull systemd images
community.docker.docker_image:
name: "{{ images[item.family] }}"
source: pull
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control:
label: "{{ 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 }}"
tmpfs: "{{ systemd_defaults.tmpfs }}"
capabilities: "{{ systemd_defaults.capabilities }}"
published_ports: "{{ item.publish | default([]) }}"
state: started
restart_policy: unless-stopped
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control:
label: "{{ item.name }}"
- name: Start DinD nodes
community.docker.docker_container:
name: "{{ item.name }}"
image: "docker:27-dind"
privileged: true
environment:
DOCKER_TLS_CERTDIR: ""
networks:
- name: "{{ docker_network }}"
published_ports: "{{ item.publish | default([]) }}"
volumes:
- "{{ 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 }}"
- name: Start DOoD 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([]) }}"
- "/var/run/docker.sock:/var/run/docker.sock"
tmpfs: "{{ systemd_defaults.tmpfs }}"
capabilities: "{{ systemd_defaults.capabilities }}"
published_ports: "{{ item.publish | default([]) }}"
state: started
restart_policy: unless-stopped
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}"
loop_control:
label: "{{ item.name }}"
# ---------- Build multi-group map ----------
- name: Init 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 | default([])) | subelements('groups', skip_missing=True) }}"
loop_control:
label: "{{ item.0.name }}"
vars:
item_name: "{{ item.0.name }}"
item_group: "{{ item.1 }}"
when: item.0.groups is defined
- name: Append hosts to single group
set_fact:
groups_map: >-
{{
groups_map | combine(
{ item.group: (groups_map[item.group] | default([])) + [item.name] }
)
}}
loop: "{{ hosts | default([]) }}"
loop_control:
label: "{{ item.name }}"
when: item.group is defined and item.groups is not defined
# ---------- INI inventory ----------
- name: Render inventory.ini
set_fact:
inv_ini: |
[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 | default([])) %}{{ h.name }}
{% endfor %}
- name: Write hosts.ini
copy:
dest: "{{ generated_inventory }}"
content: "{{ inv_ini }}"
mode: "0644"
# ---------- Kind clusters (если определены) ----------
- name: Create kind cluster configs
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
mkdir -p /ansible/.kind;
cat > /ansible/.kind/{{ item.name }}.yaml <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
{% if (item.addons|default({})).ingress_nginx|default(false) %}
extraPortMappings:
- containerPort: 80
hostPort: {{ item.ingress_host_http_port | default(8081) }}
protocol: TCP
- containerPort: 443
hostPort: {{ item.ingress_host_https_port | default(8443) }}
protocol: TCP
{% endif %}
{% for i in range(item.workers | default(0)) %}
- role: worker
{% endfor %}
networking:
apiServerAddress: "0.0.0.0"
apiServerPort: {{ item.api_port | default(0) }}
EOF
'
loop: "{{ kind_clusters | default([]) }}"
when: (kind_clusters | default([])) | length > 0
- name: Create kind clusters
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
for n in {{ (kind_clusters | default([]) | map(attribute="name") | list) | map('quote') | join(' ') }}; do
if kind get clusters | grep -qx "$$n"; then
echo "[kind] cluster $$n already exists";
else
echo "[kind] creating $$n";
kind create cluster --name "$$n" --config "/ansible/.kind/$$n.yaml";
fi
done
'
when: (kind_clusters | default([])) | length > 0
- name: Install Ingress NGINX, Metrics Server, Istio, Kiali, Prometheus Stack (per cluster, if enabled)
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
helm repo add kiali https://kiali.org/helm-charts >/dev/null 2>&1 || true;
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts >/dev/null 2>&1 || true;
helm repo update >/dev/null 2>&1 || true;
for n in {{ (kind_clusters | default([]) | map(attribute="name") | list) | map('quote') | join(' ') }}; do
# ingress-nginx
if {{ (kind_clusters | items2dict(key_name="name", value_name="addons")).get(n, {}).get("ingress_nginx", False) | to_json }}; then
echo "[addons] ingress-nginx on $$n";
kubectl --context kind-$$n apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml || true;
kubectl --context kind-$$n -n ingress-nginx rollout status deploy/ingress-nginx-controller --timeout=180s || true;
fi
# metrics-server
if {{ (kind_clusters | items2dict(key_name="name", value_name="addons")).get(n, {}).get("metrics_server", False) | to_json }}; then
echo "[addons] metrics-server on $$n";
kubectl --context kind-$$n apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml || true;
kubectl --context kind-$$n -n kube-system patch deploy metrics-server -p \
"{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"metrics-server\",\"args\":[\"--kubelet-insecure-tls\",\"--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname\"]}]}}}}}" || true;
fi
# istio (demo profile)
if {{ (kind_clusters | items2dict(key_name="name", value_name="addons")).get(n, {}).get("istio", False) | to_json }}; then
echo "[addons] istio (demo profile) on $$n";
istioctl install -y --set profile=demo --context kind-$$n;
kubectl --context kind-$$n -n istio-system rollout status deploy/istiod --timeout=180s || true;
kubectl --context kind-$$n -n istio-system rollout status deploy/istio-ingressgateway --timeout=180s || true;
fi
# kiali (server chart, anonymous auth) — требует istio/metrics
if {{ (kind_clusters | items2dict(key_name="name", value_name="addons")).get(n, {}).get("kiali", False) | to_json }}; then
echo "[addons] kiali on $$n";
kubectl --context kind-$$n create ns istio-system >/dev/null 2>&1 || true;
helm upgrade --install kiali-server kiali/kiali-server \
--namespace istio-system --kube-context kind-$$n \
--set auth.strategy=anonymous --wait --timeout 180s;
fi
# kube-prometheus-stack (Prometheus + Grafana)
if {{ (kind_clusters | items2dict(key_name="name", value_name="addons")).get(n, {}).get("prometheus_stack", False) | to_json }}; then
echo "[addons] kube-prometheus-stack on $$n";
kubectl --context kind-$$n create ns monitoring >/dev/null 2>&1 || true;
helm upgrade --install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring --kube-context kind-$$n \
--set grafana.adminPassword=admin \
--set grafana.defaultDashboardsTimezone=browser \
--wait --timeout 600s;
# дождаться графаны
kubectl --context kind-$$n -n monitoring rollout status deploy/monitoring-grafana --timeout=300s || true;
fi
done
'
when: (kind_clusters | default([])) | length > 0
- name: Apply Istio Telemetry + mesh mTLS + Grafana dashboards (per cluster)
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
for n in {{ (kind_clusters | default([]) | map(attribute="name") | list) | map("quote") | join(" ") }}; do
# Telemetry/mTLS — только если istio есть
if {{ (kind_clusters | items2dict(key_name="name", value_name="addons")).get(n, {}).get("istio", False) | to_json }}; then
echo "[istio] applying Telemetry + PeerAuthentication on $$n";
kubectl --context kind-$$n -n istio-system apply -f /ansible/files/k8s/istio/telemetry.yaml || true;
kubectl --context kind-$$n -n istio-system apply -f /ansible/files/k8s/istio/trafficpolicy.yaml --dry-run=client -o yaml >/dev/null 2>&1 || true;
# DestinationRule из trafficpolicy — namespace bookinfo, создадим позже в verify после деплоя
fi
# Grafana dashboards (ConfigMap with label grafana_dashboard=1)
if {{ (kind_clusters | items2dict(key_name="name", value_name="addons")).get(n, {}).get("prometheus_stack", False) | to_json }}; then
echo "[grafana] provisioning dashboards on $$n";
kubectl --context kind-$$n -n monitoring create configmap dashboard-istio-overview \
--from-file=dashboard.json=/ansible/files/grafana/dashboards/istio-overview.json \
--dry-run=client -o yaml | kubectl --context kind-$$n apply -f -;
kubectl --context kind-$$n -n monitoring label configmap dashboard-istio-overview grafana_dashboard=1 --overwrite;
kubectl --context kind-$$n -n monitoring create configmap dashboard-service-sli \
--from-file=dashboard.json=/ansible/files/grafana/dashboards/service-sli.json \
--dry-run=client -o yaml | kubectl --context kind-$$n apply -f -;
kubectl --context kind-$$n -n monitoring label configmap dashboard-service-sli grafana_dashboard=1 --overwrite;
fi
done
'
when: (kind_clusters | default([])) | length > 0

View File

@@ -0,0 +1,50 @@
---
# Уничтожение инфраструктуры универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- hosts: localhost
gather_facts: false
vars_files:
- vars.yml
tasks:
- 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 containers
community.docker.docker_container:
name: "{{ item.name }}"
state: absent
force_kill: true
loop: "{{ hosts }}"
loop_control:
label: "{{ item.name }}"
ignore_errors: true
- name: Remove network
community.docker.docker_network:
name: "{{ docker_network }}"
state: absent
ignore_errors: true
- name: Remove kind clusters
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
for n in {{ (kind_clusters | default([]) | map(attribute="name") | list) | map('quote') | join(' ') }}; do
if kind get clusters | grep -qx "$$n"; then
echo "[kind] deleting $$n";
kind delete cluster --name "$$n" || true;
fi
done
'
when: (kind_clusters | default([])) | length > 0
ignore_errors: true

View File

@@ -0,0 +1,57 @@
---
# Универсальная лаборатория для тестирования Ansible ролей
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
driver:
name: docker
platforms:
- name: instance-ubuntu
image: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
privileged: true
pre_build_image: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
capabilities:
- "SYS_ADMIN"
tmpfs:
- "/run"
- "/run/lock"
provisioner:
name: ansible
config_options:
defaults:
stdout_callback: default
callbacks_enabled: profile_tasks
env:
ANSIBLE_STDOUT_CALLBACK: default
dependency:
name: galaxy
enabled: false
verifier:
name: ansible
lint: |-
set -e
ansible-lint
scenario:
name: universal
test_sequence:
- dependency
- cleanup
- destroy
- syntax
- create
- prepare
- converge
- idempotence
- side_effect
- verify
- cleanup
- destroy

View File

@@ -0,0 +1,90 @@
---
# Конфигурация универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Сеть для лаборатории
docker_network: labnet
# Образы для разных семейств ОС
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
# Можно использовать собственные образы
# debian: "inecs/ansible:ubuntu"
# rhel: "inecs/ansible:centos"
# Настройки по умолчанию для systemd контейнеров
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs:
- "/run"
- "/run/lock"
capabilities:
- "SYS_ADMIN"
# Определение хостов лаборатории
hosts:
# Пример: etcd кластер
- name: etcd1
group: etcd
family: debian
- name: etcd2
group: etcd
family: debian
- name: etcd3
group: etcd
family: debian
# Пример: PostgreSQL с Patroni
- name: patroni1
group: patroni
family: rhel
- name: patroni2
group: patroni
family: rhel
- name: patroni3
group: patroni
family: rhel
# Пример: HAProxy
- name: haproxy
group: haproxy
family: rhel
publish:
- "5000:5000" # RW порт
- "5001:5001" # RO порт
# Пример: DinD узел для изоляции
- name: app-dind
group: apps
type: dind
publish:
- "8080:8080"
# Пример: DOoD узел (Docker Outside of Docker)
- name: app-dood
group: apps
type: dood
publish:
- "8081:8081"
# Kind кластеры (опционально)
kind_clusters:
- name: lab
workers: 2
api_port: 6443
addons:
ingress_nginx: true
metrics_server: true
istio: true
kiali: true
prometheus_stack: true
ingress_host_http_port: 8081
ingress_host_https_port: 8443
# Пути для файлов
generated_inventory: "${MOLECULE_EPHEMERAL_DIRECTORY}/inventory/hosts.ini"

View File

@@ -0,0 +1,278 @@
---
# Проверка работы универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- hosts: localhost
gather_facts: false
vars:
inv_yaml: "{{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.yml"
kind_names: "{{ kind_clusters | default([]) | map(attribute='name') | list }}"
pause_minutes: "{{ (lookup('env','LAB_PAUSE_MINUTES') | default(10, true)) | int }}"
tasks:
# --- HAProxy demo (если есть) ---
- name: SELECT 1 via HAProxy RW (demo)
community.docker.docker_container_exec:
container: ansible-controller
command: bash -lc "psql -h haproxy -p 5000 -U postgres -d postgres -tAc 'select 1;'"
environment: { PGPASSWORD: postgres }
register: sel_rw
failed_when: false
ignore_errors: true
# --- Idempotence ---
- name: Idempotence run
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc "
ANSIBLE_ROLES_PATH=/ansible/roles
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/files/playbooks/site.yml --check"
register: idemp
# --- Helm demo nginx + Ingress + Toolbox per cluster ---
- name: Helm nginx install & Ingress & Toolbox (per cluster)
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
helm repo add bitnami https://charts.bitnami.com/bitnami >/dev/null 2>&1 || true;
helm repo update >/dev/null 2>&1 || true;
for n in {{ kind_names | map('quote') | join(' ') }}; do
ns="lab-demo"; rel="nginx-$$n";
kubectl --context kind-$$n create ns $$ns >/dev/null 2>&1 || true;
# метка для автосайдкаров Istio — не мешает, если Istio отключен
kubectl --context kind-$$n label ns $$ns istio-injection=enabled --overwrite >/dev/null 2>&1 || true;
echo "[helm] installing $$rel";
helm upgrade --install $$rel bitnami/nginx --namespace $$ns --kube-context kind-$$n --wait --timeout 180s;
# Ingress (ingressClassName: nginx), бэкенд на сервис релиза
cat <<EOF | kubectl --context kind-$$n -n $$ns apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: $$rel
port:
number: 80
EOF
# Toolbox — чтобы можно было "зайти в кластер"
cat <<EOF | kubectl --context kind-$$n -n $$ns apply -f -
apiVersion: apps/v1
kind: Deployment
metadata: { name: toolbox }
spec:
replicas: 1
selector: { matchLabels: { app: toolbox } }
template:
metadata: { labels: { app: toolbox } }
spec:
containers:
- name: sh
image: alpine:3
command: ["/bin/sh","-c","sleep 1000000"]
EOF
kubectl --context kind-$$n -n $$ns rollout status deploy/toolbox --timeout=90s || true
# curl по Ingress с хоста: http://localhost:<mapped>
http_port="{{ (kind_clusters | items2dict(key_name='name', value_name='ingress_host_http_port')).get(n, 8081) }}"
echo "[ingress] test curl http://localhost:${http_port}/";
curl -sS -o /dev/null -w "%{http_code}" "http://localhost:${http_port}/" || true
done
'
register: helm_ingress_toolbox
when: kind_names | length > 0
failed_when: false
# --- Istio/Kiali overview (если включены) ---
- name: Istio & Kiali status
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
for n in {{ kind_names | map('quote') | join(' ') }}; do
echo "=== $$n istio pods ===";
kubectl --context kind-$$n -n istio-system get pods -o wide || true;
echo "=== $$n services (istio-system) ===";
kubectl --context kind-$$n -n istio-system get svc || true;
done
'
register: istio_kiali
when: kind_names | length > 0
failed_when: false
# === Istio Bookinfo demo (если включён Istio) ===
- name: Deploy Istio Bookinfo + Gateway/Routes (per cluster)
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
for n in {{ kind_names | map('quote') | join(' ') }}; do
# проверим что istio есть (namespace и istiod)
if ! kubectl --context kind-$$n get ns istio-system >/dev/null 2>&1; then
echo "[bookinfo] skip $$n: istio not installed"; continue;
fi
kubectl --context kind-$$n create ns bookinfo >/dev/null 2>&1 || true;
kubectl --context kind-$$n label ns bookinfo istio-injection=enabled --overwrite || true;
# Bookinfo (официальные манифесты)
kubectl --context kind-$$n -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/release-1.22/samples/bookinfo/platform/kube/bookinfo.yaml;
# DestinationRules (подсети версий)
kubectl --context kind-$$n -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/release-1.22/samples/bookinfo/networking/destination-rule-all.yaml;
# Gateway + VirtualService (route 90% v1, 10% v2 для reviews)
cat <<EOF | kubectl --context kind-$$n -n bookinfo apply -f -
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata: { name: bookinfo-gateway }
spec:
selector:
istio: ingressgateway
servers:
- port: { number: 80, name: http, protocol: HTTP }
hosts: ["*"]
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata: { name: bookinfo }
spec:
hosts: ["*"]
gateways: ["bookinfo-gateway"]
http:
- match:
- uri:
prefix: /productpage
- uri:
prefix: /static
- uri:
prefix: /login
- uri:
prefix: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port: { number: 9080 }
- match:
- uri:
prefix: /reviews
route:
- destination:
host: reviews
subset: v1
port: { number: 9080 }
weight: 90
- destination:
host: reviews
subset: v2
port: { number: 9080 }
weight: 10
EOF
# Ждём доступности productpage/reviews
kubectl --context kind-$$n -n bookinfo rollout status deploy/productpage-v1 --timeout=180s || true
kubectl --context kind-$$n -n bookinfo rollout status deploy/reviews-v1 --timeout=180s || true
kubectl --context kind-$$n -n bookinfo rollout status deploy/reviews-v2 --timeout=180s || true
echo "[bookinfo] try curl through Istio IngressGateway (port-forward 8082 if needed)";
done
'
register: istio_bookinfo
when: kind_names | length > 0
failed_when: false
- name: Apply DestinationRule TrafficPolicy for bookinfo (after deploy)
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
for n in {{ kind_names | map("quote") | join(" ") }}; do
if kubectl --context kind-$$n get ns bookinfo >/dev/null 2>&1; then
echo "[istio] traffic policies for bookinfo on $$n";
# из общего файла — применятся только DR в namespace bookinfo
kubectl --context kind-$$n -n bookinfo apply -f /ansible/files/k8s/istio/trafficpolicy.yaml || true;
fi
done
'
when: kind_names | length > 0
failed_when: false
# --- K8s overview (nodes & kube-system pods) ---
- name: Collect k8s overview
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -e;
for n in {{ kind_names | map('quote') | join(' ') }}; do
echo "=== $$n nodes ===";
kubectl --context kind-$$n get nodes -o wide || true;
echo "=== $$n pods kube-system ===";
kubectl --context kind-$$n -n kube-system get pods -o wide || true;
done
'
register: k8s_overview
when: kind_names | length > 0
failed_when: false
# --- Health JSON (для HTML отчёта) ---
- name: Build health report JSON
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -euo pipefail;
mkdir -p /ansible/reports;
jq -n \
--arg time "$$(date -Is)" \
--arg idemp "{{ idemp.stdout | to_json | replace("\"","\\\"") }}" \
--arg haproxy_sel "{{ sel_rw.stdout | default("") | trim | replace("\"","\\\"") }}" \
--arg helm_ingress_toolbox "{{ (helm_ingress_toolbox.stdout | default("")) | replace("\"","\\\"") }}" \
--arg istio_kiali "{{ (istio_kiali.stdout | default("")) | replace("\"","\\\"") }}" \
--arg istio_bookinfo "{{ (istio_bookinfo.stdout | default("")) | replace("\"","\\\"") }}" \
--arg k8s_overview "{{ (k8s_overview.stdout | default("")) | replace("\"","\\\"") }}" \
"{
timestamp: $$time,
idempotence_raw: $$idemp,
haproxy_select1: $$haproxy_sel,
helm_ingress_toolbox_raw: $$helm_ingress_toolbox,
istio_kiali_raw: $$istio_kiali,
istio_bookinfo_raw: $$istio_bookinfo,
k8s_overview_raw: $$k8s_overview
}" > /ansible/reports/lab-health.json
'
when: kind_names | length > 0
# --- Final summary ---
- name: Final summary
debug:
msg: |
========================================
РЕЗУЛЬТАТЫ ПРОВЕРКИ УНИВЕРСАЛЬНОЙ ЛАБОРАТОРИИ:
========================================
Idempotence: {{ '✓ Успешно' if idemp is succeeded else '✗ Ошибка' }}
HAProxy: {{ '✓ Работает' if sel_rw is succeeded else '✗ Недоступен' }}
Kubernetes: {{ '✓ Готов' if k8s_overview is succeeded else '✗ Недоступен' }}
========================================

12
scripts/cleanup.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Очистка лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
set -euo pipefail
echo "[cleanup] removing lab containers/volumes/networks"
docker ps -aq --filter "label=ansible.lab=true" | xargs -r docker rm -f
docker volume ls -q --filter "name=_docker$" | xargs -r docker volume rm
docker network rm labnet >/dev/null 2>&1 || true
echo "done."

143
scripts/report_html.py Executable file
View File

@@ -0,0 +1,143 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Генератор HTML отчетов для универсальной лаборатории
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
import sys
import json
import html
import datetime
def main():
if len(sys.argv) < 3:
print("Usage: report_html.py <input.json> <output.html>")
sys.exit(1)
inp, outp = sys.argv[1], sys.argv[2]
try:
with open(inp, 'r', encoding='utf-8') as f:
data = json.load(f)
except Exception as e:
data = {"error": f"failed to read json: {e}"}
ts = data.get("timestamp", datetime.datetime.utcnow().isoformat())
idemp_raw = data.get("idempotence_raw", "")
haproxy_sel = data.get("haproxy_select1", "")
helm_ingress_toolbox = data.get("helm_ingress_toolbox_raw", "")
istio_kiali = data.get("istio_kiali_raw", "")
istio_bookinfo = data.get("istio_bookinfo_raw", "")
k8s_overview = data.get("k8s_overview_raw", "")
def badge(label, ok):
color = "#10b981" if ok else "#ef4444"
return f'<span class="badge" style="background:{color}">{html.escape(label)}</span>'
# Анализ статусов
idempotent_ok = ("changed=0" in idemp_raw)
haproxy_ok = (haproxy_sel.strip() == "1") if haproxy_sel else None
ingress_ok = ("ingress" in helm_ingress_toolbox.lower()) or ("curl http://localhost" in helm_ingress_toolbox.lower())
toolbox_ok = ("deploy/toolbox" in helm_ingress_toolbox.lower()) or ("rollout status" in helm_ingress_toolbox.lower())
istio_ok = ("istio-system" in istio_kiali.lower()) and ("istiod" in istio_kiali.lower())
kiali_ok = ("kiali" in istio_kiali.lower())
bookinfo_ok = ("bookinfo" in istio_bookinfo.lower()) or ("productpage" in istio_bookinfo.lower())
k8s_ok = ("nodes" in k8s_overview.lower()) and ("pods" in k8s_overview.lower())
def maybe_badge(label, status):
if status is None:
return f'<span class="badge" style="background:#6b7280">{html.escape(label)}: n/a</span>'
return badge(f"{label}", bool(status))
html_doc = f"""<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Lab Report</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
:root {{ --bg:#0f172a; --card:#111827; --muted:#94a3b8; --fg:#e5e7eb; --accent:#38bdf8; }}
* {{ box-sizing:border-box; }}
body {{ margin:0; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Arial;
background:linear-gradient(180deg,#0b1220,#0f172a); color:var(--fg); }}
.container {{ max-width:1100px; margin:40px auto; padding:0 16px; }}
.hdr {{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; }}
.hdr h1 {{ margin:0; font-size:28px; }}
.time {{ color:var(--muted); font-size:14px; }}
.grid {{ display:grid; grid-template-columns:1fr; gap:16px; margin-top:20px; }}
.card {{ background:rgba(17,24,39,.7); border:1px solid rgba(148,163,184,.15);
border-radius:14px; padding:16px; box-shadow:0 10px 30px rgba(0,0,0,.25); backdrop-filter: blur(6px); }}
.card h2 {{ margin:0 0 10px 0; font-size:18px; color:#c7d2fe; }}
pre {{ margin:0; padding:12px; background:#0b1220; border-radius:10px; overflow:auto; font-size:12px; line-height:1.4; }}
.badge {{ display:inline-block; padding:4px 10px; border-radius:999px; font-size:12px; color:white; }}
.kv {{ display:flex; flex-wrap:wrap; gap:8px; margin:8px 0 0 0; }}
footer {{ margin:24px 0 40px; color:var(--muted); font-size:12px; text-align:center; }}
a {{ color: var(--accent); text-decoration:none; }} a:hover {{ text-decoration:underline; }}
</style>
</head>
<body>
<div class="container">
<div class="hdr">
<h1>Ansible Lab Report</h1>
<div class="time">generated: {html.escape(ts)}</div>
</div>
<div class="grid">
<div class="card">
<h2>Summary</h2>
<div class="kv">
{badge("Idempotent", idempotent_ok)}
{maybe_badge("HAProxy SELECT=1", haproxy_ok)}
{maybe_badge("Ingress ready", ingress_ok)}
{maybe_badge("Toolbox ready", toolbox_ok)}
{maybe_badge("Istio ready", istio_ok)}
{maybe_badge("Kiali ready", kiali_ok)}
{maybe_badge("Bookinfo ready", bookinfo_ok)}
{maybe_badge("K8s ready", k8s_ok)}
</div>
</div>
<div class="card">
<h2>Idempotence (raw)</h2>
<pre>{html.escape(idemp_raw) if idemp_raw else "n/a"}</pre>
</div>
<div class="card">
<h2>Helm + Ingress + Toolbox (raw)</h2>
<pre>{html.escape(helm_ingress_toolbox) if helm_ingress_toolbox else "n/a"}</pre>
</div>
<div class="card">
<h2>Istio / Kiali (raw)</h2>
<pre>{html.escape(istio_kiali) if istio_kiali else "n/a"}</pre>
</div>
<div class="card">
<h2>Istio Bookinfo (raw)</h2>
<pre>{html.escape(istio_bookinfo) if istio_bookinfo else "n/a"}</pre>
</div>
<div class="card">
<h2>K8s Overview (raw)</h2>
<pre>{html.escape(k8s_overview) if k8s_overview else "n/a"}</pre>
</div>
<div class="card">
<h2>HAProxy SELECT 1</h2>
<pre>{html.escape(haproxy_sel) if haproxy_sel else "n/a"}</pre>
</div>
</div>
<footer>HTML from /ansible/reports/lab-health.json · kubeconfigs in reports/kubeconfigs/</footer>
</div>
</body>
</html>"""
with open(outp, "w", encoding="utf-8") as f:
f.write(html_doc)
print(outp)
if __name__ == "__main__":
main()

25
scripts/restore.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Восстановление лаборатории из снапшотов
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
set -euo pipefail
IN_DIR="snapshots"
if [ ! -d "$IN_DIR" ]; then
echo "No snapshots dir"
exit 1
fi
for f in "$IN_DIR"/*.image; do
if [ ! -f "$f" ]; then
continue
fi
name=$(basename "$f" .image)
img=$(cat "$f")
echo "[restore] $name from $img"
docker rm -f "$name" >/dev/null 2>&1 || true
docker run -d --name "$name" "$img" >/dev/null
done
echo "Restored from $IN_DIR/"

26
scripts/snapshot.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Снапшот лаборатории
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
set -euo pipefail
OUT_DIR="snapshots"
mkdir -p "$OUT_DIR"
# Найти все контейнеры лаборатории
ids=$(docker ps -q --filter "label=ansible.lab=true")
if [ -z "$ids" ]; then
echo "No lab containers to snapshot"
exit 0
fi
for id in $ids; do
name=$(docker inspect --format '{{.Name}}' "$id" | sed 's#^/##')
img="lab-snap-$name:latest"
echo "[snapshot] $name -> $img"
docker commit "$id" "$img" >/dev/null
echo "$img" > "$OUT_DIR/$name.image"
done
echo "Snapshots saved to $OUT_DIR/"

View File

@@ -1 +1 @@
password123
test