# Ansible или Terraform: что выбрать и когда объединять

> Ansible и Terraform решают разные задачи: Terraform создаёт серверы, Ansible настраивает их. Разбираем, когда какой инструмент нужен.

Вопрос "Ansible или Terraform" возникает у каждого, кто впервые автоматизирует развёртывание серверов. Короткий ответ: это разные инструменты для разных задач, и в реальных проектах они почти всегда работают вместе. Terraform создаёт инфраструктуру — сервер, диск, сеть, а Ansible настраивает то, что уже создано. Разберём, где проходит граница и как собрать из двух инструментов один рабочий пайплайн.

## Чем принципиально отличаются Ansible и Terraform

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

Граница простая: Terraform отвечает на вопрос "сколько серверов и какие" — VDS, диски, приватная сеть, правила фаервола у провайдера. Ansible отвечает на вопрос "что внутри сервера" — какой веб-сервер, какая версия PHP, какие пользователи и cron-задачи.

## Когда выбирать Terraform

Terraform нужен, если инфраструктура описывается через API облачного провайдера: заказ VDS, привязка плавающего IP, настройка приватной сети между серверами, создание балансировщика нагрузки. Если завтра нужно поднять второй такой же кластер серверов в другом регионе, Terraform сделает это за одну команду.

- Заказ и удаление серверов через API провайдера без ручных кликов в панели
- Версионирование инфраструктуры в git — изменения видны в diff перед применением
- Воспроизводимость: staging и production собираются из одного набора файлов

## Когда выбирать Ansible

Ansible нужен там, где серверы уже существуют и их надо привести к одинаковому состоянию: установить nginx и PHP-FPM, развернуть SSH-ключи, настроить firewall на уровне ОС, применить обновления безопасности. Ему не важно, откуда взялся сервер — из Terraform, из ручного заказа в панели ZevsHost или из старого парка железа.

- Настройка ПО и служб на серверах, которые уже существуют
- Массовое применение изменений на десятках серверов одной командой
- Задачи, которые не описываются термином "инфраструктура": деплой кода, ротация логов, обновление сертификатов

## Декларативный и процедурный подход: в чём разница на практике

Terraform декларативен: файл описывает желаемое состояние, а не список шагов. Запустили `terraform apply` дважды подряд без изменений в файлах — второй раз ничего не произойдёт. Ansible процедурен по структуре плейбука, но идемпотентен по каждому модулю: модуль `apt` не переустановит уже установленный пакет, а модуль `copy` не перезапишет файл с тем же содержимым.

| Критерий | Terraform | Ansible |
| --- | --- | --- |
| Что описывает | Ресурсы облака: серверы, диски, сети | Состояние ОС и приложений на сервере |
| Модель | Декларативная, с файлом состояния | Последовательность задач по инвентарю |
| Хранение состояния | state-файл, обычно в S3 или Terraform Cloud | Состояние не хранится, проверяется при каждом запуске |
| Скорость правки одного параметра | Требует apply, может пересоздать ресурс | Точечный запуск playbook на нужный хост |

## Как связать Terraform и Ansible в одном пайплайне

Стандартная схема: Terraform создаёт сервер и выводит его IP-адрес через `output`, Ansible берёт этот адрес как inventory и настраивает сервер. Провайдер VDS для примера — [Hetzner Cloud](https://www.zevshost.net/ru/kb/hetzner-cloud-nastroika-servera/), но схема работает с любым провайдером, у которого есть API.

```
resource "hcloud_server" "web" {
  name        = "web-01"
  server_type = "cx22"
  image       = "ubuntu-24.04"
  ssh_keys    = [hcloud_ssh_key.main.id]
}

output "web_ip" {
  value = hcloud_server.web.ipv4_address
}
```

Дальше динамический inventory для Ansible собирается из вывода Terraform одной командой, а сам плейбук ставит базовый набор пакетов:

```
- hosts: web
  become: true
  tasks:
    - name: Установить nginx и PHP-FPM
      apt:
        name: ["nginx", "php-fpm"]
        state: present
        update_cache: true
    - name: Запустить и включить nginx
      service:
        name: nginx
        state: started
        enabled: true
```

Полный процесс — от заказа сервера до готового к работе окружения — обычно оформляют отдельным этапом в [пайплайне GitLab CI](https://www.zevshost.net/ru/kb/gitlab-ci-deploy-vps/): сначала джоб с `terraform apply`, затем джоб с `ansible-playbook`, который получает адрес из артефактов первого шага. Подробнее про совместное описание инфраструктуры в коде смотрите в статье про [Terraform для VPS](https://www.zevshost.net/ru/kb/terraform-vps-infrastruktura/).

## Частые ошибки при совместном использовании

Первая ошибка — дублирование ответственности: часть настройки сервера прописывают через `cloud-init` внутри Terraform, а часть — через Ansible, и через полгода никто не помнит, где что менять. Вторая — хранение state-файла Terraform локально на ноутбуке разработчика без резервной копии: при потере файла Terraform перестаёт понимать, что уже создано, и норовит создать ресурсы заново.

- Смешивание задач настройки ОС между cloud-init и Ansible в одном проекте
- Локальный state-файл Terraform без удалённого бэкенда и блокировок
- Запуск Ansible без предварительной проверки playbook в режиме `--check`

## Итог: короткий чек-лист выбора

Если нужно управлять серверами, дисками и сетями у провайдера — берите Terraform. Если нужно настроить то, что уже работает, — берите Ansible. В большинстве проектов оба инструмента используются вместе, каждый в своей зоне ответственности.

- Инфраструктура облака и её версии в git — Terraform
- Пакеты, конфиги и службы внутри сервера — Ansible
- State Terraform хранить удалённо, с блокировкой
- Связывать оба шага одним пайплайном CI, а не запускать вручную

---

Источник: https://www.zevshost.net/ru/kb/ansible-ili-terraform/
