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
This commit is contained in:
2025-10-22 13:01:53 +03:00
parent deebf78047
commit b4881da7c5
14 changed files with 1051 additions and 12 deletions

View File

@@ -0,0 +1,153 @@
---
# Проверка работы универсальной лаборатории
# Автор: Сергей Антропов
# Сайт: 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;
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
# --- 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 k8s_overview "{{ (k8s_overview.stdout | default("")) | replace("\"","\\\"") }}" \
"{
timestamp: $$time,
idempotence_raw: $$idemp,
haproxy_select1: $$haproxy_sel,
helm_ingress_toolbox_raw: $$helm_ingress_toolbox,
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 '✗ Недоступен' }}
========================================