tfstateを手動編集する危険性とやむを得ない場合の手順

1. 概要

  • tfstateを手動編集してはいけない理由
  • やむを得ない場合の安全な手順
  • stateを壊してしまった場合の復旧方法
  • 手動編集の代替手段(terraform stateコマンド)

tfstateファイルはTerraformがリソースの状態を追跡するためのデータベースです。JSONフォーマットで人間が読める形式ですが、直接編集することは強く非推奨です。 この記事では、なぜ危険なのか、どうしても編集しなければならない場合の安全な手順を解説します。


2. 手動編集が危険な理由

stateの整合性が崩れる

tfstateにはリソースの属性値・依存関係・メタデータが記録されています。1箇所の変更が別のリソースの参照を壊す可能性があります。

チームメンバーが混乱する

チームで共有しているS3バックエンドのstateを手動編集した場合、他のメンバーがplanを実行すると予期しない変更が表示されます。

バージョン管理されない

stateの変更はGitに記録されません。誰がいつどんな変更をしたかのトレーサビリティが失われます。


3. 代替手段(まずこれを使う)

手動編集の代わりに、まず以下のコマンドを検討してください。

# リソースのリネーム・移動
$ terraform state mv aws_instance.old aws_instance.new

# stateからリソースを除外(AWSリソースは残る)
$ terraform state rm aws_instance.legacy

# 既存リソースをstateに取り込む
$ terraform import aws_instance.web i-1234567890abcdef0

これらのコマンドは安全にstateを操作するための公式手段です。


4. やむを得ず手動編集する場合の手順

状況: APIが壊れたstateのみを修正する場合など、コマンドでは対応できないケース。

ステップ1: バックアップを取る

# リモートstateをローカルに取得してバックアップ
$ terraform state pull > backup_$(date +%Y%m%d_%H%M%S).tfstate

# バックアップを安全な場所にコピー
$ cp backup_20260606_120000.tfstate ~/Desktop/tfstate_backup_20260606.tfstate

ステップ2: ロックを確認する(S3バックエンドの場合)

# DynamoDBのロックテーブルを確認して、他のメンバーが作業していないことを確認
$ aws dynamodb scan --table-name terraform-locks --region ap-northeast-1

ステップ3: JSONを編集する(最小限の変更に留める)

# バックアップコピーを編集
$ cp backup_20260606_120000.tfstate modified.tfstate
$ vim modified.tfstate  # または任意のエディタ

ステップ4: シリアルバージョンを更新する

{
  "version": 4,
  "terraform_version": "1.9.0",
  "serial": 42,   ← ここを +1 する(例: 43に変更)
  "lineage": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "outputs": {},
  "resources": [...]
}

serialは変更のたびに増加するカウンターです。手動編集時も必ず1増やす必要があります。

ステップ5: pushする前にplanで確認

# 編集後のstateを一時的にローカルで使ってplanを確認
$ terraform plan -state=modified.tfstate

# 問題なければpush
$ terraform state push modified.tfstate

ステップ6: チームに共有

編集内容・理由・実行者を必ずチームのSlack/Confluenceなどに記録してください。


5. stateを壊してしまった場合の復旧

# S3バックエンドでは過去バージョンが保存されている(バージョニングが有効な場合)
$ aws s3api list-object-versions \
    --bucket my-tfstate-bucket \
    --prefix dev/terraform.tfstate

# 特定バージョンを復元
$ aws s3api copy-object \
    --bucket my-tfstate-bucket \
    --copy-source "my-tfstate-bucket/dev/terraform.tfstate?versionId=xxxxxx" \
    --key "dev/terraform.tfstate"

S3バックエンドでは必ずバージョニングを有効にしておくことで、誤った変更を元に戻せます。

# バックエンドの設定例(バージョニング有効化)
resource "aws_s3_bucket" "tfstate" {
  bucket = "my-tfstate-bucket"

  tags = {
    Name        = "terraform-state"
    Environment = "shared"
    ManagedBy   = "terraform"
  }
}

resource "aws_s3_bucket_versioning" "tfstate" {
  bucket = aws_s3_bucket.tfstate.id

  versioning_configuration {
    status = "Enabled"  # 必ず有効化
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "tfstate" {
  bucket = aws_s3_bucket.tfstate.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

6. 関連記事


7. まとめ

  • tfstateの手動編集は原則禁止。まずterraform state mv/rm/importで解決できないか検討する
  • やむを得ず編集する場合は必ずstate pullでバックアップを取ってから行う
  • serialを必ず1増やすこと。忘れるとstateの競合が発生する
  • S3バックエンドではバージョニングを有効化して復元可能な状態を保つ
  • 手動編集した場合は必ずチームに内容・理由・実行者を共有する

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/state