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 снесли. Приятно.