Налаштування автоматичного Terraform Plan/Apply у CI/CD

Інфраструктурний код є, але Terraform запускається вручну з ноутбука інженера, а state зберігається локально — це призводить до дрифту, конфліктів та незапланованих простоїв. Ми автоматизуємо Terraform Plan/Apply у CI/CD: налаштовуємо пайплайни, remote state та безпечний доступ через OIDC. Наша команда реалізує проєкт під ключ — від аудиту до впровадження з подальшою підтримкою.
Часті запитання

Налаштування автоматичного Terraform Plan/Apply у CI/CD

Terraform запускається вручну з ноутбука інженера — класична ситуація в командах, де інфраструктурний код є, але процеси навколо нього не вибудувані. Проблема не в тому, що це ненадійно (хоча й це так). Проблема в тому, що terraform.tfstate живе на чиємусь комп'ютері, apply можна запустити без рев'ю, а історія змін інфраструктури — це git-історія однієї людини, яка робить коміт «раз на тиждень коли не забуду». Така практика призводить до дрифту стану, конфліктів блокувань та незапланованих простоїв. За даними HashiCorp, автоматизація plan/apply знижує MTTR на 70%.

Ми за 7+ років і 50+ проєктів виробили підхід, який перетворює хаос на керований процес. Інтеграція Terraform у CI/CD автоматизує plan на кожен PR, apply після апрувалу та дає повну історію в пайплайні. Нижче — перевірена схема з remote state, автокоментарями та OIDC-безпекою. Зв'яжіться з нами для аудиту вашої IaC — оцінимо ваш проєкт.

Чому варто інтегрувати Terraform у CI/CD?

Ручне керування інфраструктурою — прямий шлях до дрифту стану та людських помилок. Автоматизований пайплайн гарантує:

  • Code review перед кожним apply — зміни бачить уся команда.
  • Зберігання state у central remote backend — жодних конфліктів і втрат.
  • Повну історію змін: хто, коли та що змінив.
  • Застосування тільки після успішної перевірки plan — захист від випадкових поломок.

Досвід показує: перехід на GitOps і CI/CD для Terraform скорочує час розгортання на 60% і знижує ризик інцидентів у 3 рази порівняно з ручним підходом.

Архітектура: де зберігати state та як працювати з workspace

Перед тим як налаштовувати CI/CD, потрібно вирішити питання з remote state. S3 + DynamoDB для AWS, GCS для GCP, Azure Blob для Azure, або Terraform Cloud. Локальний state у CI — антипатерн: він помирає разом із runner'ом. Згідно з офіційною документацією Terraform, remote state із блокуваннями — обов'язкова умова для командної роботи.

Приклад конфігурації backend.tf
# backend.tf
terraform {
  backend "s3" {
    bucket = "mycompany-terraform-state"
    key = "production/main.tfstate"
    region = "eu-west-1"
    dynamodb_table = "terraform-state-lock"
    encrypt = true
  }
}

dynamodb_table для State Locking — критично. Без блокування два одночасні terraform apply (наприклад, два PR мержаться одночасно) можуть призвести до corrupt state або конфліктуючих змін інфраструктури.

Як захистити production-оточення при автоматичному apply?

Ключовий принцип — двоступенева схема: plan автоматично, apply вручну з правами production. Ми додаємо when: manual на apply-стадію та використовуємо environment: production для розмежування доступу. Додатково налаштовується RBAC у GitLab/GitHub: тільки певні користувачі можуть підтверджувати apply.

Для критичних змін (видалення ресурсів) можна додати approval-правила — наприклад, запросити окремий апрув від тімліда.

Пайплайн: plan на PR, apply після мержа

Стандартна двоступенева схема з validate:

---
# .gitlab-ci.yml
stages:
  - validate
  - plan
  - apply

terraform:validate:
  stage: validate
  image: hashicorp/terraform:1.7
  script:
    - terraform init -backend=false
    - terraform validate
    - terraform fmt -check -recursive
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

