--- # Проверка работы универсальной лаборатории # Автор: Сергей Антропов # Сайт: 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 < 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 < 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 '✗ Недоступен' }} ========================================