Ansible — автоматизация инфраструктуры

Продолжительность: 20 уроков · Уровень: с нуля

Ansible — это система управления конфигурациями: оно позволяет описать состояние серверов декларативно и применять его одной командой. Без агентов, только SSH и Python на целевой машине.

1. Что такое Ansible

Концепция похожа на Terraform, но Ansible работает на уровне ОС и приложений, а Terraform — на уровне облачной инфраструктуры.

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 ping

3. Модули и 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.yml

5. Переменные

Переменные описываются в разделе 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
    - git

Handlers

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: restarted

7. Теги

Теги позволяют выполнять только нужные части плейбука:

tasks:
  - name: Установить зависимости
    apt:
      name: git
    tags: deps

  - name: Скачать код
    git:
      repo: https://github.com/me/app.git
      dest: /opt/app
    tags: deploy
ansible-playbook site.yml --tags deploy
ansible-playbook site.yml --tags "deps,deploy"
ansible-playbook site.yml --skip-tags deps

8. Роли

Роли упаковывают плейбук в переиспользуемый пакет. Структура типовой роли:

roles/app/
├── tasks/
│   └── main.yml
├── handlers/
│   └── main.yml
├── templates/
├── files/
├── vars/
├── defaults/
│   └── main.yml
└── meta/
    └── main.yml

Использование в плейбуке:

- name: Развернуть приложение
  hosts: all
  roles:
    - common
    - app
Роли тестируются фреймворком Molecule — он поднимает окружение и прогоняет роль с проверками.

9. Шифрование ansible-vault

Секреты (пароли, ключи) хранят в зашифрованных файлах:

ansible-vault create secrets.yml
ansible-vault view secrets.yml
ansible-vault encrypt secrets.yml
ansible-vault decrypt secrets.yml
ansible-playbook site.yml --ask-vault-pass
Никогда не храни пароли открытым текстом в плейбуках и не коммить зашифрованные файлы вместе с паролем в комментариях.

10. Факты

При подключении 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: production

13. Роли и повторяемые плейбуки

Когда плейбуки разрастаются, на помощь приходят роли — структура из 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]
Правило: роли из общего хранилища (Ansible Galaxy) проверяй на тестовом стенде, прежде чем сыграть на прод. Новички часто ломают продуктив несовместимыми версиями ролей.

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
Не зашивай секреты в шаблоны и переменные. Для этого есть Ansible Vault — зашифруй файл целиком и передавай пароль через --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». Правильный порядок: собрать факты, описать конфиги, затем идемпотентно применить.

  1. зафиксируй текущее состояние: установленные пакеты, конфиги, cron-задачи;
  2. напиши роли для каждой роли сервера (nginx, база, приложение);
  3. перенеси изменённые вручную файлы в шаблоны;
  4. прогони --check, затем примени на непродуктивном клоне;
  5. на проде запускай по одному хосту и контролируй вывод.
Никогда не запускай непроверенный плейбук сразу на прод. Ансибилизацию начинай с самого «безопасного» хоста, а основной сервер оставляй напоследок.

17. Динамическая инвентаризация (AWS, GCP, Docker)

Для облаков и контейнеров писать inventory вручную бессмысленно: машины создаются и исчезают сами. Ansible умеет подтягивать список хостов из облачных провайдеров через динамические inventory-скрипты.

# ansible.cfg
[defaults]
inventory = aws_ec2.yaml
# aws_ec2.yaml (пример)
plugin: amazon.aws.aws_ec2
regions:
  - eu-central-1
keyed_groups:
  - key: tags.Environment
    prefix: env
filters:
  instance-state-name: running
Комбинируйте статический и динамический inventory: «база» — файл, «облако» — скрипт. Так вы поймёте, откуда пришли хосты, через группы в output.

18. 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-хост и приложение разделяйте. Так проще откатываться к версии, которая работала.

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"
Audit-логи — обязательное требование во многих компаниях: кто запустил плейбук на проде и что он изменил, должно быть зафиксировано и доступно для проверок.

20. Частые ошибки и отладка плейбуков

Даже опытные инженеры наступают на одни и те же грабли: неправильные пути, неверные имена модулей, зависимости от хоста, ошибки ShJinja-синтаксиса. Научитесь отлаживать системно.

ОшибкаПричинаФикс
переменная не находитсяобласть видимостипроверить group_vars; используйте debug
модуль не найденне установлена collectionansible-galaxy install
кодировка/файлline-endingset_fact + normalize
playbook «работает по-разному»неипотентностьсделать задачи проверяемыми
  1. запускайте с --step, чтобы видеть каждый таск;
  2. используйте модуль debug для переменных до применения;
  3. пишите assert-проверки на ключевые инварианты в конце ролей;
  4. в логе смотрите полный стек ошибки, а не первую строку.
Проверяйте плейбук зелёным прогоном (dry-run) и в «тестовом» окружении до прода. Уверенность из репутации одной среды — самый частый источник прод-инцидентов.

21. Rolling-деплой и стратегии применения

Обновление «все серверы сразу» даёт окно недоступности и общую точку отказа. Стратегии Ansible позволяют применять изменения по партиям, проверяя состояние после каждой группы.

- hosts: web
  serial: 2
  tasks:
    - name: перезапустить сервис
      service: name=webapp state=restarted
    - name: проверить здоровье
      uri: url=http://localhost/health
Совмещайте serial с проверкой health после каждой партии: «частично обновлено» не должно оставаться без контроля.
serial без проверок — ложная безопасность: вы всё так же не знаете, что прод-часть сломалась на второй партии.

22. Безопасность: секреты, become и окружения

Пароли, ключи и токены не должны лежать в Git. Ansible даёт vault для шифрования секретов, а контроль прав — через become и разделение окружений.

Никогда не добавляйте пароль vault в сам плейбук: подставляйте через переменную окружения при запуске.
Секрет, попавший в историю Git, считается скомпрометированным: смените ключи, а не просто исправьте файл.

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()
Для повторяющихся «бизнес-проверок» модуль окупается: одно изменение — и все плейбуки получают новое поведение.
Большинство задач решается комбинацией модулей: сначала поищите готовое, модуль пишите только под специфику.

24. Ansible в CI/CD и самопроверка плейбуков

Ручной запуск плейбуков уступает автоматической проверке в пайплайне: линтеры, dry-run и тестовый прогон ловят ошибки до прода.

# пример job в GitLab
ansible-lint .
ansible-playbook -i inventory/staging site.yml --check
Добавьте «проверку идемпотентности» в pipeline: второй прогон должен давать changed=0 на большинстве задач.
CI без стейджа опасен: первое знакомство с плейбуком не должно происходить на проде. Всегда есть как минимум тестовая инвентаризация.

Что дальше

Протестируй роли с помощью Molecule, инфраструктуру опиши через Terraform, а конфигурации серверов храни в Git. Все курсы — на главной странице.

← Вернуться к курсам