Всем привет, меня зовут Сергей Прощаев, я Tech Lead и руководитель направления Java | Kotlin разработки в FinTech, а также преподаю на курсах разработки и архитектуры в OTUS. В этой статье расскажу про Ansible — инструмент, который в мире DevOps уже практически стал стандартом для автоматизации конфигураций и деплоя.

Мы пройдем путь начиная с вопроса «а зачем это вообще?» до реальных кейсов и лучших практик, которые мы собрали в боевых проектах.

Сначала — коротко о контексте. Я давно работаю в финтехе, где на кону не просто аптайм, а реальные деньги клиентов и репутация. Еще несколько лет назад все управляли серверами «по старинке»: ssh, bash‑скрипты, копипаст команд.

Всё работало, пока масштаб не перевалил за пару десятков нод. Когда вам нужно обновить конфиг Nginx на 50 серверах или развернуть новую версию микросервиса на кластере из 100+ инстансов, ручной подход превращается в рулетку. Одна опечатка — и здравствуй, даунтайм в пятницу вечером. В этот момент команды всерьёз задумываются об Ansible.

Почему именно Ansible, а не другой зоопарк автоматизации?

Рынок инструментов управления конфигурациями насыщен: Puppet, Chef, SaltStack. Но Ansible выделяется одной архитектурной деталью, которая для меня стала решающей: агенты не нужны. Ansible работает по SSH (или WinRM для Windows), подключается к целевым хостам и выполняет модули, передавая через тот же канал результаты. Вам не нужно устанавливать и обслуживать дополнительное ПО на управляемых машинах, не нужно следить за совместимостью версий агентов. Это резко снижает порог входа и сокращает время от «хочу попробовать» до первого работающего плейбука до получаса.

Многие команды, с которыми я общался на конференциях и митапах, начинали с банальной лени: «Настроим пару серверов вручную, а потом как‑нибудь автоматизируем». Но когда цейтнот и количество серверов растут, «как‑нибудь» превращается в хаос. Ansible позволяет декларативно описать последовательность шагов, которые приводят систему к требуемому состоянию. При использовании идемпотентных модулей повторные запуски позволяют приводить систему к требуемому состоянию без необходимости помнить, какие изменения вносились ранее.

Первый плейбук: делаем с умом, а не лишь бы работало

Давайте сразу к коду. Вот типичный пример установки и настройки Nginx, с которого многие начинают:

- name: Configure web servers
  hosts: web
  become: yes
  vars:
    nginx_port: 8080
  tasks:
    - name: Ensure nginx is installed
      apt:
        name: nginx
        state: present
        update_cache: yes
        cache_valid_time: 3600 
      when: ansible_os_family == "Debian"

    - name: Deploy custom nginx config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: reload nginx

  handlers:
    - name: reload nginx
      service:
        name: nginx
        state: restarted

Выглядит несложно, правда? Но новички (и я сам когда‑то) часто допускают одни и те же ошибки, превращающие такой плейбук в грабли. Перечислю те, что мы выстрадали:

  • Писать команды «в лоб» через shell/command. Например, вместо модуля apt использовать shell: apt-get install nginx. Ansible не сможет определить, изменилось ли состояние системы, и корректно обработать повторный запуск. Всегда ищите нативный модуль.

  • Хардкодить значения, которые меняются от окружения. В примере выше порт вынесен в переменную — это минимум. Лучше вообще использовать групповые переменные инвентаря.

  • Забывать про become для привилегированных операций. Без become: yes плейбук молча упадет на попытке записи в /etc.

Ещё одна сложность — отсутствие тегов. Представьте плейбук с 20 задачами, и вам нужно запустить только задачи, связанные с Nginx. Если вы не пометили таски тегами, придётся гонять всё целиком. Поэтому правило хорошего тона:

tasks:
  - name: Ensure nginx is installed
    apt: ...
    tags: [install, nginx]

Best Practices, которые действительно работают

За годы практики я собрал для себя (и своих студентов на курсе «DevOps практики и инструменты») набор правил, которые помогают не наступать на грабли:

  1. Структурируйте репозиторий по ролям. Даже если у вас пара плейбуков, сразу закладывайте разделение: group_vars/host_vars/, роли в roles/. Это окупится, когда проект вырастет.

  2. Используйте ansible-vault для секретов. Пароли, токены, приватные ключи никогда не должны лежать в открытом виде в Git. В связке с CI/CD можно передавать пароль от vault через переменные окружения.

  3. Запускайте ansible-lint и ansible-playbook --syntax-check на каждом коммите. Это ваш первый уровень защиты от глупых ошибок в YAML и откровенно плохих практик.

  4. Проверяйте идемпотентность с --check --diff. Перед продакшеном обязательно смотрите, что именно изменится. Это спасёт от ситуации «ой, я думал модуль только добавит строчку, а он перезаписал весь конфиг».

  5. Дробите плейбуки по ответственности. Не валите всё в один огромный файл: базовую настройку ОС, установку Docker, деплой приложения держите раздельно. Так меньше риск сломать всё разом.

  6. Документируйте неочевидное прямо в YAML с помощью name и comments. Через месяц вы сами скажете себе спасибо.

