Ansible — автоматизация инфраструктуры
Ansible — это система управления конфигурациями: оно позволяет описать состояние серверов декларативно и применять его одной командой. Без агентов, только SSH и Python на целевой машине.
1. Что такое Ansible
- Декларативный подход — описываешь «как должно быть», а не «что делать»;
- Без агентов — ничего не устанавливается на управляемые серверы;
- Идемпотентность — повторный запуск не ломает состояние;
- единый язык для настройки серверов, деплоя, конфигурации сети и orchestration.
2. Установка и инвентарь
sudo apt update
sudo apt install ansible
ansible --versionИнвентарь — список управляемых хостов. По умолчанию файл /etc/ansible/hosts или локальный inventory.ini:
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com ansible_user=ubuntuПроверка доступности:
ansible all -i inventory.ini -m ping3. Модули и ad-hoc команды
Работа строится на модулях — готовых «кирпичиках» действий.
# выполнить команду
ansible all -i inventory.ini -m command -a "uptime"
# установить пакет
ansible web1 -m apt -a "name=nginx state=present" -b
# скопировать файл
ansible all -m copy -a "src=hosts dest=/tmp/hosts"Частые модули
| Модуль | Что делает |
|---|---|
| apt / yum / dnf | управление пакетами |
| copy / template | копирование файлов и шаблонов Jinja2 |
| service | запуск и остановка служб |
| user / group | пользователи и группы |
| git | клонирование репозиториев |
| docker_container | управление контейнерами |
-b (become) означает выполнение с правами root через sudo.4. Playbook — первый
Playbook описывает сценарий для группы хостов. YAML-файл:
---
- name: Установка и запуск nginx
hosts: webservers
become: yes
tasks:
- name: Установить nginx
apt:
name: nginx
state: present
- name: Запустить nginx
service:
name: nginx
state: started
enabled: yesЗапуск:
ansible-playbook -i inventory.ini nginx.yml5. Переменные
Переменные описываются в разделе vars, в файлах vars/, через флаг -e или в inventory.
---
- name: Шаблон конфига
hosts: webservers
vars:
app_port: 8080
log_level: info
tasks:
- name: Сгенерировать конфиг
template:
src: app.conf.j2
dest: /etc/app/conf.d/app.conf# приоритет: -e > playbook vars > inventory
ansible-playbook app.yml -e "log_level=debug"6. Условия, циклы и handlers
Условия
- name: Рестарт только на продакшене
service:
name: app
state: restarted
when: environment == "prod"Циклы
- name: Установить несколько пакетов
apt:
name: "{{ item }}"
state: present
loop:
- curl
- htop
- gitHandlers
Handler запускается только если задача изменила состояние:
tasks:
- name: Обновить конфиг
template:
src: app.conf.j2
dest: /etc/app/conf.d/app.conf
notify: restart app
handlers:
- name: restart app
service:
name: app
state: restarted7. Теги
Теги позволяют выполнять только нужные части плейбука:
tasks:
- name: Установить зависимости
apt:
name: git
tags: deps
- name: Скачать код
git:
repo: https://github.com/me/app.git
dest: /opt/app
tags: deployansible-playbook site.yml --tags deploy
ansible-playbook site.yml --tags "deps,deploy"
ansible-playbook site.yml --skip-tags deps8. Роли
Роли упаковывают плейбук в переиспользуемый пакет. Структура типовой роли:
roles/app/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── templates/
├── files/
├── vars/
├── defaults/
│ └── main.yml
└── meta/
└── main.ymlИспользование в плейбуке:
- name: Развернуть приложение
hosts: all
roles:
- common
- app9. Шифрование ansible-vault
Секреты (пароли, ключи) хранят в зашифрованных файлах:
ansible-vault create secrets.yml
ansible-vault view secrets.yml
ansible-vault encrypt secrets.yml
ansible-vault decrypt secrets.ymlansible-playbook site.yml --ask-vault-pass10. Факты
При подключении Ansible собирает факты о хосте: ОС, IP-адреса, память и т.д.
---
- name: Факты
hosts: all
gather_facts: yes
tasks:
- name: Показать ОС
debug:
msg: "{{ ansible_distribution }} {{ ansible_distribution_version }}"Сбор фактов можно отключить ради скорости: gather_facts: no.
11. Проверки и dry-run
ansible-playbook site.yml --check # репетиция без изменений
ansible-playbook site.yml --syntax-check
ansible-lint site.yml # линтер12. Ansible в CI/CD
Ansible легко вызывается из GitLab CI — нужен только ключ доступа к серверам:
deploy:
stage: deploy
image: alpine
before_script:
- apk add ansible openssh
script:
- ansible-playbook -i inventory deploy.yml
environment: production13. Роли и повторяемые плейбуки
Когда плейбуки разрастаются, на помощь приходят роли — структура из tasks, handlers, templates, vars и defaults. Роль — это готовый «кубик LEGO», который легко переиспользовать между проектами и делиться с командой.
roles/
└── nginx/
├── tasks/main.yml # что делать
├── handlers/main.yml # перезапуск при изменении
├── templates/ # конфиги с переменными
├── vars/main.yml # переменные роли
└── defaults/main.yml # значения по умолчанию---
- name: Установить и настроить nginx
hosts: web
roles:
- nginx
- role: firewall
vars:
open_ports: [80, 443]14. Templates и переменные окружений
Конфигурации редко совпадают дословно между dev, stage и prod. Шаблоны Jinja2 вместе с переменными из group_vars и host_vars решают эту задачу элегантно.
# templates/nginx.conf.j2
server {
listen 80;
server_name {{ domain }};
root {{ web_root }}; # разное на каждом окружении
}# group_vars/prod.yml
domain: example.com
web_root: /srv/www
log_level: error
# group_vars/dev.yml
domain: dev.example.com
web_root: /srv/www-dev- файлы
group_vars/<группа>.ymlприменяются к хостам из inventory; - приоритет:
host_vars>group_vars>vars>defaults; - шаблон подключается таском
template, а неcopy.
--ask-vault-pass.15. Условия, циклы и теги
Ansible — декларативный инструмент, но без логики не обойтись: ветвления when, циклы loop и with_items, а также теги для выборочного запуска.
---
- name: Установить пакеты
hosts: all
tasks:
- name: Пакет для Debian
apt:
name: htop
state: present
when: ansible_os_family == 'Debian'
tags: [packages]
- name: Пакет для RedHat
dnf:
name: htop
state: present
when: ansible_os_family == 'RedHat'
tags: [packages]| Конструкция | Назначение |
|---|---|
when | выполнить таск только при условии |
loop | пройти список элементов |
tags | запустить только отмеченные таски |
ignore_errors | продолжить, даже если таск упал |
ansible-playbook site.yml --tags deploy выполняет только нужную часть, остальное не трогая.16. Ансибилизация существующего сервера
Частый сценарий — сервер уже настроен руками, а приходит задача «перевести его под Ansible». Правильный порядок: собрать факты, описать конфиги, затем идемпотентно применить.
- зафиксируй текущее состояние: установленные пакеты, конфиги, cron-задачи;
- напиши роли для каждой роли сервера (nginx, база, приложение);
- перенеси изменённые вручную файлы в шаблоны;
- прогони
--check, затем примени на непродуктивном клоне; - на проде запускай по одному хосту и контролируй вывод.
17. Динамическая инвентаризация (AWS, GCP, Docker)
Для облаков и контейнеров писать inventory вручную бессмысленно: машины создаются и исчезают сами. Ansible умеет подтягивать список хостов из облачных провайдеров через динамические inventory-скрипты.
# ansible.cfg
[defaults]
inventory = aws_ec2.yaml- AWS:
aws_ec2— по тегам, регионам, состоянию; - GCP:
gcp_compute— по проектам и зонам; - Docker:
community.docker.docker_containers; - переменные hostvars можно собирать из тегов инстансов;
- для локальных тестов —
localhostили Docker-контейнеры.
# aws_ec2.yaml (пример)
plugin: amazon.aws.aws_ec2
regions:
- eu-central-1
keyed_groups:
- key: tags.Environment
prefix: env
filters:
instance-state-name: running18. Ansible и Docker: готовые сценарии
Ansible часто используют для развёртывания контейнеров: он стартует образы, создаёт сети и поднимает compose-стек на группе хостов с idempotent-гарантией.
- name: Запустить стек
hosts: docker_hosts
tasks:
- name: Установка docker-compose
package:
name: docker-compose-plugin
state: present
- name: Поднять контейнеры
docker_compose_v2:
project_src: /opt/app
state: present- модули
docker_container,docker_image,docker_network; - сборка образов на каждой ноде — отдельный шаг с кэшем;
- переменную версии образа (!) версионируем — повторный запуск не сломает стек;
- логика «проверь и запусти» — идемпотентность по умолчанию.
19. Callback-плагины и логирование запусков
По умолчанию Ansible сильно «разговорчив» в терминале, но это непрактично для аудита. Callback-плагины и логирование сохраняют результаты каждого запуска: кто, что, когда и с каким результатом.
# ansible.cfg
[defaults]
stdout_callback = yaml # компактный вывод
bin_ansible_callbacks = True
callback_whitelist = timer, profile_tasks
[callback_timer]
format = "Час: %Hh %Mm %Ss"- сохранение логов запусков в
/var/log/ansible; - уведомления в Slack/Telegram через callback-плагины;
- профилирование задач:
profile_tasksпокажет узкие места; - интеграция с Ansible Tower / AWX: история и роли доступа.
20. Частые ошибки и отладка плейбуков
Даже опытные инженеры наступают на одни и те же грабли: неправильные пути, неверные имена модулей, зависимости от хоста, ошибки ShJinja-синтаксиса. Научитесь отлаживать системно.
| Ошибка | Причина | Фикс |
|---|---|---|
| переменная не находится | область видимости | проверить group_vars; используйте debug |
| модуль не найден | не установлена collection | ansible-galaxy install |
| кодировка/файл | line-ending | set_fact + normalize |
| playbook «работает по-разному» | неипотентность | сделать задачи проверяемыми |
- запускайте с
--step, чтобы видеть каждый таск; - используйте модуль
debugдля переменных до применения; - пишите assert-проверки на ключевые инварианты в конце ролей;
- в логе смотрите полный стек ошибки, а не первую строку.
21. Rolling-деплой и стратегии применения
Обновление «все серверы сразу» даёт окно недоступности и общую точку отказа. Стратегии Ansible позволяют применять изменения по партиям, проверяя состояние после каждой группы.
- hosts: web
serial: 2
tasks:
- name: перезапустить сервис
service: name=webapp state=restarted
- name: проверить здоровье
uri: url=http://localhost/health- serial задаёт размер партии: число узлов или процент;
- pause между партиями — время на ручную проверку;
- вывод узла из балансировщика перед обновлением даёт zero-downtime;
- при провале задачи — stop, диагностика и controlled откат.
22. Безопасность: секреты, become и окружения
Пароли, ключи и токены не должны лежать в Git. Ansible даёт vault для шифрования секретов, а контроль прав — через become и разделение окружений.
- ansible-vault encrypt шифрует плейбуки и переменные в репозитории;
- ключ vault храните отдельно — в менеджере секретов или CI-переменных;
- become-права минимизируйте: повышайте привилегии точечно, а не на всё;
- прод и стейдж разделяйте инвентаризациями и разными наборами vault.
23. Написание собственных модулей
Стандартных модулей почти всегда достаточно, но специфичная логика — повод написать свой. Ansible подключит пользовательские модули из папки library в проекте.
# library/my_module.py
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(argument_spec={
'path': {'required': True, 'type': 'str'}})
result = {'changed': False, 'path': module.params['path']}
module.exit_json(**result)
if __name__ == '__main__':
main()- имя файла = имя модуля, аргументы описываются в argument_spec;
- возвращайте результат через exit_json с ключами;
- следите за идемпотентностью: модуль должен работать «изменено/не изменено»;
- тестируйте модуль локально с параметрами до запуска плейбука.
24. Ansible в CI/CD и самопроверка плейбуков
Ручной запуск плейбуков уступает автоматической проверке в пайплайне: линтеры, dry-run и тестовый прогон ловят ошибки до прода.
- ansible-lint проверяет стиль и частые ошибки на этапе кода;
- ansible-playbook --syntax-check валидирует структуру плейбука;
- molecule запускает роли в контейнерах с идемпотентной проверкой;
- в CI прогоняйте playbook на стейдже перед прод-дистрибуцией.
# пример job в GitLab
ansible-lint .
ansible-playbook -i inventory/staging site.yml --checkЧто дальше
Протестируй роли с помощью Molecule, инфраструктуру опиши через Terraform, а конфигурации серверов храни в Git. Все курсы — на главной странице.