既存のクラウド資産をTerraform管理下に移す最初の一歩が terraform import です。import は“状態に写し込む”操作であり、設定ファイルそのものは自動生成しません。したがって、状態と設定の整合性をどう確保するかが肝になります。
本記事では、Terraform 1.5以降で推奨される import block と、引き続き使える従来の terraform import CLI の両方を、安全かつ試験対策の観点で比較・解説します。
terraform import は既存リソースをTerraformの状態(tfstate)へ関連付ける操作です。これにより、そのリソースは以後terraform plan/applyの対象になります。ただしimport自体は設定(HCL)を生成せず、設定は手で用意する必要があります。
取り込みは「正しいアドレスへ、正しいIDで」行うことが全てです。対象リソースのID形式はリソースタイプごとに異なるため、プロバイダの公式ドキュメントで確認してください。また、認証情報とプロバイダ設定が事前に正しく構成されていることが前提です。
最小限のリソース定義の例(取り込み対象)
resource "aws_s3_bucket" "example" {
bucket = "my-existing-bucket"
# 実環境の属性に合わせて必要最小限から開始
}importは“どこに紐づけるか”が重要です。Terraformのリソースアドレスは、モジュール階層・種類・名前・インデックス(count/for_each)で構成されます。誤ったアドレスに取り込むと、のちにリネームや再取り込みが発生し、リスクや手戻りにつながります。
dataソースは取り込み対象外です。importできるのはmanaged resourceのみです。モジュール配下へ取り込む場合は module.<name> の階層を含むフルアドレスを使います。
代表的なアドレス指定例
# 単一
# terraform import aws_instance.web i-0123456789abcdef0
# countの0番目
# terraform import aws_instance.web[0] i-0aaa...
# for_eachのkey=blue
# terraform import aws_instance.web["blue"] i-0bbb...
# モジュール配下
# terraform import module.app.aws_instance.web i-0ccc...Terraform 1.5以降は、設定にimport blockを宣言してからplan/applyで取り込むワークフローが推奨です。コードとしてレビューでき、再現性が高いのが利点です。import blockは to と id を指定します。to には取り込み先のリソースアドレス、id には既存リソースのIDを与えます。
import blockと対応するresourceブロックの双方が設定内にあることが前提です。planで差分を確認し、applyで状態に取り込みます。その後、必要に応じて属性を明示設定してドリフトを減らします。
import block方式の流れ
import blockと対応リソースの例(S3バケット)
resource "aws_s3_bucket" "example" {
bucket = "my-existing-bucket"
}
import {
to = aws_s3_bucket.example
id = "my-existing-bucket"
}
# 実行
# terraform init
# terraform plan # importされる提案を確認
# terraform apply # 状態へ取り込み従来の terraform import ADDRESS ID も引き続き利用可能です。こちらは即時に状態へ書き込みます。取り込み後に設定がない(または属性不一致がある)と、次のplanで差分が多く出るため、取り込み前後で設定を整える運用が必要です。
モジュールやfor_each/countのアドレス指定に注意してください。誤ったアドレスへ取り込んだ場合は terraform state mv で移動できますが、計画的に行う方が安全です。
| 観点 | import block (1.5+) | terraform import CLI | 試験メモ |
|---|---|---|---|
| 再現性・監査性 | コードに残るため高い | 都度コマンド。履歴は残りにくい | コードで管理できる方式を選べるかを理解 |
| 実行タイミング | plan/applyの一部として実施 | 即時state更新 | planに現れるか否かが違い |
| レビュー性 | PRでレビュー可能 | 口頭・手順書ベースになりがち | チーム運用の観点が問われやすい |
| 設定生成 | 自動生成はしない | 自動生成はしない | importは“設定を作らない”が定番出題 |
| ロールバック性 | plan差分で安全に適用可 | 誤実行の巻き戻しに手間 | state mv/rmコマンドの用途も把握 |
CLI方式の例とリカバリ操作
# 取り込み(IAMロール名で識別する例)
terraform import aws_iam_role.app_role app-role
# モジュール配下
terraform import module.app.aws_s3_bucket.logs my-log-bucket
# 誤取り込みを移動
terraform state mv aws_s3_bucket.wrong module.app.aws_s3_bucket.logs
# 誤取り込みを削除(リソース自体は削除されない)
terraform state rm aws_s3_bucket.wrongimport直後にplanで大きな差分が出る場合、設定が実体を十分に表現できていません。強いデフォルトやcomputed属性に依存せず、実環境に合わせて明示設定するほどドリフトは減ります。特に暗号化、ライフサイクル、タグ、削除保護などは明示的に書きましょう。
count/for_eachやモジュール階層の導入は、取り込み前に決めておくと後の移動が減らせます。名前変更の必要が出た場合は movedブロックで安全にアドレスを移譲できます。大規模移行は一括ではなく、重要度の低いリソースから段階的に進め、ステートのバックアップを徹底します。
for_each取り込みとmovedブロックの例
# for_eachの例(タグ値ごとにキー管理)
resource "aws_kms_key" "keys" {
for_each = toset(["blue", "green"])
description = "key-${each.key}"
}
import {
to = aws_kms_key.keys["blue"]
id = "1234abcd-...-blue-key-id"
}
import {
to = aws_kms_key.keys["green"]
id = "5678efgh-...-green-key-id"
}
# アドレス変更の安全な移行
moved {
from = aws_kms_key.keys["blue"]
to = module.security.aws_kms_key.keys["blue"]
}試験では「importは状態に取り込むだけで設定を作らない」「正しいリソースアドレスとIDを指定」「dataソースは対象外」「モジュール/for_each/countの扱い」「import blockと従来CLIの違い」が頻出です。apply前にplanで輸入提案が見えるのがimport block方式の特徴です。
運用では、取り込み後に terraform state show で状態を確認し、設定との差分を埋めることが重要です。誤取り込み時の state mv/rm、名前変更時の moved ブロック、状態のバックアップとロック、ワークスペースの使い分けを押さえておきましょう。
よく使う確認・調整コマンド
# 状態の中身を確認
terraform state list
terraform state show aws_s3_bucket.example
# ステートの安全な移動
terraform state mv aws_s3_bucket.old aws_s3_bucket.new
# ワークスペース切替
terraform workspace select stagingAssociate / Pro
問題 1
チームはTerraform 1.5+を使用し、既存のS3バケットを安全にTerraform管理下へ移したい。レビュー可能で再現性の高い手順を選びたい。最も適切なアプローチはどれか。
正解: A
1.5+ではimport blockをコードとして管理し、plan/applyで取り込むフローが推奨。レビュー性・再現性が高い。CLIのterraform importも可能だが、即時に状態が変わりレビューしづらい。削除再作成は不要かつリスクが高い。dataソースはimport対象外。
importは設定ファイルを自動生成しますか?
いいえ。importは既存リソースをtfstateへ関連付けるだけで、HCLの生成はしません。取り込み後はterraform state showで確認し、必要な属性を設定へ追記して差分を減らします。
for_eachやcountのリソースはどのように取り込みますか?
各要素を個別のアドレスで取り込みます。countなら [index]、for_eachなら ["key"] を使います。import blockを複数記述するか、CLIで要素ごとに terraform import ADDRESS ID を実行します。
誤って別のアドレスに取り込みました。元に戻せますか?
対象リソースを削除せずに、terraform state mv で正しいアドレスへ安全に移動できます。不要なエントリは terraform state 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を用いた既存リソース参照の基本、選択基準、評価順序、...