更新: 2026年03月 · 12 分で読める · 5,950 文字
Terraform stateが壊れた時の復旧手順|5つの実践的な対処法
Terraform stateファイルが壊れると、インフラストラクチャの管理状態が不整合になり、デプロイに失敗する危険があります。本記事では、実際に発生しやすい破損パターンと、それぞれの復旧手順を段階的に解説します。バックアップから復元する方法から、部分的な状態修正まで、すぐに使える対処法を5つ紹介します。
Terraform stateが壊れる主な原因
stateファイルの破損は、以下のようなシナリオで発生します。復旧方法を選ぶ前に、原因を特定することが重要です。
1. ファイルの同時編集による競合
複数の開発者が同時にterraform applyを実行すると、stateファイルが中途半端な状態で保存されることがあります。特にローカルストレージを使用している場合、ロック機構がないため危険性が高まります。
2. 不完全なアップロード/ダウンロード
ネットワーク接続が不安定な環境でS3やTerraform Cloudに対してstate操作を行うと、ファイルが途中で切断され、JSONフォーマットが破損することがあります。
3. 手動によるstateファイル編集の失敗
terraform state rmやjqコマンドでstateを直接編集する際、JSONの構文エラーやネストの誤りが発生しやすいです。
4. ストレージの障害
S3のデータ破損やディスク障害により、保存されたstateファイル自体が読み込み不可能になる場合があります。
復旧前の重要な確認事項
復旧作業を開始する前に、必ず以下を確認してください。
バックアップの有無を確認する
まず最初に、バックアップが存在するかを確認します。定期的にバックアップを取っていれば、復旧は簡単です。
# S3のバージョニング機能でバックアップを確認
aws s3api list-object-versions --bucket your-bucket-name --prefix terraform.tfstate
# Terraform Cloudの場合、UIから過去のstate履歴を確認可能
ローカルの.terraform/terraform.tfstateファイルをチェック
既にいくつかのリソースをデプロイしている場合、ローカル実行環境の古いstateコピーが残っている可能性があります。
# ローカルの古いstate確認
ls -la .terraform/terraform.tfstate*
ls -la terraform.tfstate*
復旧方法1: バックアップからの復元(最も推奨)
バックアップが存在する場合、これが最も安全で確実な復旧方法です。
S3バックアップからの復元手順
# ステップ1: 現在の壊れたstateをバックアップ
cp terraform.tfstate terraform.tfstate.broken
# ステップ2: S3から最後の正常なバージョンを取得
aws s3 cp s3://your-bucket-name/terraform.tfstate.backup ./terraform.tfstate
# ステップ3: 復元したstateの整合性を確認
terraform state list
# ステップ4: プランを実行して差分を確認
terraform plan
Terraform Cloudでの復元
Terraform Cloudを使用している場合、Web UIから状態を直接復元できます。
# Terraform Cloudの履歴APIで過去のstateを取得
curl -H "Authorization: Bearer $TF_API_TOKEN" \
https://app.terraform.io/api/v2/workspaces/your-workspace/state-versions
# 特定のバージョンを復元
terraform state pull > current.state
# UIから以前のバージョンを"Current"に設定
復旧方法2: JSONファイルの構文エラーを修正
stateファイルが部分的に破損しており、JSONの構文エラーのみの場合、修正可能です。
破損箇所を特定する
# JSONの構文検証
python3 -m json.tool terraform.tfstate > /dev/null
# または
jq . terraform.tfstate > /dev/null
# エラー位置を確認
cat terraform.tfstate | jq . 2>&1 | head -20
よくある破損パターンと修正方法
# パターン1: 末尾の括弧や波括弧が不完全な場合
# 修正前: { "version": 4, "terraform_version": "1.0",
# 修正後: { "version": 4, "terraform_version": "1.0" }
# パターン2: ダブルクォートが閉じられていない
# jqで自動修正を試みる
jq . terraform.tfstate 2>/dev/null || echo "修正不可能"
# パターン3: 不正なエスケープシーケンス
# テキストエディタで手動確認・修正
sed -i 's/\\//g' terraform.tfstate
修正後の検証
# 構文確認後、stateが読み込み可能かテスト
terraform state list
# もしエラーが出た場合、以下でstate内容を表示
terraform state show
復旧方法3: 部分的な状態の再構築
一部のリソースだけが不整合の場合、該当リソースのみ状態を削除して再度importできます。
破損したリソースを特定する
# 現在のstate内のすべてのリソースを表示
terraform state list
# 特定のリソースの詳細情報を確認
terraform state show aws_instance.example
# JSON形式で表示(より詳細)
terraform state show -json aws_instance.example
問題のあるリソースを削除して再importする
# ステップ1: stateから特定リソースを削除
terraform state rm aws_instance.example
# ステップ2: Terraformコード(.tf)には定義が残ったまま
# ステップ3: 実際のAWSリソースIDを確認
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId'
# ステップ4: リソースをstateに再度追加(import)
terraform import aws_instance.example i-1234567890abcdef0
# ステップ5: planで差分を確認
terraform plan
一括importの自動化スクリプト
#!/bin/bash
# 複数リソースの一括import
RESOURCES=(
"aws_instance.web:i-1234567890abcdef0"
"aws_instance.db:i-0987654321fedcba0"
"aws_security_group.main:sg-12345678"
)
for resource in "${RESOURCES[@]}"; do
tf_path="${resource%%:*}"
aws_id="${resource##*:}"
echo "Importing $tf_path with ID $aws_id"
terraform import "$tf_path" "$aws_id"
if [ $? -ne 0 ]; then
echo "Failed to import $tf_path"
exit 1
fi
done
echo "All imports completed"
terraform plan
復旧方法4: リモートstateをリセット
S3やTerraform Cloudのリモートstateが完全に破損している場合、リセットして再構築する方法があります。
S3リモートstateのリセット
# ステップ1: バックエンド設定を確認
cat backend.tf
# ステップ2: 現在のlocal stateに切り替え(一時的)
terraform init -migrate-state
# プロンプトで "yes" を入力
# ステップ3: S3の破損したstateファイルを削除
aws s3 rm s3://your-bucket-name/terraform.tfstate
aws s3 rm s3://your-bucket-name/terraform.tfstate.backup
# ステップ4: 新しいlocal stateから全リソースをimport
# importコマンドで既存リソースを再度登録
# ステップ5: 再度リモートバックエンドに切り替え
terraform init
# プロンプトで "yes" を入力してlocal stateをS3にアップロード
Terraform Cloudでのロック解除とリセット
# Terraform Cloudが「ロック状態」で動けない場合
terraform force-unlock LOCK_ID
# ロックIDを確認する方法
curl -H "Authorization: Bearer $TF_API_TOKEN" \
https://app.terraform.io/api/v2/workspaces/your-workspace/state-locks
復旧方法5: 新しいstateから出発する
既存stateが完全に復旧不可能な場合、既存リソースを全てimportして新しいstateを構築する方法があります。これは時間がかかりますが、完全な再スタートが可能です。
既存リソースの一覧取得と自動import
#!/bin/bash
# AWS EC2インスタンスをすべてimportするスクリプト例
# 既存インスタンス一覧を取得
INSTANCES=$(aws ec2 describe-instances \
--query 'Reservations[].Instances[].[InstanceId,Tags[?Key==`Name`].Value|[0]]' \
--output text)
# 各インスタンスをimport
echo "$INSTANCES" | while read instance_id instance_name; do
if [ -z "$instance_id" ]; then
continue
fi
# Terraform設定に リソース定義を追加
cat >> main.tf << EOF
resource "aws_instance" "imported_${instance_id}" {
# 既存リソースの設定をここに記述
}
EOF
# importを実行
terraform import aws_instance.imported_${instance_id} $instance_id
done
importしたリソースの設定を確認
# importしたリソースの詳細情報を取得
terraform state show aws_instance.imported_i1234567890abcdef0
# JSON形式で全リソースを確認
terraform state pull | jq '.resources[].instances[0].attributes' | head -50
今後の破損を防ぐための対策
定期的なバックアップ設定
# S3バージョニングを有効化
aws s3api put-bucket-versioning \
--bucket your-bucket-name \
--versioning-configuration Status=Enabled
# Terraformで使用するS3バックアップポリシー
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
# 定期的なバックアップをCron設定
0 2 * * * aws s3 cp s3://your-bucket-name/terraform.tfstate s3://your-bucket-name/backups/terraform.tfstate.$(date +\%Y\%m\%d)
stateファイルのロック機構を有効化
# DynamoTableを使用したstate locking
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
# backend設定で dynamodb_tableを指定
terraform {
backend "s3" {
bucket = "your-bucket-name"
key = "terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
stateファイルの暗号化設定
# S3での暗号化設定
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# または KMS暗号化を使用(より安全)
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state_kms" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.terraform.arn
}
}
}
よくある質問
Q1: terraform state pullとpushの違いは何ですか?
terraform state pullはリモートstateをローカ
おすすめDevOpsリソース
- Docker Documentation Official Docker and Docker Compose reference.
- Kubernetes Docs Official K8s documentation. Great for understanding concepts.
- GitHub Actions Docs Official guide for CI/CD workflows.