# 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/uk/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/uk/kb/gitlab-ci-deploy-vps/): спочатку джоба з `terraform apply`, потім джоба з `ansible-playbook`, яка отримує адресу з артефактів першого кроку. Детальніше про спільний опис інфраструктури в коді дивіться у статті про [Terraform для VPS](https://www.zevshost.net/uk/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/uk/kb/ansible-ili-terraform/
