Инфраструктура

Как настроить блокировку состояния Terraform в S3 с помощью OVHcloud Object Storage

Поделиться:
Terraform S3 state locking with OVHcloud Object Storage

В предыдущем посте блога я объяснил, как использовать совместимое с S3 объектное хранилище OVHcloud в качестве бэкенда Terraform для хранения файлов состояний Terraform/OpenTofu.

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

На практике Terraform/OpenTofu может создать объект .tflock, только если его ещё не существует. Если другая операция уже создала файл блокировки, условная запись не удаётся, и вторая операция блокируется.

В этом посте я объясню, как настроить бэкенд Terraform/OpenTofu для хранения состояний в совместимом с S3 объектном хранилище OVHcloud с блокировкой состояний S3.

Функция блокировки состояний S3 в Terraform/OpenTofu

Блокировка состояния — это критически важная функция для совместной работы с Terraform/OpenTofu. Она гарантирует, что в любой момент времени только одна операция может изменять файл состояния, предотвращая одновременные записи, которые могут привести к несоответствиям или повреждению состояния.

Конкретно: когда пользователь запускает terraform apply (или tofu apply), Terraform создаёт файл .tflock в S3-бакете. Этот файл блокировки указывает, что в данный момент выполняется операция и файл состояния используется. Если другой пользователь попытается запустить terraform apply (или tofu apply) во время активной блокировки, Terraform обнаруживает существующую блокировку и прерывает операцию с сообщением об ошибке. Это предотвращает одновременное изменение файла состояния и помогает избежать его повреждения.

Terraform S3 state locking with OVHcloud Object Storage

Предварительные требования

Чтобы хранить состояния Terraform/OpenTofu и активировать функцию use_lockfile, необходимо выполнить следующие предварительные условия:

  • Иметь учётную запись OVHcloud
  • Создать совместимое с S3 объектное хранилище (включите версионирование бакета для вашего бакета состояний, чтобы в случае необходимости можно было восстановить предыдущие версии состояния)
  • Установить CLI Terraform или CLI OpenTofu (версия 1.10 или выше)
  • Установить OVHcloud CLI

Сохраните учётные данные пользователя S3 в переменных окружения (это позволит вам получать доступ и хранить файлы в бакете):

export AWS_ACCESS_KEY_ID="xxxxxxxxx"
export AWS_SECRET_ACCESS_KEY="yyyyyyyyy"

Настройка

Создайте новую папку с именем my-app (например) и перейдите в неё.

Создайте файл provider.tf со следующим содержимым и замените значение bucket на имя созданного вами бакета:

terraform {
backend "s3" {
bucket = "terraform-state-3az" # имя ВАШЕГО бакета
key = "my-app.tfstate" # имя состояния вашего приложения
region = "eu-west-par" # регион бакета
endpoints = {
s3 = "https://s3.eu-west-par.io.cloud.ovh.net/" # эндпоинт
}
skip_credentials_validation = true
skip_region_validation = true
skip_requesting_account_id = true
skip_s3_checksum = true

use_lockfile = true # активация встроенной блокировки состояний S3
}
}

💡Аргумент use_lockfile = true включает встроенную блокировку состояний S3. Terraform/OpenTofu использует объект .tflock, чтобы предотвратить одновременную запись в один и тот же файл состояния двумя операциями.

Тестирование!

Создайте файл resource.tf с примером ресурса для создания (только для целей тестирования):

resource "null_resource" "test" {}

Инициализируйте Terraform:

$ terraform init

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Finding latest version of hashicorp/null...
- Installing hashicorp/null v3.3.0...
- Installed hashicorp/null v3.3.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Как видите, Terraform использует бэкенд «s3» и инициализировал провайдеры. 💪

💡Обратите внимание: .terraform.lock.hcl — это файл блокировки зависимостей провайдера, создаваемый при инициализации. Файл блокировки состояния, используемый для блокировки бэкенда S3, — это файл .tflock, который отображается в бакете во время terraform apply.

Выполните команду apply (не отвечайте «yes»):

$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# null_resource.test will be created
+ resource "null_resource" "test" {
+ id = (known after apply)
}

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

Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value:

Проверьте, появился ли новый файл в S3-бакете:

$ ovhcloud cloud storage object object list terraform-state-3az

┌───────────────────────┬──────┐
│ key │ size │
├───────────────────────┼──────┤
│ my-app.tfstate.tflock │ 219 │
└───────────────────────┴──────┘
💡 Используйте опцию -o json или -o yaml, чтобы получить необработанный вывод со всей информацией

Появился файл .tflock! 💪

Вы также можете проверить это в панели управления OVHcloud:

Terraform S3 state locking with OVHcloud Object Storage

Этот файл .tflock означает, что кто-то работает над этой инфраструктурой. После ответа «yes» на команду terraform apply ресурсы будут развёрнуты, появится состояние, а файл блокировки исчезнет:

$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# null_resource.test will be created
+ resource "null_resource" "test" {
+ id = (known after apply)
}

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

Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value: yes

null_resource.test: Creating...
null_resource.test: Creation complete after 0s [id=2048943220587414471]

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


$ ovhcloud cloud storage object object list terraform-state-3az
┌────────────────┬──────┐
│ key │ size │
├────────────────┼──────┤
│ my-app.tfstate │ 612 │
└────────────────┴──────┘
💡 Используйте опцию -o json или -o yaml, чтобы получить необработанный вывод со всей информацией

🎉

Почему эта функция блокировки состояний Terraform полезна?

Если пользователь выполняет команду terraform apply (не отвечая «yes»), а другой пользователь выполняет ту же команду, отобразится сообщение об ошибке:

$ terraform apply


│ Ошибка: Ошибка получения блокировки состояния

│ Сообщение об ошибке: ошибка операции S3: PutObject, код ответа https: 412, идентификатор запроса: tx7b439680a0104339a2fc7-xxxxxxxxxxxx, идентификатор хоста: tx7b439680a0104339a2fc7-xxxxxxxxxxxx, ошибка api
│ PreconditionFailed: По крайней мере одно из предварительных условий не выполнено
│ Информация о блокировке:
│ ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
│ Путь: terraform-state-3az/my-app.tfstate
│ Операция: OperationTypeApply
│ Кто: avache@xxxxxxxxxx
│ Версия: 1.14.9
│ Создана: 2026-06-09 13:09:05.562244 +0000 UTC
│ Информация:


│ Terraform получает блокировку состояния, чтобы защитить состояние от записи
│ несколькими пользователями одновременно. Пожалуйста, устраните указанную выше проблему и попробуйте
│ снова. Для большинства команд вы можете отключить блокировку с помощью флага "-lock=false",
│ но это не рекомендуется.

Эта ошибка ожидаема. Она означает, что другая операция Terraform/OpenTofu уже получила блокировку состояния, поэтому вторая операция не может одновременно изменять файл состояния. Пользователь должен подождать, пока первая операция завершится и файл блокировки будет освобождён, а затем повторить попытку. Хотя Terraform позволяет отключить блокировку с помощью -lock=false, это не рекомендуется, так как может привести к конкурентным изменениям состояния и потенциальному повреждению состояния.

Заключение

В этой записи блога мы рассмотрели один из случаев использования условных записей, но эта функция выходит далеко за его рамки. Поддержка условных записей не только помогает предотвратить случайные перезаписи, но и обеспечивает более безопасные конкурентные рабочие процессы, такие как блокировка состояния в Terraform/OpenTofu.

Terraform S3 state locking with OVHcloud Object Storage