• システム開発に関わる内容をざっくりと書いていく

Terraform state lock の外し方と注意点(force-unlock)

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 確認までがワンセット

関連記事