Чтобы наглядно представить, как Ansible взаимодействует с инфраструктурой, я подготовил схему (Рис. 1). Она отражает push‑модель и основные компоненты.

Рис. 1 Схема push-модели Ansible
Рис. 1 Схема push‑модели Ansible

Схема иллюстрирует принцип push‑модели Ansible: управляющий узел (Control Node) по SSH подключается к целевым хостам и самостоятельно инициирует на них выполнение задач. При запуске он считывает список машин из статического или динамического инвентаря и загружает сценарий автоматизации — плейбук в YAML‑формате. Затем, используя встроенную библиотеку модулей, Ansible последовательно выполняет задачи, параллельно применяя их к группе узлов, что позволяет привести систему к требуемому состоянию.

При интеграции в CI/CD процесс усложняется, и появляется дополнительная обвязка из линтеров и сухих прогонов. Это отражено на Рис. 2.

Рис. 2 Типовой процесс CI/CD с использованием Ansible
Рис. 2 Типовой процесс CI/CD с использованием Ansible

На схеме изображён полностью автоматизированный пайплайн доставки конфигураций с помощью Ansible, интегрированный в систему непрерывной интеграции Jenkins. Процесс запускается в момент, когда разработчик отправляет изменения плейбуков в Git‑репозиторий — это единственное ручное действие, необходимое для старта. Git через механизм вебхуков мгновенно оповещает Jenkins о появлении нового кода, и конвейер переходит к серии автоматических проверок.

Первым делом Jenkins выполняет ansible-playbook --syntax-check — быструю проверку корректности YAML‑синтаксиса и структуры плейбука. Сразу за ней следует ansible-lint, который анализирует код на соответствие лучшим практикам, выявляет потенциально опасные конструкции и нарушения стиля. Если линтер находит ошибки, пайплайн немедленно останавливается и отправляет разработчику уведомление о провале. Это критически важный барьер: он не пропускает в продакшен даже случайные опечатки.

Если проверки пройдены успешно, Jenkins переходит к этапу «сухого прогона» — ansible-playbook --check --diff. Ansible Control при этом подключается к целевым управляемым узлам по SSH, но не вносит никаких реальных изменений. Вместо этого он симулирует применение плейбука и фиксирует, какие файлы, пакеты или сервисы были бы модифицированы (для модулей, поддерживающих check mode). Результат — детальный отчёт о планируемых изменениях — направляется обратно разработчику.

Дальше в процесс включается человек: разработчик изучает dry‑run отчёт и должен явно одобрить применение изменений. Это ручное подтверждение выполняет роль «последнего предохранителя» перед запуском на живых серверах. Только получив одобрение, Jenkins инициирует реальное выполнение плейбука командой ansible-playbook (без флагов проверки). Ansible Control по SSH применяет все описанные в сценарии задачи к целевым нодам, что в большинстве случаев приводит инфраструктуру в требуемое состояние.

Такая архитектура превращает деплой из нервного ручного действа в контролируемый, воспроизводимый и полностью логируемый процесс.

Что дальше?

Ansible не решит всех проблем, если подходить к нему как к «волшебной палочке». Но он даёт главное — воспроизводимость и прозрачность. Вы всегда знаете, в каком состоянии должны быть ваши серверы, и можете доказать аудиторам, что изменения применялись предсказуемо.

На курсе «DevOps практики и инструменты» разбираем, как выстраивать такие процессы системно: от CI/CD и GitLab CI до Ansible, контейнеризации, мониторинга и практик надёжной доставки изменений.

Присмотритесь к бесплатным открытым урокам:

  • 30 июня в 20:00 — «GitLab CI как конструктор workflow». Записаться
    покажем, как создавать эффективные и надёжные пайплайны с помощью GitLab CI.

  • 15 июля в 18:00 — «Настройка GitLab Runners. Хаки по настройке и оптимизации сборок проектов». Записаться
    разберем, как неправильная настройка раннеров замедляет сборки и что с этим делать.

На уроках можно будет познакомиться с форматом обучения, задать вопросы преподавателю-практику и понять, какие пробелы в DevOps-процессах стоит закрыть в первую очередь.

Больше бесплатных открытых уроков по DevOps, разработке, инфраструктуре и другим IT-направлениям собрали в дайджесте OTUS. Там можно выбрать тему под свой текущий стек, рабочую задачу или пробел, который давно пора закрыть.

Комментарии (0)