Виклик операційної автоматизації
Infrastructure as Code з Terraform вирішує проблему provisioning інфраструктури—створення VPC, баз даних, контейнерних кластерів—але production системи вимагають поточних операційних завдань, які виходять за межі декларативної моделі Terraform. Seeding бази даних, конфігурація додатків, операції на рівні контейнерів та динамічне управління середовищами вимагають імперативної автоматизації, яка реагує на runtime умови замість декларування бажаного стану.
Операційні завдання, які Terraform не може ефективно виконувати:
- Операції з базою даних: Виконання міграцій, seeding даних, управління схемами для кожного середовища
- Управління контейнерами: Виявлення запущених контейнерів, виконання команд, streaming логів
- Отримання секретів: Завантаження credentials з Parameter Store під час виконання
- Динамічне виявлення: Пошук ресурсів інфраструктури без hardcoded конфігурації
- Робочі процеси для конкретних середовищ: Різні операції для розробки vs production
Виклик інтеграції: Як операційні інструменти виявляють та взаємодіють з динамічно provisioned інфраструктурою без підтримки статичної конфігурації, яка дрейфує від реальності?
Ключові результати:
- Автоматизований database seeding для всіх середовищ (30 хвилин → 5 хвилин)
- Нульова статична конфігурація через динамічне виявлення ECS хостів
- Секрети ніколи не зберігаються в коді (100% отримання з SSM Parameter Store)
- Environment-agnostic playbooks (єдиний код для всіх середовищ)
- 95% операційна повторюваність через кодифіковані робочі процеси
Архітектура: інтеграція Terraform + Ansible
Terraform та Ansible виконують комплементарні ролі в управлінні інфраструктурою: Terraform provisioning immutable інфраструктури декларативно, Ansible виконує mutable операції імперативно. Патерн інтеграції використовує resource tagging та AWS APIs як контракт між інструментами.
Terraform provisioning інфраструктури:
- VPC, підмережі, security groups, таблиці маршрутизації
- RDS PostgreSQL з Multi-AZ конфігурацією
- ECS кластери, task definitions, сервіси
- ECR container registry з lifecycle policies
- S3 buckets, CloudFront distributions
- IAM ролі, security groups, load balancers
- Заповнення SSM Parameter Store секретами
- Консистентний resource tagging (app_name, environment)
Ansible виконує операції:
- Налаштування схеми бази даних та seeding
- Виявлення ECS контейнерів та виконання команд
- Отримання параметрів SSM для runtime конфігурації
- Міграції та deployments на рівні додатка
- Мультисередовищні операційні робочі процеси
- Завдання обслуговування та troubleshooting
- Запити до ECS API для запущених tasks фільтрованих за тегами
- Розв'язання ланцюжка task → container instance → EC2 instance
- Побудова динамічного inventory без статичних файлів
Integration Pattern
Контракт:
- Terraform provisioning інфраструктури з консистентними тегами
- Terraform зберігає секрети в SSM Parameter Store за шаблоном іменування
- Ansible виявляє ресурси через AWS APIs використовуючи фільтри за тегами
- Ansible отримує секрети з SSM використовуючи сконструйовані шляхи параметрів
- Ansible виконує операції на виявлених ресурсах
- Немає hardcoded деталей інфраструктури в коді Ansible
Data Flow:
Переваги:
- Зміни інфраструктури автоматично відображаються в Ansible
- Немає статичних inventory файлів для підтримки
- Секрети ніколи в коді або version control
- Єдиний playbook працює для всіх середовищ
- Конфігураційний дрейф неможливий (завжди запитує поточний стан)
Реалізація: Terraform Output → Ansible Input
Реалізація встановлює інтеграцію через Terraform resource tagging та Ansible playbooks динамічного виявлення.
Terraform конфігурація для Ansible
Налаштування SSM Parameter Store:
Terraform створює параметри за передбачуваною конвенцією іменування, яку Ansible може сконструювати:
# terraform/ssm.tf
resource "aws_ssm_parameter" "postgres_host" {
name = "/${var.app_name}/${var.env}/POSTGRES_HOST"
type = "String"
value = data.terraform_remote_state.shared.outputs.rds_address
}
resource "aws_ssm_parameter" "postgres_password" {
name = "/${var.app_name}/${var.env}/POSTGRES_PASSWORD"
type = "SecureString"
value = "${var.db_password}_${var.env}"
}
Шаблон іменування параметрів:
/${app_name}/${environment}/${parameter_name}
Приклади:
/terraform-letscommerce/dev/POSTGRES_HOST/terraform-letscommerce/prod/POSTGRES_PASSWORD
Конфігурація ECS Service:
# terraform/ecs.tf
resource "aws_ecs_service" "app" {
name = "${var.app_name}-${var.env}-ecs-service"
cluster = "${var.app_name}-ecs-cluster"
task_definition = aws_ecs_task_definition.app.arn
desired_count = var.task_count
tags = {
Application = var.app_name
Environment = var.env
}
}
Структура проекту Ansible
ansible/
├── site.yml # Головний orchestration playbook
├── get-ecs-hosts.yml # Динамічне виявлення ECS хостів
├── get-ssm-db-params.yml # Отримання параметрів SSM
├── get-docker-container.yml # Виявлення контейнерів на хостах
├── exec-in-container.yml # Загальне виконання команд
├── seed-db-sql.yml # SQL ініціалізація бази даних
├── seed-db-sequelize.yml # ORM-based міграції/seeding
└── connect-test.yml # Перевірка connectivity
Головний Orchestration (site.yml):
---
# 1. Виявлення інфраструктури
- import_playbook: get-ecs-hosts.yml
# 2. Тестування connectivity
- import_playbook: connect-test.yml
# 3. Отримання конфігурації
- import_playbook: get-ssm-db-params.yml
# 4. Операції з контейнерами
- import_playbook: get-docker-container.yml
- import_playbook: exec-in-container.yml
# 5. Операції з базою даних
- import_playbook: seed-db-sql.yml
- import_playbook: seed-db-sequelize.yml
Патерн динамічного Inventory
Патерн виявлення ECS хостів:
1. Запит до ECS API для запущених tasks
→ Фільтрація за: cluster name + service name + environment tag
→ Повертає: List of task ARNs
2. Отримання ARN container instances з tasks
→ Вхід: Task ARNs
→ Повертає: Container instance ARNs
3. Розв'язання EC2 instance IDs
→ Вхід: Container instance ARNs
→ Повертає: EC2 instance IDs
4. Отримання EC2 instance IPs
→ Вхід: EC2 instance IDs
→ Повертає: Public/Private IP addresses
5. Додавання до динамічного inventory
→ Побудова in-memory inventory
→ Статичні файли не потрібні
Ключовий момент: Ланцюжок виявлення розв'язує: Service → Tasks → Container Instances → EC2 Instances → IPs
Патерн отримання параметрів SSM:
1. Конструювання шляху параметра зі змінних
→ Шаблон: /{app_name}/{environment}/{parameter}
→ Приклад: /terraform-letscommerce/dev/POSTGRES_HOST
2. Запит до SSM Parameter Store
→ Запит дешифрування для SecureString параметрів
→ Повертає: Значення параметрів
3. Побудова об'єкта конфігурації
→ Збирання всіх параметрів в структуровану конфігурацію
→ Доступна для всіх наступних playbooks
Переваги:
- Той самий код отримує dev/staging/prod параметри (змінна середовища вибирає)
- Секрети дешифруються під час виконання, ніколи не зберігаються в коді
- Terraform оновлює параметри → Ansible бачить зміни негайно
Операційні робочі процеси
Production операції кодифіковані як повторювані Ansible playbooks, які виявляють інфраструктуру динамічно та виконують завдання специфічні для середовища.
Робочий процес 1: Database Seeding
Процес:
1. Підключення до виявлених ECS хостів
→ Використовує динамічний inventory з фази виявлення
2. Пошук цільового Docker контейнера
→ Збіг за шаблоном імені контейнера
→ Збереження container ID для операцій
3. Виявлення директорії додатка
→ Пошук загальних шляхів (/app, /usr/src/app, /opt/app)
→ Ідентифікація за наявністю package.json
4. Виконання міграцій бази даних
→ Виконання: docker exec {container} sequelize db:migrate
→ Виконується у всіх середовищах
5. Seeding бази даних (умовно)
→ Виконання: docker exec {container} sequelize db:seed:all
→ Тільки в development середовищі
Логіка для конкретних середовищ:
- Development: Міграції + повний data seeding
- Staging: Міграції + мінімальні тестові дані
- Production: Тільки міграції (без seeding)
Робочий процес 2: операції з контейнерами
Патерн:
1. Виявлення контейнера
→ Запит до Docker daemon на ECS хостах
→ Фільтрація за шаблоном імені контейнера (ecs-*-server)
→ Збереження container ID для операцій
2. Виконання команди
→ Виконання: docker exec {container_id} {command}
→ Захоплення та повернення output
→ Логування результатів для аудиту
3. Загальні операції
→ Очищення application cache
→ Rebuild search indexes
→ Генерація звітів
→ Health checks
→ Debug production issues
Робочий процес 3: повне налаштування середовища
Процес виконання:
1. Infrastructure Discovery
→ Пошук ECS хостів з запущеними tasks для середовища
→ Побудова динамічного inventory
2. Перевірка Connectivity
→ Перевірка SSH доступу до виявлених хостів
→ Тестування мережевої connectivity
3. Отримання Secrets
→ Завантаження database credentials з SSM
→ Дешифрування secure параметрів
4. Ідентифікація контейнерів
→ Виявлення application контейнерів на хостах
→ Збереження container IDs
5. Операції з базою даних
→ Виконання міграцій (всі середовища)
→ Seed даних (тільки development)
6. Валідація
→ Підтвердження успішності всіх операцій
→ Генерація audit log
Порівняння часу:
- Manual: 30-45 хвилин (схильний до помилок, не повторюваний)
- Automated: 5 хвилин (консистентний, повторюваний, з аудитом)
Патерни динамічного виявлення
Динамічне виявлення усуває статичну конфігурацію шляхом запитів до AWS APIs для визначення поточного стану інфраструктури під час виконання.
Розв'язання ECS до EC2
Ланцюжок виявлення:
aws ecs list-tasks aws ecs describe-tasks ECS Service Name Task ARNs Container Instance ARNs
aws ec2 describe-instances ansible add_host EC2 Instance IDs EC2 IP Addresses Ansible Inventory
Flow: ECS Service → Tasks → Container Instances → (aws ecs describe-container-instances) → EC2 IDs → IPs → Ansible Inventory
Чому це важливо:
- ECS tasks можуть переміщатися між instances
- Instances можуть бути замінені auto-scaling
- IP адреси змінюються при recreation instance
- Статичний inventory стає застарілим негайно
Динамічне виявлення гарантує:
- Завжди підключається до поточно запущених instances
- Адаптується до scaling подій автоматично
- Виживає заміни instances
- Не потрібні ручні оновлення inventory
Виявлення контейнерів
Виклик: Кілька контейнерів запущені на кожному ECS instance. Який контейнер містить додаток?
Патерн виявлення:
- name: Find application container
become: true
shell: >
docker ps
--filter "label=com.amazonaws.ecs.task-definition-family={{ app_name }}-{{ env }}"
--format "{{ '{{' }}.ID{{ '}}' }}"
register: container_id
Критерії виявлення:
- ECS task definition family labels
- Шаблони імен контейнерів
- Фільтр running state
- Вибір першого збігу
Результат: Встановлена змінна target_container для всіх наступних операцій
Виявлення параметрів SSM
Конструювання шляху параметра:
# Змінні
app_name: terraform-letscommerce
env: dev
parameter: POSTGRES_HOST
# Сконструйований шлях
parameter_path: '/{{ app_name }}/{{ env }}/{{ parameter }}'
# Результат: /terraform-letscommerce/dev/POSTGRES_HOST
Переваги:
- Немає hardcoded імен параметрів
- Environment-specific значення автоматичні
- Terraform та Ansible використовують однакову конвенцію іменування
- Додавання нових параметрів не вимагає змін Ansible
Безпека:
- SecureString параметри зашифровані у спокої
- Дешифрування з прапором
--with-decryption - IAM policies контролюють доступ per environment
- Секрети ніколи не з'являються в коді чи логах
Результати та уроки
Ключові метрики
Операційна ефективність:
- Час database seeding: 30 хвилин → 5 хвилин (83% скорочення)
- Налаштування середовища: 2 години → 10 хвилин (повна операційна готовність)
- Конфігураційний дрейф: 0% (динамічне виявлення запобігає застарілій конфігурації)
- Операційна повторюваність: 95% (кодифіковані робочі процеси, консистентне виконання)
- Ручне втручання: Зменшено з 10+ кроків до однієї команди
Операційний вплив:
- Provisioning нового середовища: Інфраструктура (Terraform) + операції (Ansible) повністю автоматизовані
- Disaster recovery: Повне відтворення середовища з коду
- Onboarding команди: Операції документовані як виконуваний код
- Debugging: Стандартизовані робочі процеси для інспекції контейнерів та troubleshooting
Що спрацювало
✅ Патерн динамічного inventory: Нульова статична конфігурація, автоматична адаптація до змін інфраструктури
✅ Tag-based виявлення: Terraform теги стають Ansible query фільтрами—простий, надійний контракт
✅ Інтеграція параметрів SSM: Секрети ніколи в коді, автоматичне environment-specific отримання
✅ Idempotent операції: Database seeding безпечний для повторного виконання, міграції відстежують стан
✅ Патерн єдиного playbook: Одна кодова база для всіх середовищ, параметр середовища вибирає поведінку
✅ Розділення Terraform + Ansible: Чіткі обов'язки запобігають перекриттю інструментів та плутанині
Підводних каменів уникати
❌ Hardcoding деталей інфраструктури: IP, hostnames, container IDs в playbooks гарантують застарілу конфігурацію
❌ Статичні inventory файли: Стають застарілими негайно коли ECS масштабується або instances заміняються
❌ Неконсистентний tagging: Terraform ресурси без стандартних тегів ламають discovery запити
❌ Відсутні IAM permissions: Ansible потребує ECS:Describe*, EC2:Describe*, SSM:GetParameter permissions
❌ Non-idempotent операції: Database операції, які падають при повторному виконанні, запобігають автоматизації
❌ Ігнорування обробки помилок: Production операції потребують комплексного виявлення збоїв та звітування
Висновок
Операційна автоматизація з Ansible доповнює Terraform provisioning інфраструктури, обробляючи імперативні завдання, які вимагають runtime state awareness. Патерн інтеграції—Terraform provisioning з тегами, Ansible виявляє динамічно—усуває статичну конфігурацію та запобігає дрейфу.
Шлях реалізації:
- Встановити Terraform стратегію tagging (app_name, environment на всіх ресурсах)
- Створити SSM параметри з передбачуваною конвенцією іменування
- Реалізувати playbook виявлення ECS хостів
- Побудувати отримання параметрів SSM для секретів
- Розробити playbooks операційних робочих процесів (база даних, контейнери)
- Тестувати в development, валідувати в staging, deploy в production
Коли це має сенс:
- Управління операційними завданнями поза provisioning інфраструктури
- Мультисередовищні AWS deployments, що вимагають консистентних операцій
- Команди, які кодифікують операційні знання для повторюваності
- Потреба в автоматизованому database seeding, міграціях, операціях з контейнерами
- Організації, що усувають ручні операційні процедури
Ресурси: