Terraform vs Ansible: когда что использовать

terraformansibleiacdevops

“Terraform или Ansible?” — один из самых частых вопросов, которые мне задают. И ответ почти всегда: “Оба”. Это не конкуренты, а инструменты для разных задач, которые отлично работают вместе. Давайте разберёмся, где проходит граница.

Философия: декларативный vs процедурный

Terraform — декларативный. Вы описываете желаемое состояние инфраструктуры, а Terraform сам вычисляет, что нужно сделать, чтобы его достичь. Создать сервер, удалить диск, изменить DNS-запись — всё это Terraform решает сам на основе разницы между текущим и целевым состоянием.

Ansible — преимущественно процедурный, хотя многие модули идемпотентны. Вы описываете последовательность шагов: установи пакет, скопируй файл, перезапусти сервис. Ansible выполняет их по порядку.

На практике это означает: Terraform знает, что “сервер уже существует” и не будет его пересоздавать. Ansible знает, что “nginx уже установлен” и не будет его переустанавливать. Но Terraform мыслит целиком инфраструктурой, а Ansible — задачами на конкретной машине.

# Terraform: "Хочу сервер с такими параметрами"
resource "hcloud_server" "web" {
  name        = "web-01"
  server_type = "cx22"
  image       = "ubuntu-24.04"
  location    = "fsn1"
  ssh_keys    = [hcloud_ssh_key.default.id]

  public_net {
    ipv4_enabled = true
    ipv6_enabled = true
  }
}

resource "hcloud_rdns" "web" {
  server_id  = hcloud_server.web.id
  ip_address = hcloud_server.web.ipv4_address
  dns_ptr    = "web-01.example.com"
}
# Ansible: "Настрой этот сервер так"
- name: Configure web server
  hosts: web_servers
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true

    - name: Deploy nginx config
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: Restart nginx

    - name: Ensure nginx is running
      ansible.builtin.systemd:
        name: nginx
        state: started
        enabled: true

Видите разницу? Terraform создаёт ресурс в облаке. Ansible настраивает то, что уже существует.

Ландшафт инструментов IaC: provisioning vs configuration management

Terraform: провижининг инфраструктуры

Terraform блестяще справляется с облачными ресурсами:

  • Виртуальные машины — Hetzner, AWS, DigitalOcean, любой провайдер
  • Сети — VPC, подсети, firewall rules, load balancers
  • DNS — записи в Cloudflare, Route53, любом DNS-провайдере
  • Хранилище — S3-бакеты, блочные диски, managed databases
  • Managed-сервисы — Kubernetes кластеры, managed PostgreSQL, Redis

Ключевая фича — state. Terraform хранит текущее состояние инфраструктуры в файле terraform.tfstate. Это позволяет ему точно знать, что существует, что изменилось и что нужно удалить:

$ terraform plan
# hcloud_server.web will be updated in-place
~ resource "hcloud_server" "web" {
    ~ server_type = "cx22" -> "cx32"
      # (6 unchanged attributes hidden)
  }

Plan: 0 to add, 1 to change, 0 to destroy.

terraform plan — одна из лучших вещей в Terraform. Вы видите, что произойдёт, до того как оно произойдёт. Никаких сюрпризов.

Но state — это и ахиллесова пята. Потеряли tfstate — Terraform больше не знает о вашей инфраструктуре. Поэтому state всегда хранят в remote backend (S3, Consul, Terraform Cloud), никогда локально.

Ansible: конфигурация и управление

Ansible — мастер конфигурации уже существующих серверов:

  • Установка и настройка софта — пакеты, конфиги, сервисы
  • Управление пользователями — аккаунты, SSH-ключи, sudo
  • Деплой приложений — git pull, docker compose up, systemd restart
  • Оркестрация — выполнение задач на группах серверов в определённом порядке
  • Ad-hoc команды — быстрые одноразовые действия на всём парке серверов

Ansible stateless — он не хранит состояние. Каждый запуск подключается к серверу, проверяет текущее состояние и приводит его к желаемому. Это и плюс (нечего терять), и минус (нет полной картины инфраструктуры).

