ADG Оставить заявку
Блог DevOps 5 мин чтения

Terraform Cloud: переходим с S3-бэкенда на remote state с историей и state locking

HashiCorp расширила бесплатный тир Terraform Cloud: remote state, Sentinel-политики, workspace-workflow для команд. Переехали с S3-бэкенда - делимся опытом.

Контекст момента

HashiCorp расширил бесплатный тир Terraform Cloud: remote state, Sentinel-политики, улучшенный workspace-workflow для команд до 5 человек

Полгода назад мы мигрировали инфраструктурный код на Terraform 0.12 и заодно разбирались с remote state. Тогда остановились на S3 + DynamoDB для state locking - классическое решение, работает, описано во всех гайдах. Но у него есть одна особенность: чтобы этот бэкенд существовал, его нужно сначала создать, и желательно не через Terraform - получается bootstrap-проблема. Мы держали отдельный S3-бакет и DynamoDB-таблицу, управлявшиеся руками. Так себе ситуация для команды, которая декларирует infrastructure-as-code.

В мае HashiCorp обновила условия Terraform Cloud: бесплатный тир теперь включает remote state для команд до 5 человек, а также workspace-workflow с историей plan/apply и базовые Sentinel-политики. Мы завели аккаунт и потратили пару дней на перенос.

Что было не так с S3-бэкендом

Жаловаться на S3-бэкенд серьёзно - это было бы преувеличением. Работает надёжно. Но есть несколько вещей, которые стабильно создавали трение.

State locking через DynamoDB - вроде бы мелочь, но нужно следить, чтобы таблица существовала и имела правильный первичный ключ (LockID типа String). Один раз кто-то из команды снёс не ту таблицу в процессе уборки - всё началось с невинного вопроса «а зачем эта DynamoDB нужна». Потом полчаса разбирались, почему Terraform говорит, что не может заблокировать state.

Нет истории в штатном виде. S3 поддерживает versioning, и технически через консоль можно смотреть старые версии state-файлов. Но это не то же самое, что история plan/apply с привязкой к git-коммиту и автору.

Bootstrap - тот самый. Новый проект = сначала создать бакет и таблицу руками или отдельным Terraform-кодом, который сам хранит state локально. Небольшой, но постоянный налог при онбординге.

Что такое Terraform Cloud remote state в 2020-м

Terraform Cloud - это сервис HashiCorp, который существует уже несколько лет, но долгое время был платным для командного использования. Сейчас бесплатный тир стал полезнее: workspace с remote state, state locking из коробки, history plan/apply, базовый Sentinel для policy as code.

Remote state в Terraform Cloud - это не просто хранилище файла. Workspace хранит:

  • сам state с версионированием
  • историю всех run-ов: кто запустил, когда, какой план, применился или нет
  • переменные (и чувствительные, с шифрованием)
  • доступ через API-токен

Sentinel - отдельная история. Это policy-as-code движок: пишешь политику на языке Sentinel, она проверяется между plan и apply. Например, можно запретить создавать публичные S3-бакеты или требовать наличие определённых тегов. В бесплатном тире это доступно, но с ограничениями по количеству политик.

Как переехали

Переезд с S3 на Terraform Cloud remote state - это по сути замена backend-блока и последовательный terraform init с миграцией.

Было:

terraform {
  backend "s3" {
    bucket         = "company-tfstate"
    key            = "prod/vpc/terraform.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "terraform-state-lock"
  }
}

Стало:

terraform {
  backend "remote" {
    organization = "adg"

    workspaces {
      name = "prod-vpc"
    }
  }
}

После этого terraform init предлагает скопировать существующий state. Соглашаешься, state переезжает в Terraform Cloud, локальный файл удаляется. Всё занимает минуты.

Нюанс один: нужно заранее создать workspace в Terraform Cloud и убедиться, что токен настроен через terraform login или переменную TF_TOKEN_app_terraform_io. Иначе init упадёт с невнятным сообщением об авторизации.

Что поменялось в работе команды

Больше нет bootstrap-проблемы. Новый проект - создаём workspace в UI Terraform Cloud, добавляем backend-блок, делаем init. Никаких предварительных шагов с ресурсами AWS.

История plan/apply теперь есть в одном месте. Можно зайти в UI и посмотреть кто и когда последний раз делал apply на prod, какие ресурсы изменялись. Раньше это либо было в голове человека, который запускал, либо нужно было копаться в git-истории и пытаться восстановить последовательность.

State locking работает без DynamoDB. Terraform Cloud берёт это на себя. Если кто-то запустил plan - другой получит сообщение, что workspace заблокирован, с указанием кем и когда. Это то, что должно работать само по себе, без дополнительной инфраструктуры.

Переменные из UI вместо .tfvars в репозитории. Чувствительные переменные - токены, пароли - теперь живут в Terraform Cloud с пометкой sensitive. В репозитории их нет вообще. Это лучше, чем .tfvars.encrypted с ключом где-то в 1Password.

Что пока не нравится

Remote run - это когда plan и apply выполняются на агентах Terraform Cloud, а не локально. По умолчанию новые workspace создаются в этом режиме. Для нас это пока неудобно: часть инфраструктурного кода обращается к внутренним сервисам, недоступным снаружи нашей сети. Пришлось переключить workspace в режим local operations - тогда plan/apply выполняются локально, но state и история хранятся в Terraform Cloud. Это рабочий компромисс.

Sentinel-политики попробовали на одном workspace. Язык простой, порог входа невысокий, но для серьёзного использования политики нужно тестировать - есть sentinel test, это отдельный тулчейн. Оставили на потом, сейчас достаточно того, что state нормально работает.

Итого

Переезд занял меньше дня на все активные проекты. S3-бэкенд работал, претензий не было, но Terraform Cloud убирает bootstrap-налог и добавляет историю изменений и нормальный state locking без внешних зависимостей. Для managed-сопровождения это удобнее: всё в одном месте, доступ через токен, никакой дополнительной AWS-инфраструктуры ради хранения state.

DynamoDB-таблицу и S3-бакет с tfstate снесли. Приятно.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.