Как настроить Amazon S3 для хранения state-файла Terraform?

Ответ

Хранение Terraform state в S3 с блокировкой через DynamoDB — это стандартный подход в моих проектах для обеспечения консистентности и совместной работы команды.

Пошаговая настройка:

  1. Создание S3 bucket и DynamoDB таблицы. Я делаю это отдельным "бутстрап"-конфигом Terraform или через AWS CLI для начальной инициализации инфраструктуры управления.

    # Создание bucket с версионированием и шифрованием
    aws s3api create-bucket --bucket my-company-terraform-state --region us-east-1
    aws s3api put-bucket-versioning --bucket my-company-terraform-state --versioning-configuration Status=Enabled
    aws s3api put-bucket-encryption --bucket my-company-terraform-state --server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'
    
    # Создание таблицы DynamoDB для блокировок
    aws dynamodb create-table 
        --table-name terraform-state-locks 
        --attribute-definitions AttributeName=LockID,AttributeType=S 
        --key-schema AttributeName=LockID,KeyType=HASH 
        --billing-mode PAY_PER_REQUEST
  2. Конфигурация backend в основном коде Terraform. Указываю созданные ресурсы.
    terraform {
      backend "s3" {
        bucket         = "my-company-terraform-state"
        key            = "production/network/terraform.tfstate" # Логическая структура папок
        region         = "us-east-1"
        dynamodb_table = "terraform-state-locks"
        encrypt        = true
      }
    }
  3. Инициализация. После добавления backend-конфигурации выполняю terraform init. Terraform предложит перенести существующий локальный state в S3.

Важные детали из практики:

  • Ключ (key) лучше структурировать по проектам и окружениям (например, prod/vpc/state, dev/eks/state).
  • Bucket Policy стоит настроить так, чтобы запретить удаление state-файлов всем, кроме админов, и включить MFA Delete для дополнительной защиты.
  • Для разных команд или проектов можно использовать один bucket, но разные ключи и DynamoDB таблицы (или разные атрибуты в одной таблице).

Ответ 18+ 🔞

А, ну это классика, ёпта! Хранение стейта Terraform в S3 с блокировкой через DynamoDB — это как поставить хороший замок на дверь, чтобы твои же коллеги случайно не наебнули всю инфраструктуру, пока ты её меняешь. Без этого — пиздец и бардак, state-файлы летают у всех локально, и потом все дружно охуевают, откуда взялась лишняя сетевая карта.

Как это делается, по шагам:

  1. Создаём ведро и таблицу для блокировок. Я обычно делаю это отдельным куском кода, типа "бутстрап", или просто через AWS CLI, чтобы не париться. Главное — сделать это один раз и навсегда.

    # Создаём ведро, включаем версионирование и шифрование. Без этого — вообще никуда.
    aws s3api create-bucket --bucket my-company-terraform-state --region us-east-1
    aws s3api put-bucket-versioning --bucket my-company-terraform-state --versioning-configuration Status=Enabled
    aws s3api put-bucket-encryption --bucket my-company-terraform-state --server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'
    
    # А это — наша спасительная табличка в DynamoDB. Она не даст двум терраформам одновременно лезть в один state.
    aws dynamodb create-table 
        --table-name terraform-state-locks 
        --attribute-definitions AttributeName=LockID,AttributeType=S 
        --key-schema AttributeName=LockID,KeyType=HASH 
        --billing-mode PAY_PER_REQUEST

    Без этой таблицы — доверия ебать ноль. Кто-нибудь да запустит apply одновременно с тобой и будет вам хиросима.

  2. Прописываем backend в основном коде. Теперь говорим терраформу: "Дружище, забудь про локальный файл, всё теперь живёт в облаке".

    terraform {
      backend "s3" {
        bucket         = "my-company-terraform-state" # Имя нашего священного ведра
        key            = "production/network/terraform.tfstate" # Раскладываем по папочкам, а то будет пиздопроебища
        region         = "us-east-1"
        dynamodb_table = "terraform-state-locks" # Волшебная таблица против конфликтов
        encrypt        = true # Ну а хули, шифруем на всякий
      }
    }
  3. Инициализируем. Запускаешь terraform init, а он тебе: "О, я вижу, ты state в S3 хочешь хранить. Переносим?". Говоришь "да", и твой локальный terraform.tfstate летит в облака. С этого момента все работают с одной правдой.

А теперь жизненные лайфхаки, чтобы не обосраться:

  • Ключ (key) — это твой лучший друг. Структурируй его как книгу: проект/окружение/компонент. Типа prod/vpc/state, dev/eks/state. Иначе через полгода в одном файле будет овердохуища всего, и разобраться — тот ещё квест.
  • Политика доступа к ведру (Bucket Policy) — это must have. Настрой так, чтобы удалять state-файлы мог только господь бог и, может быть, ты (после трёх подтверждений). MFA Delete включи — подозрение ебать чувствую ко всем этим случайным кликам.
  • На всю компанию часто хватает одного ведра, но кучи разных ключей. С DynamoDB тоже можно одну таблицу на всех использовать — она же по LockID различает, чья там блокировка. Главное — договориться, кто как называет свои проекты, а то получится манда с ушами.