Terraform で Error acquiring the state lock が出て apply も plan も進まない。ロックは state の同時書き換えを防ぐための仕組みなので、むやみに外すと state 破損のリスクがある。外す前に「本当に誰も実行していないか」を確認するのが正しい順序。
先に結論
- まずエラー文に含まれるロック ID と保持者情報(Who / Created)を控える
- CI や他の実行が終わっていることを確認してから
terraform force-unlock で外す - DynamoDB のロック行を直接消すのは、force-unlock が効かないときの最終手段
- 外した直後は
terraform plan で意図しない差分が出ていないか確認する - apply の途中で落ちた場合は、実リソースと state のズレも一緒に見る
ロックが残る典型パターン
- 実行中に Ctrl+C / ターミナルを閉じた、ノートPCがスリープした
- CI ジョブがタイムアウトで強制終了された
- ネットワーク断でクライアントだけ死に、ロック解放が走らなかった
- そもそも別の人・別の CI が今まさに実行中(これは外してはいけない)
外す前の確認
- CI の実行画面で、同じ環境のジョブが動いていないか確認する
- エラー文の
Lock Info(ID / Path / Who / Created)で、いつの・誰のロックか当たりを付ける terraform plan も読み取り用ロックを取るので、「plan すらロックエラー」自体は異常ではない
force-unlock の手順
ロック ID はエラー文の ID: の値をそのまま使う。確認プロンプトが出るので、対象を目視してから進める。
terraform force-unlock <LOCK_ID>
# Do you really want to force-unlock?
# yes と入力
-force オプションを付けると確認をスキップする。手動作業では原則付けない- 外した人が・いつ・なぜ外したかをチームに一言残すと、後の切り分けが楽になる
DynamoDB のロック行を消す話
S3 + DynamoDB バックエンドでは、ロックは DynamoDB テーブルの行として残る。force-unlock で外れない場合に限り、対象行(LockID が state パスと一致するもの)を慎重に削除する。実行中ジョブがある状態で消すと同時書き換えが起き得るので、ここでも「誰も実行していない」確認が前提になる。
外した後にやること
terraform plan を実行し、意図しない差分(作り直し・削除)が混ざっていないか見る- apply 途中終了だった場合は、実リソースが中途半端に作られていないかコンソール側でも確認する
- state のバックアップが取れる構成か確認する。S3 バックエンドならバージョニング有効化が定番
予防
- バックエンドはリモート(S3 + DynamoDB ロック等)に寄せ、ローカル state の運用をやめる
- CI 側で同時実行制御(concurrency)を入れ、同じ環境の apply が重ならないようにする
- 長時間 apply は分割を検討する。ロック保持時間が長いほど事故率が上がる
- 「ロックを外す手順と判断者」をチームの手順書に先に書いておく
ざっくりまとめ
- ロックは敵ではなく、state を守る仕組み。外す判断の前に実行者の不在確認
- 正規手順は force-unlock。DynamoDB 直接削除は最終手段
- 外した後の plan 確認までがワンセット
関連記事