Миграция состояния в S3

Для удобства можно загрузить файл tfstate в хранилище S3. Дальнейшее взаимодействие с этим файлом состояния будет производиться непосредственно механизмами Terraform. Преимущество такого варианта хранения — функция блокировки файла во время использования. Благодаря этому становится возможной одновременная работа команды инженеров над объемной инфраструктурой без риска конфликтов при запуске критичных операций. И, конечно же, размещение состояния в S3 предполагает надежность хранения и версионирование файла.

Миграция файла состояния tfstate начинается с создания отдельного каталога, в котором будут описаны файлы конфигурации, предназначенные только для создания ресурсов, обеспечивающих функции хранения состояния.

provider.tf

Изначально создадим конфиг провайдера:

provider "aws" {
  region = "eu-central-1"
}

terraform {
  required_providers {
    aws = {
      version = "~> 3.28.0"
    }
  }
}

Создание хранилища

Затем — конфиг ресурса aws_s3_bucket. Данный ресурс создает выделенное хранилище в S3:

resource "aws_s3_bucket" "terraform_state" {
  bucket = "eu-terraform-state"
  lifecycle {
    prevent_destroy = true
  }
  versioning {
    enabled = true
  }
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}

Особенностями представленной конфигурации являются следующие параметры:

  • bucket: название каталога для хранения;
  • lifecycle { prevent_destroy = true }: запрет на удаление ресурса;
  • versioning { enabled = true }; включение версионирования файла terraform.tfstate на стороне S3-хранилища;
  • server_side_encryption_configuration: настройки шифрования.

Создание таблицы DynamoDB

Также добавим в конфиг ресурс aws_dynamodb_table. Это таблица AWS DynamoDB, в которой будет храниться информация о блокировках файла terraform.tfstate:

resource "aws_dynamodb_table" "terraform_locks" {
  name = "eu-terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key = "LockID"
  attribute {
    name = "LockID"
    type = "S"
  }
}
  • name: название таблицы для записи информации о блокировках;
  • billing_mode = “PAY_PER_REQUEST”: тип оплаты. Значение PAY_PER_REQUEST позволяет оплачивать по количеству обращений к таблице;
  • hash_key
attribute {
  name = "LockID"
  type = "S"
}

указание первичного ключа таблицы.

Подготовка к переходу

Инициализируем конфигурацию, после чего выполняем планирование и применение:

~$ terraform init
Initializing the backend...
                ~~~
Terraform has been successfully initialized!

~/states/eu$ terraform plan
Terraform will perform the following actions:

  # aws_dynamodb_table.terraform_locks will be created

  # aws_s3_bucket.terraform_state will be created

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

~/states/eu$ terraform apply
Terraform will perform the following actions:

  # aws_dynamodb_table.terraform_locks will be created

  # aws_s3_bucket.terraform_state will be created

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

aws_dynamodb_table.terraform_locks: Creating...
aws_s3_bucket.terraform_state: Creating…

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Активация нового бэкенда

Переходим в директорию с конфигурацией ресурсов AWS и создаем в ней файл backend.tf следующего содержания:

~$ cd ../../regions/eu
~$ vim backend.tf
terraform {
 backend "s3" {
   bucket = "eu-terraform-state"
   key = "terraform.tfstate"
   region = "eu-central-1"
   dynamodb_table = "eu-terraform-locks"
   encrypt = true
 }
}

Если попытаться выполнить какие-либо действия с текущей конфигурацией ресурсов, то возникнет ошибка:

Backend reinitialization required. Please run "terraform init".
Reason: Initial configuration of the requested backend "s3"

Для ее устранения требуется повторно запустить инициализацию. При этом Terraform обратится в созданное ранее хранилище S3 и запросит файл terraform.tfstate. Поскольку хранилище еще пустое, он предложит нам перенести локальный state-файл в хранилище S3:

~/regions/eu$ terraform init

Initializing the backend...
Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "local" backend to the
  newly configured "s3" backend. No existing state was found in the newly
  configured "s3" backend. Do you want to copy this state to the new "s3"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes

Releasing state lock. This may take a few moments...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

Terraform has been successfully initialized!
И, наконец, планируем окончательную версию конфигурации:
~/regions/eu$ terraform plan
Refreshing Terraform state in-memory prior to plan...
                ~~~
No changes. Infrastructure is up-to-date.

Подробнее здесь