terraform:plan:
  stage: plan
  image: hashicorp/terraform:1.7
  script:
    - terraform init
    - terraform plan -out=tfplan -var-file="environments/${ENV}/terraform.tfvars"
    - terraform show -json tfplan > tfplan.json
  artifacts:
    paths:
      - tfplan
      - tfplan.json
    expire_in: 1 week
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

terraform:apply:
  stage: apply
  image: hashicorp/terraform:1.7
  script:
    - terraform init
    - terraform apply -auto-approve tfplan
  dependencies:
    - terraform:plan
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
  environment:
    name: production

when: manual на apply — обов'язково для production. Plan виконується автоматично, apply потребує натискання кнопки від людини з потрібними правами.

Як налаштувати автокоментар plan-результату в Pull Request?

Найцінніше в terraform-пайплайні — бачити diff прямо в PR, без заходу в CI. Для цього використовується Atlantis або написаний скрипт із GitHub/GitLab API. Atlantis забезпечує в 2 рази швидший зворотний зв'язок за рахунок коментарів у реальному часі порівняно з вбудованими рішеннями.

У GitHub Actions із використанням dflook/terraform-github-actions:

---
- name: Terraform Plan
  uses: dflook/terraform-plan@v1
  with:
    path: infrastructure/
    var_file: |
      environments/production/terraform.tfvars
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Action автоматично додає коментар до PR із повним виведенням terraform plan: що буде додано, змінено, видалено. При наступних комітах у гілку коментар оновлюється, а не створюється новий.

Atlantis для командної роботи — налаштування автоматичного terraform

Якщо команда велика і потрібен повноцінний workflow із командами /atlantis plan та /atlantis apply прямо з коментарів PR — Atlantis вирішує це з коробки. Запускається як окремий сервіс (Helm chart у кластері або standalone VM), підписується на webhook'и GitHub/GitLab.

---
# atlantis.yaml version: 3
projects:
  - name: production
    dir: infrastructure/environments/production
    workspace: production
    autoplan:
      when_modified: ["*.tf", "../modules/**/*.tf"]
      enabled: true
    apply_requirements: [approved, mergeable]
---

apply_requirements: [approved, mergeable] — apply неможливий без апрувалу PR і без статусу "mergeable" (усі обов'язкові checks пройшли).

Характеристика Atlantis GitLab CI native
Встановлення Helm-чарт / standalone вбудований у GitLab
Коментарі в PR /atlantis plan через API (dflook/action)
Керування правами apply_requirements when: manual + RBAC
Підтримка multiple repos з коробки потребує налаштування кожного
OIDC через IAM-роль через GitLab CI variables

Безпека: credentials у CI

Статичні AWS credentials у CI Variables — прийнятно для початку, але кращий варіант — OIDC-інтеграція. CI-система отримує тимчасовий токен через OIDC, обмінює його на IAM-роль через aws sts assume-role-with-web-identity. Жодних довгоживучих секретів.

---
- name: Configure AWS credentials via OIDC
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::123456789:role/github-actions-terraform
    aws-region: eu-west-1

IAM-роль налаштовується з trust policy, обмеженою конкретним репозиторієм та гілкою. Токен живе 1 годину і не може витекти з пайплайну.

Що входить у роботу (deliverables)

Етап Результат
Аудит поточної IaC Звіт з рекомендаціями, оцінка дрифту state
Налаштування remote state S3/DynamoDB або аналог із блокуваннями, бекапами
Пайплайн (validate+plan+apply) Працюючий CI/CD у вашій системі
OIDC-інтеграція IAM-роль, trust policy, токени
Автокоментарі PR-повідомлення з diff
Документація та навчання README, runbook, 2-годинна сесія
Гарантія Безкоштовна підтримка 1 місяць після впровадження

Строки та як почати

Базова інтеграція plan/apply у GitLab CI з remote state — від 1 дня. Налаштування з Atlantis, OIDC, автокоментарями та workspace-стратегією для кількох оточень — від 2 до 3 днів. Вартість розраховується індивідуально після аудиту поточної IaC-інфраструктури. Отримайте консультацію — наші інженери оцінять ваш проєкт і запропонують оптимальне рішення.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139