TL;DR: 応急処置
**「Error acquiring the state lock」(状態ロックの取得エラー)**というメッセージが表示された場合、通常は別のTerraform操作が実行中であるか、以前の操作がクラッシュして古いロックが残されていることを意味します。緊急時に迅速に解決するには、特に他の正当な操作が実行されていないと確信できる場合、force-unlock(強制ロック解除)できることがあります。エラーメッセージからロックIDを取得し、以下を実行します。
terraform force-unlock <LOCK_ID>
force-unlockを使用する際は、別のプロセスが実際にロックを保持している場合に誤って使用すると状態が破損する可能性があるため、細心の注意を払ってください。
詳細な根本原因
Terraformは、複数の操作が同時に状態ファイルを破損させるのを防ぐために、状態ロックを使用します。terraform plan、apply、またはdestroyを実行すると、Terraformは状態のロックを取得しようとします。このメカニズムにより、一度に1つのユーザーまたはプロセスのみがインフラストラクチャを変更できることが保証されます。AWS S3のようなリモートバックエンドでは、これらのロックを管理するために、通常DynamoDBのような別のサービスが使用されます。
**「Error acquiring the state lock」(状態ロックの取得エラー)**メッセージは、いくつかの理由で表示されます。
- 同時実行: 他の誰か(または別の自動化パイプライン)が、同じ状態ファイルに対してTerraformコマンドを同時に実行しています。
- 操作のクラッシュ: 以前のTerraformコマンドがクラッシュ、ネットワーク中断、または手動終了(例: Ctrl+C)により実行中に失敗しました。ロックが適切に解放されませんでした。
- ネットワークの問題: Terraformがロックメカニズム(例: DynamoDB)と通信できず、ロックを取得または検証できません。
- 権限の問題: Terraformを実行しているIAMユーザーまたはロールが、DynamoDBロックテーブルまたはS3ステートバケットとやり取りするために必要な権限を持っていません。
要するに、Terraformは続行を拒否することで、インフラストラクチャの状態を潜在的な損傷から保護するという役割を果たしています。私たちの仕事は、なぜTerraformがロックを取得できないと考えているのかを突き止めることです。
修正アプローチ
アプローチ1: terraform force-unlockを使用する(注意!)
これは古いロックを解決する最も迅速な方法ですが、リスクが伴います。他の正当なTerraform操作がアクティブではないと絶対に確信できる場合にのみ使用してください。
-
ロックIDの特定: エラーメッセージ自体にロックIDが含まれていることがほとんどです。UUIDのような形式(例:
0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d)をしています。
Error: Error acquiring the state lock
Error message: Failed to get lock: An error occurred (ConditionalCheckFailedException) when calling the PutItem operation: The conditional request failed Lock Info: ID: a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d Path: some-s3-bucket/path/to/terraform.tfstate Operation: OperationTypeApply Who: user@hostname Version: 1.0.0 Created: 2023-10-27 08:00:00 +0000 UTC Info:
Terraform acquires a state lock to protect the state from being simultaneously updated by multiple working copies. If you believe this lock is erroneous, you may use the "terraform force-unlock" command to release it.
-
**`terraform force-unlock`を実行する:**
```bash
terraform force-unlock a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d
Terraformは確認を求めます。続行するにはyesと入力してください。
アプローチ2: アクティブなTerraformプロセスを確認する
force-unlock(強制ロック解除)を行う前に、特に自動化された環境や他のチームメンバーが作業している可能性がある場合は、他のTerraformプロセスが実際に実行されていないことを確認するのが賢明です。
-
ローカル: 自身のマシンの実行中のプロセスを確認します。Linux/macOSの場合:
ps aux | grep terraform
残っている`terraform apply`または`terraform plan`プロセスを探します。見つかった場合は`kill <PID>`を使用して終了させます。
-
**CI/CDパイプライン:** このエラーがCI/CDジョブからのものである場合、パイプラインのログとステータスを確認してください。手動でキャンセルまたは再起動が必要なスタックしたジョブがある可能性があります。
### アプローチ3: DynamoDBロックテーブルの検証(AWS S3バックエンドの場合)
リモートステートにAWS S3を使用している場合、TerraformはロックのためにDynamoDBテーブルを使用します。このテーブルを検査することで、何がロックを保持しているかを明らかにできます。
-
**DynamoDBへのアクセス:** AWS Management Consoleにアクセスし、DynamoDBに移動して、Terraformがロックに使用しているテーブル(通常、バックエンドで設定されている`terraform-lock`などの名前)を見つけます。テーブル内の項目を確認します。
または、AWS CLIを使用します:
```bash
aws dynamodb scan --table-name your-terraform-lock-table --query 'Items[*].LockID.S'
これにより、アクティブなロックIDがリストされます。それらをエラーメッセージのIDと比較してください。
-
古いロックエントリの手動削除(極めて注意!): DynamoDBでエラーメッセージに対応するロックエントリが見つかり、それが確実に古い(つまり、実際のTerraform操作がアクティブではない)と確信できる場合は、DynamoDBコンソールまたはAWS CLIを使用して直接削除できます。これは
terraform force-unlockが本質的に行っていることです。
aws dynamodb delete-item
--table-name your-terraform-lock-table
--key '{"LockID": {"S": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d"}}'
影響を完全に理解している場合にのみ削除してください。アクティブなロックを削除すると、データ破損につながる可能性があります。
### アプローチ4: ネットワーク接続とIAM権限
より根本的な問題として、Terraformがロックをチェックすることさえ妨げられている可能性があります。
-
**ネットワーク接続の確認:** Terraformを実行しているマシンが、AWS S3およびDynamoDBエンドポイントへのネットワークアクセスを持っていることを確認します。これには、セキュリティグループ、NACL、VPCエンドポイント、またはプロキシ設定の確認が含まれます。
-
**IAM権限の検証:** Terraformを実行するIAMエンティティ(ユーザーまたはロール)には、S3バケット(`s3:GetObject`、`s3:PutObject`、`s3:DeleteObject`、`s3:ListBucket`)およびDynamoDBロックテーブル(`dynamodb:GetItem`、`dynamodb:PutItem`、`dynamodb:DeleteItem`、`dynamodb:DescribeTable`)に対する特定の権限が必要です。ここで権限が不足していると、ステートのロックとロック解除がブロックされます。
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::your-terraform-state-bucket",
"arn:aws:s3:::your-terraform-state-bucket/*"
]
},
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:DeleteItem",
"dynamodb:DescribeTable"
],
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT_ID>:table/your-terraform-lock-table"
}
]
}
アタッチされたポリシーを確認し、必要なアクセス権が付与されていることを確認してください。aws sts get-caller-identityを使用して、Terraformが使用しているIAMエンティティを確認します。
検証ステップ
修正を試みた後、ロックの問題が解決され、Terraformが正常に動作できることを検証することが重要です。
-
terraform planの実行: 簡単なプランを実行します。ロックが正常に解放または取得された場合、このコマンドはロックエラーなしで実行されるはずです。
terraform plan
-
**`terraform apply -auto-approve -refresh=false`の実行(安全な場合):** 非本番環境でより徹底的なチェックを行う場合、またはプランが本当にno-opである場合は、クイックapplyを試みることができます。`-refresh=false`フラグは、状態をリフレッシュするのではなく、ロックメカニズムをテストしたい場合に処理を高速化できます。
```bash
terraform apply -auto-approve -refresh=false
- DynamoDBの監視: DynamoDBテーブルを監視している場合、
planまたはapplyの開始時にロック項目が表示され、操作が正常に完了すると消えるはずです。

