5. Работа с инфраструктурой: dynamic inventory, облака, rolling updates
Как автоматизировать реальные инфраструктуры: использовать dynamic inventory, работать с облаками (AWS/GCP/Azure), применять delegation (delegate_to), выполнять rolling updates через serial, строить zero‑downtime деплой по стратегии. В разделе — небольшие примеры кода с комментариями и production best practices.
Dynamic Inventory
Dynamic inventory строит список хостов и групп из внешнего источника (API облака, CMDB). Это решает проблему, когда сервера создаются/удаляются автоматически и статический hosts.ini устаревает.
Подходы
- Inventory plugins (предпочтительно): встроенные/коллекционные плагины (AWS EC2, Azure, GCP).
- Скрипт inventory: свой генератор JSON (устаревающий подход, но встречается).
Production best practices:
- группировать хосты по тегам (env, role, app, owner)
- фиксировать конфигурацию inventory‑плагина в репозитории
- ограничивать права cloud‑аккаунта (минимальные permissions только на read)
AWS: EC2 inventory plugin (пример)
Требуется коллекция amazon.aws и доступ к AWS API (через IAM role/keys).
Файл inventories/prod/aws_ec2.yml:
plugin: amazon.aws.aws_ec2
regions:
- eu-central-1
filters:
tag:Environment: prod
keyed_groups:
# Группы формируются по тегам, удобно для hosts: web, db и т.п.
- key: tags.Role
prefix: role
compose:
# Установить ansible_host в public_ip_address или private_ip_address
ansible_host: private_ip_address
Запуск:
ansible-inventory -i inventories/prod/aws_ec2.yml --graph
ansible-playbook -i inventories/prod/aws_ec2.yml site.yml
Комментарий: в production чаще используют private IP и ходят через bastion/VPN; доступ к AWS лучше через IAM role (например, на runner/бастионе), а не через статические ключи.
GCP / Azure (концептуально)
Идея одинаковая:
- inventory‑плагин получает список VM по API
- группирует по labels/tags
- задаёт
ansible_host(обычно private IP)
Best practices:
- одинаковая модель тегов/labels между облаками (env/role/app)
- единый интерфейс выбора окружения:
inventories/dev,inventories/prod
Delegation (delegate_to)
delegate_to выполняет задачу не на целевом хосте, а на другом. Частые кейсы:
- выполнить действие на контрол‑ноде (localhost): запрос в API, запись артефакта, генерация конфига
- выполнить задачу на балансировщике (снять/вернуть ноду из пула) перед деплоем
- name: Drain node from load balancer (example API call)
ansible.builtin.uri:
url: "https://lb-api.example.com/pool/remove?host={{ inventory_hostname }}"
method: POST
status_code: 200
delegate_to: localhost
- name: Deploy app on host
ansible.builtin.template:
src: app.conf.j2
dest: /etc/myapp/app.conf
notify: Restart myapp
Production best practices:
- явно документировать, где выполняется задача (delegate_to), чтобы избежать сюрпризов
- для задач с внешними API — таймауты, retries и обработка ошибок
Serial / rolling updates
serial ограничивает число хостов, обрабатываемых одновременно, и позволяет делать rolling update.
- name: Rolling deploy myapp
hosts: role_web
become: true
serial: "20%" # или 2, 5 — фиксированным числом
tasks:
- name: Deploy config
ansible.builtin.template:
src: app.conf.j2
dest: /etc/myapp/app.conf
notify: Restart myapp
- name: Ensure service is healthy
ansible.builtin.uri:
url: "http://127.0.0.1:8080/health"
method: GET
status_code: 200
register: health
retries: 10
delay: 3
until: health.status == 200
handlers:
- name: Restart myapp
ansible.builtin.service:
name: myapp
state: restarted
Комментарий: serial сам по себе не гарантирует zero‑downtime, но снижает риск «выключить всё сразу». Zero‑downtime достигается дополнительно через балансировщик, healthchecks и корректную стратегию.
Практика: zero‑downtime деплой (идея)
Шаги:
- Перед деплоем убрать хост из балансировщика (через
delegate_to: localhostи API LB). - Обновить конфиг/бинарь/контейнер на хосте.
- Перезапустить сервис (через handler).
- Дождаться healthcheck (uri + retries/until).
- Вернуть хост в балансировщик.
- Повторить по
serial.
Это можно оформить в роль (например, app_deploy) и переиспользовать для разных сервисов.
Production best practices (сводка)
- Dynamic inventory для облаков, группы по тегам/labels
- serial + healthchecks как основа rolling update
- delegate_to для интеграций (LB/API), с retries/timeouts
- private networking: управлять по private IP через bastion/VPN
- минимальные права cloud‑аккаунта для inventory (read‑only)