import コマンド vs importブロック(1.5+)比較

1. 概要

  • terraform importコマンド(従来の方法)
  • importブロック(Terraform 1.5+の新機能)
  • 2つの方法の比較
  • どちらを選ぶべきか

Terraform管理外で作成されたAWSリソースをTerraformで管理したい場合、「インポート」が必要です。Terraform 1.5で導入されたimportブロックはより安全で再現性の高いアプローチを提供します。


2. importコマンド(従来の方法)

# 書式
$ terraform import <リソースアドレス> <リソースID>

# EC2インスタンスをインポート
$ terraform import aws_instance.web i-1234567890abcdef0

# S3バケットをインポート
$ terraform import aws_s3_bucket.app_data my-bucket-name

# セキュリティグループをインポート
$ terraform import aws_security_group.alb sg-0123456789abcdef0

# moduleのリソースをインポート
$ terraform import module.network.aws_vpc.main vpc-0123456789abcdef0

手順:

  1. コードに空のリソースブロックを書く
  2. terraform importを実行してstateに取り込む
  3. terraform state showで現在の属性値を確認する
  4. コードに属性値を書き写す
  5. terraform planでdiffがゼロになることを確認する
# ステップ1: 空のリソースブロック(仮)
resource "aws_instance" "web" {
  # importコマンド実行後にstate showで確認した値を書く
}

問題点:

  • 手動で属性値をコードに書き写す手間がかかる
  • スクリプト化・CI化が難しい
  • 複数リソースを一括インポートするのが煩雑

3. importブロック(Terraform 1.5+、推奨)

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

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

# importブロック: どのリソースをどのIDでインポートするか宣言
import {
  to = aws_instance.web
  id = "i-1234567890abcdef0"
}

# リソースブロック: インポート後に管理したい設定を書く
resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

Terraform 1.5+の-generate-config-outオプション:

# コードを自動生成する(1.5+)
$ terraform plan -generate-config-out=generated.tf

# 生成されたコードを確認
$ cat generated.tf

-generate-config-outを使うと、インポートするリソースの属性値を自動でコードに書き出してくれます。


4. 複数リソースの一括インポート

# importブロックは複数書ける
import {
  to = aws_vpc.main
  id = "vpc-0123456789abcdef0"
}

import {
  to = aws_subnet.private["ap-northeast-1a"]
  id = "subnet-0123456789abcdef0"
}

import {
  to = aws_subnet.private["ap-northeast-1c"]
  id = "subnet-abcdef0123456789"
}

import {
  to = aws_security_group.web
  id = "sg-0123456789abcdef0"
}

コマンドだと4回実行する必要がある操作を、ブロックで宣言的に記述できます。


5. 2つの方法の比較

比較importコマンドimportブロック(1.5+)
バージョン要件すべてのバージョンTerraform 1.5+
コードへの記録残らないコードで宣言
CI/CD対応難しいterraform planで確認可能
複数リソースコマンドを何度も実行ブロックを並べるだけ
コードの自動生成なし-generate-config-outで可能
レビューplanに表示されないplanで変更内容を確認できる
importブロックの後処理apply後にブロックを削除する

6. 関連記事


7. まとめ

  • importコマンドは歴史的な方法。手動での属性値の書き写しが必要
  • importブロック(1.5+)はコードに宣言でき、planでレビュー可能、CI/CD対応
  • Terraform 1.5+を使っているならimportブロック + -generate-config-outが推奨
  • importブロックはapply後に削除する(state管理が完了したら不要)

動作確認バージョン: Terraform >= 1.5(importブロック) 公式ドキュメント: https://developer.hashicorp.com/terraform/language/import