AWX на Kubernetes operator: переезжаем с Docker Compose, подключаем Event-Driven Ansible
Мигрировали AWX 22.x с Docker Compose на Kubernetes operator через Deckhouse. Встроенный мониторинг Prometheus, первые опыты с EDA и алертами Zabbix.
AWX 22.x / Ansible Automation Platform 2.3 - стабильный Kubernetes operator и Event-Driven Ansible для реагирования на события мониторинга
AWX на Docker Compose - это то, что ставишь быстро, и потом живёшь с этим несколько лет. Работает, не трогаем. Но у такого подхода есть потолок: нет нормального HA, обновления - ритуал с остановкой, мониторинг надо городить вручную. Когда у клиента уже стоит Kubernetes (в нашем случае Deckhouse), логично переехать туда. Тем более что AWX operator с версии 2.x считается стабильным, а не экспериментом.
Что было и зачем менять
У клиента AWX 19.x на Docker Compose, отдельная VM под это дело. Playbook-и запускаются по расписанию и вручную через UI, несколько десятков шаблонов, credential-и завёрнуты в AWX Vault. Всё работало, претензий не было - кроме одной: при обновлении AWX нужно останавливать сервис, и это всегда немного нервно, потому что docker-compose pull && docker-compose up -d на старой схеме регулярно приносил сюрпризы с миграциями базы.
Плюс у клиента уже есть Deckhouse-кластер, который мы ставили в мае. Прогонять автоматизацию через отдельную VM, когда рядом стоит нормальный кластер с мониторингом, ingress и управляемым жизненным циклом - немного странно.
Установка operator: проще, чем ожидали
AWX operator устанавливается через Helm или напрямую через kustomize. Мы пошли через Helm - привычнее и укладывается в наш GitOps-процесс на базе Deckhouse.
helm repo add awx-operator https://ansible.github.io/awx-operator/
helm install awx-operator awx-operator/awx-operator \
-n awx --create-namespace \
--set AWX.enabled=false
Дальше - Custom Resource AWX:
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx-prod
namespace: awx
spec:
service_type: ClusterIP
ingress_type: ingress
hostname: awx.internal.example.com
postgres_storage_class: ceph-block
projects_persistence: true
projects_storage_class: ceph-block
projects_storage_size: 20Gi
Operator поднял PostgreSQL как StatefulSet, сам AWX (web + task + ee-контейнеры), Redis. Минут через десять всё зелёное. Это приятно контрастировало с Docker Compose, где ты сам следил за порядком поднятия сервисов.
Один нюанс, который сразу словили: projects_storage_class обязательно нужно указывать явно, иначе operator берёт default StorageClass кластера - у нас это ceph-fs (CephFS), а для Projects AWX лучше подходит block-storage из-за особенностей работы с git-репозиториями. Переключили на ceph-block, стало ощутимо быстрее при clone проектов.
Миграция данных: credential-и, шаблоны, инвентари
Экспорт/импорт через awx-cli - стандартный путь. Работает, но с оговорками.
awx export --all > awx-backup.json
# На новом инстансе:
awx import < awx-backup.json
Credential-и с типом Vault мигрировали без проблем - зашифрованные значения переехали как есть. А вот Machine credentials с приватными ключами потребовали перепроверки: после импорта они помечаются как "зашифрованы на стороне AWX", и убедиться что ключ корректный можно только запустив Job. Запустили несколько тестовых - всё поднялось.
Шаблоны, инвентари, расписания - переехали чисто. Единственная потеря - история выполнения Job-ов не мигрирует штатными средствами. Заказчик решил что история за полтора года в старом AWX им особо не нужна, оставили старую VM в read-only на пару недель для справки.
Мониторинг через Prometheus - без дополнительной работы
Это, пожалуй, лучшее в operator-подходе. AWX 22.x экспортирует метрики из коробки - endpoint /api/v2/metrics/ с Prometheus-форматом. Deckhouse автоматически подхватывает ServiceMonitor через свой мониторинговый модуль.
Метрики есть по выполнению Job-ов, по очередям, по утилизации Execution Environment. В Grafana это всё появилось без дополнительной конфигурации - только добавили дашборд из community (есть готовый под AWX). На Docker Compose мы тянули метрики через node-exporter и несколько custom-скриптов, которые парсили AWX API. Теперь это просто не нужно.
Event-Driven Ansible: тестируем реакцию на алерты Zabbix
Event-Driven Ansible (EDA) - отдельный компонент, который в AAP 2.3 вышел в developer preview. Смысл простой: rulebook слушает источник событий и запускает Action (в том числе AWX Job Template) при совпадении правила.
Мы тестируем интеграцию с Zabbix. Схема такая: Zabbix отправляет webhook при срабатывании алерта, EDA-controller его принимает, матчит по severity и host-группе, запускает нужный playbook.
---
- name: Zabbix alerts handler
hosts: all
sources:
- ansible.eda.webhook:
host: 0.0.0.0
port: 5000
rules:
- name: Disk usage critical
condition: event.payload.trigger_name is search("disk.*critical", ignorecase=true)
action:
run_job_template:
name: "Cleanup temp files"
organization: Default
job_args:
extra_vars:
target_host: "{{ event.payload.host }}"
На тестовом стенде это работает. EDA поднимается как отдельный Deployment в том же namespace, принимает webhook от Zabbix, запускает Job Template в AWX. Логи в Kubernetes, метрики там же.
Честно: production-нагрузку EDA у этого клиента ещё не принял - прогоняем через staging неделю, смотрим на ложные срабатывания и edge cases (что если Zabbix шлёт шторм алертов при падении сети - надо throttling). Rulebook-и пока простые, на три-четыре паттерна. Но механика рабочая и, что важно, всё это оркестрируется из одного места - кластера.
Итог
Переезд с Docker Compose на operator занял день работы, ещё день - проверка и стабилизация. Нервотрёпки меньше, чем ожидали. Мониторинг появился сам, обновление AWX теперь - изменение версии в CR и kubectl apply. Managed-сопровождение инфраструктуры с таким AWX ощутимо проще: не нужно помнить про отдельную VM, всё видно в одном месте.
EDA - интересная история, которую стоит мониторить. На текущем этапе это не "поставил и забыл", а "поставил и настроил правила руками". Но для задачи автоматического реагирования на алерты - это первый инструмент, который не требует писать собственный webhook-обработчик с нуля.