その不満は正当だ。Terraform 1.11.0でS3ネイティブロック(use_lockfile)が正式サポートとなり、DynamoDB依存なしにstateロックが実現できるようになった。同時にDynamoDBロック引数は非推奨(deprecated)となり、将来バージョンでの削除が予定されている。
この記事では、DynamoDBロックからS3ネイティブロックへの移行手順、安全な併用期間の設け方、そして移行後に発生しやすいロック競合の解消方法を実践的に解説する。
動作確認環境:Terraform 1.11.x / AWS provider 5.x / Ubuntu 24.04 LTS
この記事のポイント
・use_lockfileはTerraform v1.11でGA。.tflockファイルをS3条件付き書き込みで管理する
・dynamodb_table引数はdeprecated。移行期間中は両設定の同時有効化が可能
・移行はIAM権限追加→use_lockfile追加→動作確認→dynamodb_table削除の4段階で進める
・ロック競合は terraform force-unlock コマンドで解除できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜDynamoDB stateロックがS3ネイティブロックに置き換わるのか
Terraform S3バックエンドでDynamoDBを使ったstateロックは、2017年以降しばらくの間ベストプラクティスとされてきた。しかし実運用では常に2つの問題を抱えていた。1つ目は「S3とDynamoDBという異なるAWSサービスをセットで管理しなければならない」という複雑さだ。tfstateそのものはS3に置くのに、ロックのためだけにDynamoDBのプロビジョニング・IAM権限管理・コスト負担が発生する。
2つ目は「S3単体でロック相当の排他制御が技術的に実現できるはず」という長年の課題感だ。S3は2024年にConditional Writes(条件付き書き込み)機能をGAとしてリリースし、この課題解決の技術的基盤が整った。
Terraform 1.10でS3ネイティブロックが実験的に導入され、1.11.0(2025年2月リリース)でGA(一般提供)となった。これに伴い、S3バックエンドのDynamoDB関連引数(dynamodb_table・dynamodb_endpoint)は非推奨扱いとなっている。
DynamoDBロックとS3ネイティブロックの仕組みの違い
2つの方式はロック情報の格納先と競合検出の仕組みが根本的に異なる。DynamoDB方式
terraform applyが実行されると、指定したDynamoDBテーブルにロックアイテム(LockID = {バケット名}/{キー})をPutItemで書き込む。テーブルにすでにそのLockIDが存在する場合は、条件付き書き込みが失敗してロック競合エラーになる仕組みだ。
S3ネイティブ方式(use_lockfile = true)
terraform applyが実行されると、stateファイルのパスに.tflockを付加したファイル(例:path/to/terraform.tfstate.tflock)をS3に書き込む。このとき、HTTPリクエストヘッダーに
If-None-Match: * を付加することで「ファイルが存在しない場合のみ書き込む」という条件付き書き込みを実現している。すでに.tflockファイルが存在すると、S3から412 Precondition Failedが返り、ロック競合エラーになる。| 観点 | DynamoDB方式(旧) | S3ネイティブ(use_lockfile) |
|---|---|---|
| ロック格納場所 | DynamoDBテーブル | S3の.tflockファイル |
| 追加サービス | DynamoDB(別途必要) | 不要(S3のみ) |
| IAM権限(追加分) | dynamodb:GetItem/PutItem/DeleteItem | s3:GetObject/PutObject/DeleteObject(.tflock) |
| 競合検出方式 | DynamoDB条件付き書き込み | S3 If-None-Match ヘッダー |
| ステータス | 非推奨(deprecated) | GA(v1.11.0~) |
use_lockfileへの移行手順
移行は「IAM権限の追加」「use_lockfileの追加(dynamodb_tableとの併用)」「動作確認」「dynamodb_tableの削除」の4段階で進める。いきなりDynamoDB設定を削除するのではなく、併用期間を設けて安全に移行するのが重要だ。1. Terraformバージョンの確認とIAM権限の追加
まずTerraformが1.11以降であることを確認する。terraform version
Terraform v1.11.4 on linux_amd64
tfenv install 1.11.4 && tfenv use 1.11.4 で切り替えられる。次にIAMポリシーへ.tflockファイル操作の権限を追加する。use_lockfileを有効にすると、Terraformは.tflockファイルに対してGetObject・PutObject・DeleteObjectを実行する。既存のIAMポリシーに以下のStatementを追加する。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::your-tfstate-bucket/path/to/terraform.tfstate.tflock" } ] }
arn:aws:s3:::your-tfstate-bucket/* のままでも動作するが、最小権限の原則から.tflockサフィックスまで絞ることを推奨する。2. use_lockfile追加とdynamodb_tableとの併用設定
既存のbackend "s3"ブロックにuse_lockfile = true を追加する。この段階ではまだdynamodb_tableを残したままにする。両設定は同時に有効化できるため、移行期間中の二重ロックが可能だ。terraform { backend "s3" { bucket = "your-tfstate-bucket" key = "path/to/terraform.tfstate" region = "ap-northeast-1" encrypt = true # S3ネイティブロックを有効化(v1.11.0以降) use_lockfile = true # 移行期間中は残す(deprecated警告が出るが動作する) dynamodb_table = "your-lock-table" } }
terraform init -reconfigure
path/to/terraform.tfstate.tflock ファイルが作成されることをAWSコンソールまたはCLIで確認する。# plan実行中に別ターミナルで.tflockファイルの存在を確認 aws s3 ls s3://your-tfstate-bucket/path/to/terraform.tfstate.tflock
3. DynamoDB依存の完全削除
動作確認が完了したら、dynamodb_table行を削除してDynamoDB依存をゼロにする。terraform { backend "s3" { bucket = "your-tfstate-bucket" key = "path/to/terraform.tfstate" region = "ap-northeast-1" encrypt = true use_lockfile = true } }
DynamoDBテーブル自体はしばらくの間残しておき、問題がなければ削除する。テーブルの中身(LockIDアイテム)が空であることをAWSコンソールで確認してから削除するのが安全だ。
>> Terraform実践セミナーの詳細はこちら
ロック競合が発生したときの解消手順
S3ネイティブロックへの移行後、apply中にプロセスがkillされたり、ネットワーク断が発生したりすると.tflockファイルが残留してロック競合エラーになることがある。1. ロック競合エラーの確認
ロック競合時は以下のようなエラーが表示される。Error: Error acquiring the state lock Error message: ConditionalCheckFailedException: The conditional request failed Lock Info: ID: abc12345-6789-def0-1234-56789abcdef0 Path: path/to/terraform.tfstate Operation: OperationTypeApply Who: user@hostname Version: 1.11.4 Created: 2026-09-10 09:15:23.123456789 +0000 UTC
ID: 行の値がforce-unlockコマンドに必要なLOCK_IDだ。エラー出力をコピーしてIDを確保しておこう。2. terraform force-unlockコマンドによる解除
ロック競合を解除するにはterraform force-unlockコマンドを使う。terraform force-unlock abc12345-6789-def0-1234-56789abcdef0
yes を入力する。Do you really want to force-unlock? Terraform will remove the lock on the remote state. This will allow local Terraform commands to modify this state, even though it may be still be in use. Only 'yes' will be accepted to confirm. Enter a value: yes Terraform state has been successfully unlocked! The state has been unlocked, and Terraform commands should now be able to run successfully.
3. .tflockファイルが残留した場合の手動削除
force-unlockが効かない場合や、何らかの理由で.tflockファイルが手動削除しか手段がない場合は、AWS CLIで直接削除できる。# .tflockファイルが存在するか確認 aws s3 ls s3://your-tfstate-bucket/path/to/terraform.tfstate.tflock # ファイルを削除 aws s3 rm s3://your-tfstate-bucket/path/to/terraform.tfstate.tflock
terraform plan でstateの整合性を確認するのが望ましい。バージョニング有効バケットでの.tflockファイル管理
tfstateバケットにS3バージョニングを有効にしている場合(推奨設定)、.tflockファイルが作成・削除されるたびに旧バージョンがS3上に蓄積する。apply頻度が高い環境では数百件のバージョンが溜まり、ストレージコストの増加と誤認識の原因になる。S3ライフサイクルポリシーで.tflockの旧バージョンを自動削除する設定をTerraformで管理する例を示す。
resource "aws_s3_bucket_lifecycle_configuration" "tfstate" { bucket = aws_s3_bucket.tfstate.id rule { id = "delete-old-lockfile-versions" status = "Enabled" filter { prefix = "" } noncurrent_version_expiration { noncurrent_days = 7 newer_noncurrent_versions = 5 } } }
noncurrent_days = 7 は7日経過した旧バージョンを削除する設定、newer_noncurrent_versions = 5 は常に最新5バージョンを保持する設定だ。stateファイル本体の旧バージョンも同じルールで削除されるため、バケット全体での設計が必要になる。.tflockファイルのみを対象にするには filter { prefix = ".tflock" } と書くこともできるが、S3のキー末尾一致ではなく前方一致のため、通常のtfstateキー構成では機能しない点に注意が必要だ。実用上はバケット全体にライフサイクルを設定しつつ、stateファイル本体の保持日数を長く設定する分離ルールで管理するのが現実的だ。本記事のまとめ
| やりたいこと | コマンド・設定 |
|---|---|
| S3ネイティブロックを有効化 | backend "s3" { use_lockfile = true } |
| Terraformバージョンを確認 | terraform version |
| バックエンド設定を再初期化 | terraform init -reconfigure |
| .tflockファイルの存在を確認 | aws s3 ls s3://bucket/path/to/key.tfstate.tflock |
| ロック競合を解除 | terraform force-unlock <LOCK_ID> |
| .tflockファイルを手動削除 | aws s3 rm s3://bucket/path/to/key.tfstate.tflock |
stateロックの設計思想や、複数チームでtfstateを共有する際の設計については、Terraform実践セミナーでさらに詳しく解説している。
>> Terraform実践セミナーの詳細はこちら
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:TerraformでVPCエンドポイントを一括定義する方法|インターフェース型のサブネット配置とプライベートDNS有効化の実装
- この記事の属するカテゴリ:Terraformへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます