terraform state rmは、リソースをステートから削除してTerraformの管理対象から外すコマンドです。実インフラは削除されませんが、次回のplan/apply挙動には強い影響が出ます。
本稿では、安全な実務手順、典型シナリオ、アドレス指定のコツ、destroy/state mv/moved/importとの違いを押さえ、Terraform公式ドキュメントの前提に沿って解説します。
terraform state rmは、現在のTerraformステートから指定のリソースインスタンスを削除します。実インフラは破壊されません。結果としてTerraformはそのリソースを「未管理」と見なし、同じアドレスの定義がHCLに残っていれば次回planで“新規作成”として扱います。
主な使いどころは、(1) 既存リソースをTerraform管理から外して手動運用へ移したい、(2) 手動で削除済みのリソースに対するステートのゴミを掃除したい、(3) モジュール再編や命名変更の前段として一時的に外す、などです。命名変更や場所の移動が目的なら、state mvやmovedブロックの方が安全で再現性が高い点に注意します。
基本操作のひな型
terraform state list
# => 管理対象のアドレスを確認
terraform state show aws_s3_bucket.logs
# => 状態詳細を確認
terraform state rm aws_s3_bucket.logs
# => ステートから除外(バケット自体は残る)state rmは強力です。安全に適用するには、事前のバックアップ、影響評価、HCL側の整合性調整が不可欠です。特に、HCL定義が残ったままstate rmすると、次のplanで“作成差分”が出てしまうため、意図しない複製作成につながります。
実務での推奨シーケンスは以下です。バックエンドがロックをサポートしている場合(例: S3+DynamoDBロック、Terraform Cloud/Enterprise)ではロックが自動で効きますが、併走applyを避ける運用を徹底してください。
手順の実行例(Bash)
# 1) ステートのバックアップ
terraform state pull > tfstate-$(date +%F-%H%M%S).bak
# 2) 対象アドレスの特定
terraform state list | grep aws_s3_bucket
terraform state show aws_s3_bucket.logs
# 3) HCLから当該resourceをコメントアウト/削除(VCSでコミット)
# 4) 現状同期(必要に応じて)
terraform plan -refresh-only
# 5) ステートから外す
terraform state rm aws_s3_bucket.logs
# 6) 意図した差分か確認
terraform plan手動削除の後始末: 実インフラを手動で削除済みなら、HCLからも該当resourceを削除し、最後にstate rmでステートの残骸を掃除します。HCLを残したままrmすると再作成が走るため目的と矛盾します。
一部リソースのみ手動運用へ移行: HCL定義を削除または条件分岐(count=0等)で作成対象外にしたうえでstate rmします。将来のapplyで再作成が起きないことを確認します。
モジュール再編/命名変更: 原則movedブロックかstate mvを使い、rmは使わない。やむを得ず外す場合は再インポートの計画を立てます。
for_each/モジュール配下の精密アドレス指定
# for_eachキーはクオートが必要
terraform state rm 'aws_subnet.public["public-1a"]'
# モジュール配下の特定インスタンス
terraform state rm 'module.network.aws_subnet.public["public-1a"]'
# 現在のworkspaceを確認
terraform workspace showstate rmの直後、HCLに同じリソース定義が残っているとTerraformは「ステートに無い=未作成」と判断します。planでは“作成”が提案され、applyで重複作成や命名衝突エラーが発生し得ます。
依存関係は基本的にHCLから再構築されるため、rmで依存の解決が壊れることは稀ですが、出力値や参照元に実体が無いとエラーや未知値拡散の原因になります。
state rm後の世界(概念フロー)
意図せず再作成になる例
# HCLにresource "aws_s3_bucket" "logs"が残ったまま
terraform state rm aws_s3_bucket.logs
terraform plan
# => + create aws_s3_bucket.logs (重複作成/命名衝突の可能性)アドレスはresource.type.name[インデックス or キー]、モジュール配下はmodule.path.resource...の形式です。誤指定は意図せぬ除外につながるため、必ずterraform state list/showで確認します。
命名変更やモジュール移動が目的の場合、Terraform 1.1以降はmovedブロックによる宣言的な状態移行が推奨です。計画時に旧→新アドレスへステートが自動移行され、再現性が高く、rmのような孤児化を避けられます。
movedブロック/state mv/importの書式例
# moved(HCL、Terraform 1.1+)
moved {
from = aws_s3_bucket.logs
to = module.logging.aws_s3_bucket.logs
}
# state mv(CLI)
terraform state mv aws_s3_bucket.logs module.logging.aws_s3_bucket.logs
# 既存を再アタッチ(import)
terraform import aws_s3_bucket.logs my-logs-bucket-namePro試験では「壊さず外す」「名前変更は何を使う」「既存の再アタッチ」の選択肢鑑別が頻出です。state rmは“管理対象から外すだけ”で、destroyは“実体破壊”、state mv/movedは“状態の移動”、importは“既存の取り込み”です。
refresh系はapply -refresh-onlyが現在の推奨。-targetは最小化のための緊急避難であり、恒常運用の推奨ではありません。
| コマンド/機能 | 実インフラへの影響 | ステートへの影響 | 主な用途 |
|---|---|---|---|
| terraform state rm | 削除なし(壊さない) | 指定アドレスを削除 | 管理対象から外す、ゴミ掃除 |
| terraform destroy (-target含む) | 実体を破壊 | 破壊に応じて削除 | 明示破棄、限定破壊は緊急時のみ |
| terraform state mv / moved{} | 壊さない | 旧→新アドレスへ移動 | 命名変更、モジュール移行 |
| terraform import | 壊さない | 既存実体を登録 | 手作り資産の取り込み |
| terraform apply -refresh-only | 壊さない | 読み取りで属性更新 | 状態同期・ドリフト検出 |
試験で問われやすいワンライナー
# "壊さず外す":
terraform state rm module.db.aws_db_instance.main
# "名前を変える/場所を変える":
terraform state mv aws_iam_role.app module.iam.aws_iam_role.app
# or HCLのmovedブロックで宣言的に
# "既存を取り込む":
terraform import aws_eip.web eipalloc-1234567890abcdef0Pro
問題 1
既存のS3バケットを今後は手動で運用したい。Terraformはそのバケットを今後管理せず、実体は削除しないことが要件。適切な手順はどれか?
正解: A
実体を残して管理対象から外すには、HCL定義を削除(または生成条件を外す)し、ステートからも除外(state rm)するのが正解。Dは次回planで再作成が走る。Bは実体を壊してしまう。Cは移動/再アタッチであり要件に合わない。
state rmで間違って除外した。元に戻す方法は?
最も安全なのはバックアップしたtfstateを用いて復元することです(terraform state pushは慎重に)。バックアップが無い場合、対象リソースがクラウド上に残っていれば、対応するHCL定義を用意してterraform importで再アタッチできます。
remote backendでも何か特別なフラグが必要?ロックはどうなる?
一般に追加フラグは不要です。バックエンドがロックをサポートしていれば(S3+DynamoDB、Terraform Cloud/Enterpriseなど)state rmも通常のplan/apply同様にロックが働きます。並行操作(別ターミナルでのapply等)は避けてください。
dataソースもstate rmの対象になる?
dataリソースはステートに現れることがありますが、計画時に再読込される性質です。通常はrmの必要はありません。どうしても消したい事情がある場合のみ、アドレスを正しく確認のうえ実施してください。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...