1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

手動作成したAWSリソースをTerraformに取り込む2つの方法

1
Last updated at Posted at 2026-04-08

本記事は学習の備忘録として執筆したものです。内容に誤りが含まれている可能性があります。お気づきの点があればコメントにてご指摘いただけると幸いです。

はじめに

AWSでの構築において、IaCで作成したリソースとコンソールで手動作成したリソースが混在すると、管理が煩雑になります。

今回はそのような状況を解消するための terraform import について学んだので、備忘録として記録します。

もともと、以下の懸念があり terraform import の使用をためらっていました。

VPCだけインポートしたら、他のTerraformで管理していない他のリソースに影響が出ないか?

この記事では実際にその懸念を検証しながら、2種類のimport方法を試して比較します。

方法 概要
方法A:自動生成 import ブロックを書き、-generate-config-out.tf を自動生成する
方法B:手動 terraform import CLI で state に取り込み、terraform show を見ながら .tf を手書きする

全体の流れ

① VPC・サブネット・NAT Gatewayを手動作成(AWSコンソール)

② VPCをインポート【方法A:自動生成

  • import ブロック + generate-config-out で vpc.tf を自動生成
  • VPCのタグを変更してみる(管理下に置けていることを確認)

③ サブネットをインポート【方法B:手動

  • terraform import CLI → terraform show → .tf を手動で書く
  • サブネットのタグを変更してみる(管理下に置けていることを確認)

④ 2つの手法を比較


事前準備

  • Terraform v1.5以上
  • AWS CLI 設定済み(aws configure 完了)

main.tfbackend.tf を用意した状態からスタートします。

# main.tf
terraform {
  required_version = ">= 1.14"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}
# backend.tf
terraform {
  backend "local" {}
}

① VPC・サブネット・NAT Gatewayを手動作成(AWSコンソール)

AWSコンソールで以下のリソースを作成します。

  • VPC(CIDR: 10.10.10.0/24)
  • パブリックサブネット(CIDR: 10.10.10.0/28、AZ: ap-northeast-1a)
  • NAT Gateway(パブリックサブネット内)

コンソールから「VPCなど」を選択し、VPC・サブネット・ルートテーブルを一括作成します。

1-1

作成後のプレビューは以下の通りです。

1-2

続けて、パブリックサブネット内にNAT Gatewayを作成します。

1-3

作成後のリソース一覧です。

1-4

次章では、このVPCをTerraformの管理下に置きます。


② VPCをインポート【方法A:自動生成】

Terraform 1.5以降で使用できる import ブロックと -generate-config-out オプションを使って、VPCをインポートします。

import ブロックを書く

インポート対象のリソースアドレスとAWSリソースIDを指定します。

# imports.tf
import {
  to = aws_vpc.main
  id = "vpc-xxxxxxxxxxxxxxxxx"
}

plan を実行し、vpc.tf を生成する

terraform init
terraform plan "-generate-config-out=vpc.tf"

このコマンドは以下の2つを同時に行います。

部分 意味
terraform plan imports.tf の import ブロックを読み取り、AWSから実際のリソース情報を取得する
-generate-config-out generate(生成)+ config(.tfファイル)+ out(出力先)の組み合わせ
=vpc.tf 生成した .tf コードの出力先ファイル名(任意の名前でOK)

実行すると、AWSコンソールで手動作成したVPCの全属性がTerraformコードとして vpc.tf に直接書き出されます。

vpc.tf を整理する

自動生成された vpc.tf には null 値や tags_all(AWSが自動付与するため不要)など、Terraformの設定として不要な属性が含まれています。これらを削除して整理します。

# vpc.tf
resource "aws_vpc" "main" {
  cidr_block                           = "10.10.10.0/24"
  assign_generated_ipv6_cidr_block     = false
  enable_dns_hostnames                 = true
  enable_dns_support                   = true
  enable_network_address_usage_metrics = false
  instance_tenancy                     = "default"

  tags = {
    ManagedBy = "Manual"
    Name      = "For_Terraform_import_demo-vpc"
    Project   = "terraform-import"
  }
}

terraform apply で管理下に置く