# Полноценная роль для настройки сервера
- name: Harden SSH
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
  loop:
    - { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
    - { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
    - { regexp: '^#?Port ', line: 'Port 6622' }
  notify: Restart sshd

Где они пересекаются

Зона перекрытия существует, и это нормально:

  • Terraform может выполнять скрипты через provisioner "remote-exec", но это антипаттерн. Provisioners — escape hatch, не основной инструмент.
  • Ansible может создавать облачные ресурсы через модули amazon.aws.ec2_instance, hetzner.hcloud.server и подобные. Работает, но без state-файла вы не увидите полную картину.

Моё правило: если ресурс имеет lifecycle в облаке (создаётся, изменяется, удаляется через API провайдера) — это Terraform. Если речь о конфигурации внутри сервера — это Ansible.

Реальный рабочий процесс

Вот как это выглядит на практике в моих проектах:

Workflow: Terraform создаёт инфраструктуру, Ansible настраивает серверы

Шаг 1: Terraform создаёт инфраструктуру.

# main.tf
resource "hcloud_server" "app" {
  name        = "app-01"
  server_type = "cx22"
  image       = "ubuntu-24.04"
  location    = "fsn1"
  ssh_keys    = [hcloud_ssh_key.deploy.id]
}

resource "cloudflare_record" "app" {
  zone_id = var.cloudflare_zone_id
  name    = "app"
  content = hcloud_server.app.ipv4_address
  type    = "A"
  proxied = false
}

# Генерируем inventory для Ansible
resource "local_file" "ansible_inventory" {
  content = yamlencode({
    all = {
      hosts = {
        app-01 = {
          ansible_host = hcloud_server.app.ipv4_address
          ansible_port = 22
          ansible_user = "root"
        }
      }
    }
  })
  filename = "${path.module}/../ansible/inventory/generated.yml"
}

Шаг 2: Ansible настраивает сервер.

cd ansible
ansible-playbook -i inventory/generated.yml playbooks/setup.yml

Terraform даже генерирует inventory-файл для Ansible — полная автоматизация. После terraform apply можно сразу запускать плейбук.

Сравнение по критериям

КритерийTerraformAnsible
Основная задачаProvisioningConfiguration
ПодходДекларативныйПроцедурный (с идемпотентностью)
ЯзыкHCLYAML
СостояниеХранит в tfstateStateless
АгентНет (API-вызовы)Нет (SSH)
Планированиеterraform plan--check --diff
Облачные ресурсыОсновная специализацияВозможно, но неудобно
Конфигурация ОСЧерез provisioners (плохо)Основная специализация
Кривая обученияСредняя (HCL, state)Низкая (YAML, SSH)
Сообщество модулейTerraform RegistryAnsible Galaxy

Управление состоянием

Это фундаментальное различие, и оно влияет на всё.

Terraform с tfstate:

# State хранится удалённо
terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "eu-central-1"
  }
}

# Можно посмотреть текущие ресурсы
$ terraform state list
hcloud_server.app
hcloud_server.vpn
cloudflare_record.app
cloudflare_record.vpn

# Можно импортировать существующие ресурсы
$ terraform import hcloud_server.legacy 12345678

Ansible без state:

# Ansible просто подключается и проверяет
$ ansible all -m ansible.builtin.setup --limit app-01
# Получаем facts: ОС, IP, диски, память...

# Для "инвентаризации" -- ad-hoc команды
$ ansible all -m ansible.builtin.shell -a "systemctl list-units --state=running"

Когда что использовать

Используйте Terraform, когда:

  • Создаёте серверы, сети, DNS, бакеты, базы данных
  • Нужна полная картина инфраструктуры (state)
  • Работаете с несколькими облачными провайдерами
  • Хотите plan перед применением изменений

Используйте Ansible, когда:

  • Настраиваете софт на серверах (пакеты, конфиги, сервисы)
  • Деплоите приложения
  • Нужны ad-hoc команды на группе серверов
  • Управляете пользователями, SSH-ключами, firewall-правилами на уровне ОС

Используйте оба, когда:

  • У вас production-инфраструктура любого масштаба. Terraform создаёт, Ansible настраивает. Это не усложнение — это правильное разделение ответственности.

Итого

Спор “Terraform vs Ansible” — ложная дихотомия. Это как спорить, что лучше: молоток или отвёртка. У каждого инструмента своя зона ответственности, и вместе они покрывают весь жизненный цикл инфраструктуры: от создания VPS в облаке до настройки последнего конфига на сервере.

Начните с того, что болит: если у вас уже есть серверы и нужно их настраивать — начните с Ansible. Если вы часто создаёте и удаляете облачные ресурсы — начните с Terraform. Рано или поздно вам понадобятся оба.

© 2026 Terminal Notes. Built with SvelteKit.