TerraformのstateロックをDynamoDBからS3ネイティブロックへ移行する判断|use_lockfileの併用期間とロック競合の解消

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Terraform > TerraformのstateロックをDynamoDBからS3ネイティブロックへ移行する判断|use_lockfileの併用期間とロック競合の解消
「S3バックエンドでstateを管理しているのに、ロックのためだけにDynamoDBテーブルを別途維持するのは無駄じゃないか」と感じたことはないだろうか。

その不満は正当だ。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 コマンドで解除できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜ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

1.11未満の場合はアップグレードが必要だ。tfenvを使っている場合は 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を実行してバックエンド設定を反映させる。

terraform init -reconfigure

terraform planを実行し、S3バケット上に path/to/terraform.tfstate.tflock ファイルが作成されることをAWSコンソールまたはCLIで確認する。

# plan実行中に別ターミナルで.tflockファイルの存在を確認 aws s3 ls s3://your-tfstate-bucket/path/to/terraform.tfstate.tflock

plan完了後にファイルが自動削除されることも確認しておこう。数回のplan/applyを通して問題がなければ次のステップへ進む。

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 } }

再度terraform init -reconfigureを実行して設定を反映する。この段階でTerraformから「DynamoDB設定が削除された」という旨のメッセージが出なければ問題ない。

DynamoDBテーブル自体はしばらくの間残しておき、問題がなければ削除する。テーブルの中身(LockIDアイテム)が空であることをAWSコンソールで確認してから削除するのが安全だ。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、TerraformのDynamoDBロック移行からstate設計まで、実務で即使えるスキルを習得できるセミナーを開催しています。
>> 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.

force-unlockは「本当に誰もapplyしていない」ことを確認してから実行すること。実行中のapplyが別プロセスで走っている状態でforce-unlockすると、stateが破損するリスクがある。

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

削除前に「そのロックを取得したプロセスが完全に停止していること」を必ず確認すること。進行中のapplyプロセスを強制終了して.tflockだけ消した場合、stateが中途半端な状態になっている可能性があるため、削除後は 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
DynamoDBロックからS3ネイティブロックへの移行は、Terraform 1.11以降を使っているならば今すぐ検討すべき変更だ。アーキテクチャがシンプルになり、IAM権限管理の範囲もS3に一本化できる。移行は本記事の4段階手順に沿って進めれば、ダウンタイムなしに安全に完了できる。

stateロックの設計思想や、複数チームでtfstateを共有する際の設計については、Terraform実践セミナーでさらに詳しく解説している。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、S3ネイティブロックへの移行からチーム開発でのstate設計まで、実務で即使えるスキルを習得できるセミナーを開催しています。
>> Terraform実践セミナーの詳細はこちら

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。