terraform apply
Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.

差分ゼロでインポートが完了し、VPCがTerraformの管理下に置かれました。

imports.tf を削除する(任意)

terraform apply でインポートが完了した時点で、リソースの情報は terraform.tfstate に記録されます。以降はリソースブロック(vpc.tf)と tfstate で管理されるため、imports.tf の import ブロックは役目を終えています。
削除するかどうかは、好みだと思います。私は削除しました。

rm imports.tf

VPCのタグを変更してみる

管理下に置けているか確認するため、タグの ManagedByManual から Terraform に変更してみます。

手動作成時のタグ

2-1

ManagedByManual から Terraform に変更します。

# vpc.tf
  tags = {
    Name      = "For_Terraform_import_demo-vpc"
    Project   = "terraform-import"
    ManagedBy = "Terraform"  # ← Manual から変更
  }
terraform apply

apply 後のタグ

2-2

タグが正常に変更されたことを確認できました。


③ サブネットをインポート【方法B:手動】

続いて、従来の terraform import CLIコマンドを使う方法でサブネットをインポートします。

空のリソースブロックを書く

terraform import を実行するには、事前に対応するリソースブロックが .tf ファイルに存在している必要があります。値はダミーでOKです。

# vpc_subnet.tf
resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "0.0.0.0/0"  # ダミー(あとで実際の値に書き直す)
}

terraform import で state に取り込む

terraform import aws_subnet.public subnet-xxxxxxxxxxxxxxxxx
Import successful!

terraform show で実際の値を確認する

terraform show は tfstate の内容を人間が読みやすい HCL 形式で表示するコマンドです。tfstate は JSON 形式のため直接読むには不向きですが、このコマンドにより .tf と同じ書き方で内容を確認できます。

terraform show

出力された値をもとに vpc_subnet.tf を書き直します。

.tf を実際の値に書き換える

terraform show の出力から必要な属性のみを抽出し、不要な属性(arnidtags_all などの computed 属性や null 値)を除いて記述します。

# vpc_subnet.tf
resource "aws_subnet" "public" {
  vpc_id                              = aws_vpc.main.id
  cidr_block                          = "10.10.10.0/28"
  availability_zone                   = "ap-northeast-1a"
  map_public_ip_on_launch             = false
  private_dns_hostname_type_on_launch = "ip-name"

  tags = {
    ManagedBy = "Manual"
    Name      = "For_Terraform_import_demo-subnet-public1-ap-northeast-1a"
    Project   = "terraform-import"
  }
}

terraform plan で差分ゼロを確認する

terraform plan
No changes. Your infrastructure matches the configuration.

差分がなければインポート完了です。なお、terraform show の出力をそのまま .tf に貼り付けると、computed 属性や競合する属性によってエラーが発生します。
何を残して何を削除するかの判断がなかなか難しいと感じました...

サブネットのタグを変更してみる

VPC と同様に、タグを変更してTerraformから操作できることを確認します。

手動作成時のタグ

3-1

ManagedByManual から Terraform に変更します。

  tags = {
    ManagedBy = "Terraform"  # ← Manual から変更
    Name      = "For_Terraform_import_demo-subnet-public1-ap-northeast-1a"
    Project   = "terraform-import"
  }
terraform apply

apply 後のタグ

3-2

タグが正常に変更されたことを確認できました。


④ 2つの手法を比較・まとめ

方法A:自動生成 方法B:手動
事前準備 imports.tf に import ブロックを書く 空のリソースブロックを書く
値の確認 vpc.tf に自動出力される terraform show で確認する
.tf の修正 不要な属性を削除するだけ 不要な属性を削除する
差分ゼロまで ほぼそのままゼロになる 試行錯誤が必要な場合がある

まとめ

両方を試した感想として、どちらも結果は同じです。

方法B(手動)terraform show の出力を見ながら必要な属性を判断して書き直す手間がかかります。
一方、方法A(自動生成) はコマンド一つで .tf ファイルが生成されるため、あとは不要な属性を削除するだけです。

作業量としては方法Aの方が少なく済みますが、大きな差ではないので、やりやすい方を選んでみると良いかと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?