Данный вопрос возник при миграции облачных ресурсов в Яндекс.Облако. Официальная документация, к сожалению, не даёт ответа на этот счёт, как и гуглёж. Однако, можно применить подход, который используется в другом облачном провайдере - AWS.
Для чего нужна блокировка состояний (state locking): когда с облаком работает более одного человека, необходимо предотвратить возможность одновременного изменения ресурсов разными людьми. Иначе есть вероятность, в лучшем случае, просто повредить state (а восстановление может занять довольно много времени), в худшем же - запороть продуктовый сервис. Подробнее можно прочесть в документации.
В AWS вопрос блокировок решается через таблицу DynamoDB. В Яндекс.Облаке есть аналогичный сервис - Yandex Managed Service for YBD (далее просто YDB).
Предполагается, что у нас уже создан создан бакет в Object Storage, и есть сервисный аккаунт с правами записи в этот бакет.
Назначим этому сервисному аккаунту роль для работы с YDB
yc resource-manager folder add-access-binding <folder-id> \
--role ydb.editor \
--subject serviceAccount:<service-account-id>
Теперь создадим базу данных:
yc ydb database create terraform-state-lock --serverless
Далее создадим таблицу. Для этого есть два пути:
через вэб-интерфейс:
1. в дашборде Managed Service for YDB
![](https://habrastorage.org/getpro/habr/upload_files/9b7/c67/86a/9b7c6786aff5f8c604f139ccca3aec77.png)
2. база "terraform-state-lock"
![](https://habrastorage.org/getpro/habr/upload_files/097/e45/011/097e450113d8058ebb4e2a057aad223f.png)
3. Навигация
![](https://habrastorage.org/getpro/habr/upload_files/035/a84/a4a/035a84a4aed528a4d92eea3c00ed9624.png)
4. Создать таблицу
![](https://habrastorage.org/getpro/habr/upload_files/2a3/8e1/941/2a38e19417dbe24dc47e9517057d345b.png)
5. Тип: документная, колонка "LockID" типа String которая будет ключем партицирования
![](https://habrastorage.org/getpro/habr/upload_files/185/26f/4d6/18526f4d6fd0c83ee340da0c06d44f86.png)
c помощью AWS CLI, указав Document API эндпоинт базы данных (посмотреть можно на главной странице базы. Имеет вид https://docapi.serverless.yandexcloud.net/ru-central1/<folder-id>/<database-id>)
aws dynamodb create-table \
--table-name terraform-state-lock \
--attribute-definitions \
AttributeName=LockID,AttributeType=N \
--key-schema \
AttributeName=LockID,KeyType=HASH \
--endpoint <document-api-endpoint>
Остаётся только обновить настройки terraform backend, добавив параметры:
dynamodb_endpoint = "<document-api-endpoint>"
dynamodb_table = "tettaform-state-lock"
И выполнить реконфигурацию:
terraform init -reconfigure
Теперь, пока кто-то выполняет операции записи в бэкенд (terraform apply/delete), все остальные будут получать ошибку вида:
terraform apply -target=module.test
╷
│ Error: Error acquiring the state lock
│
│ Error message: ConditionalCheckFailedException: Condition not satisfied
│ Lock Info:
│ ID: <...>
│ Path: <...>
│ Operation: OperationTypeApply
│ Who: <...>
│ Version: 1.3.7
│ Created: <...>
│ Info:
│
│
│ Terraform acquires a state lock to protect the state from being written
│ by multiple users at the same time. Please resolve the issue above and try
│ again. For most commands, you can disable locking with the "-lock=false"
│ flag, but this is not recommended.
На этом всё. Надеюсь, данную инструкцию многие найдут полезной.
Комментарии (3)
mrgreyves
23.01.2023 23:57+1Почему же?)
https://registry.terraform.io/providers/yandex-cloud/yandex/latest/docs/resources/storage_bucket
Яндекс вполне себе умеет создавать S3 через terraform. Еще можно посмотреть хранение стейт в том же самом Gitlab, выглядит не плохо =)
ZhilyaevDmitriy
Как по мне хранить стейт удобнее все же в S3 ведрах. А YC до сих не поддерживает создание s3 через terraform.
Спасибо за демонстрацию данного подхода.