0
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化してみた:第二回 リソースのインポート-ネットワーク、IAM編 [レベル:★★☆]

Last updated at Posted at 2025-07-30

AWS本番環境をTerraform化してみた:第二回 リソースのインポート-ネットワーク、IAM編

連載について

第一回: インポート戦略編では移行戦略と計画について解説しました。
今回は実際のインポート作業、特にPhase 1(VPCとネットワーク)とPhase 2(セキュリティグループとIAM)で実践した内容を解説します。

背景と課題

前回記事で説明したとおり、本番環境はGUIで構築されており、命名規則も統一されていない状態でした。これをTerraformでIaC化するため、terraform importコマンドを使って既存リソースを取り込んでいきます。

対象読者

  • terraform importを実際に使用する予定のエンジニア
  • 既存AWSリソースをTerraform管理下に置きたい方
  • インポートスクリプトの実装例を探している方

この記事からわかること

  • 実際のインポートスクリプトの実装方法
  • リソースIDの調査方法
  • インポート時のエラーハンドリング
  • Phase 1とPhase 2の具体的なインポート手順

この記事では説明しないこと

  • Terraformのstate管理の詳細
  • Phase 3以降のインポート内容(次回以降で解説)

方針検討

CloudFormationのスキャン結果から、本番環境のネットワーク、セキュリティに関する主なリソースは以下があることがわかっています。

Phase 1(ネットワーク)

  • VPC: 1個
  • Internet Gateway: 1個
  • Route Table: 4個
  • Subnet: 7個
  • Route Table Association: 7個

Phase 2(セキュリティ)

  • Security Group: 11個
  • IAM Role: 2個

合計33個のリソースを手動でインポートするのは面倒ですミスのもとです。そこでインポート作業をスクリプト化します。

インポートスクリプトによるterraform import

リソースIDの調査

インポートスクリプトを作成する前に、まず既存リソースのIDを調査する必要があります。CloudFormationでスキャンした結果も参考にしつつ、AWS CLIで最新の情報を取得します。
--output tableはお好みで

# VPCのID一覧
aws ec2 describe-vpcs --query 'Vpcs[*].[VpcId,Tags[?Key==`Name`].Value|[0]]' --output table

# サブネット一覧(VPC IDでフィルタ)
aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-0123456789abcdef0" \
  --query 'Subnets[*].[SubnetId,Tags[?Key==`Name`].Value|[0],AvailabilityZone]' --output table

# セキュリティグループ一覧
aws ec2 describe-security-groups --filters "Name=vpc-id,Values=vpc-0123456789abcdef0" \
  --query 'SecurityGroups[*].[GroupId,GroupName,Description]' --output table

# Route Table Association確認
aws ec2 describe-route-tables --query 'RouteTables[*].Associations[*].[SubnetId,RouteTableId]' --output table

インポート順序

依存関係を考慮して順番を決めます。依存関係の根幹となるVPCから始めることで、後続のリソースがスムーズにインポートできます。

  1. VPC
  2. Internet Gateway(VPCに依存)
  3. Route Table(VPCに依存)
  4. Subnet(VPCに依存)
  5. Route Table Association(SubnetとRoute Tableに依存)

Phase 1: VPCとネットワークのインポート

まずはネットワーク基盤からインポートします。なおインポート作業のログが流れてしまうので、適当にログファイルに出力しておきます。

./scripts/import-phase1.sh 2>&1 | tee import-phase1.log

import-phase1.shのイメージ:

#!/bin/bash

# Phase 1: Import VPC and Networking Resources

set -euo pipefail

# Change to terraform directory
cd "$(dirname "$0")/.."

# Function to import resource
import_resource() {
    local resource_type=$1
    local resource_name=$2
    local resource_id=$3
    
    echo "Importing ${resource_type} ${resource_name}..."
    if terraform import "${resource_type}.${resource_name}" "${resource_id}"; then
        echo "✓ Successfully imported ${resource_name}"
    else
        echo "✗ Failed to import ${resource_name} - continuing..."
    fi
}

# Import VPC
import_resource "aws_vpc" "main" "vpc-0123456789abcdef0"

# Import Internet Gateway
import_resource "aws_internet_gateway" "main" "igw-0123456789abcdef1"

# Import Route Tables
import_resource "aws_route_table" "public" "rtb-0123456789abcdef2"
import_resource "aws_route_table" "private_1a" "rtb-0123456789abcdef3"
import_resource "aws_route_table" "rds" "rtb-0123456789abcdef5"

# Import Subnets
import_resource "aws_subnet" "public_1a" "subnet-0123456789abcdef6"
import_resource "aws_subnet" "private_1a" "subnet-0123456789abcdef8"
import_resource "aws_subnet" "rds_1a" "subnet-0123456789abcdefa"
...

# Import Route Table Associations
# 注意: フォーマットは subnet-id/route-table-id
import_resource "aws_route_table_association" "public_1a" "subnet-0123456789abcdef6/rtb-0123456789abcdef2"
...

Route Table Associationの特殊性

通常のリソースと異なり、Route Table Associationは指定の仕方が異なります。

# 通常のリソース
terraform import aws_vpc.main vpc-xxxxx

# Route Table Association
terraform import aws_route_table_association.name subnet-id/route-table-id

この形式を知らないと、以下のようなエラーでに遭遇します

Error: Invalid address to import

Route table association import requires the format: subnet-id/route-table-id

Phase 2: セキュリティグループとIAMのインポート

続けてセキュリティグループとIAMです。

import-phase2.shのイメージ:

#!/bin/bash

# Phase 2: Import Security Groups and IAM Resources

set -euo pipefail

# Phase 1と同じimport_resource関数を使用

# Import Security Groups
import_resource "aws_security_group" "alb" "sg-0123456789abcdefd"
import_resource "aws_security_group" "ecs" "sg-0123456789abcdefe"
...

# Import IAM Roles
import_resource "aws_iam_role" "ecs_task_execution" "ecsTaskExecutionRole"
import_resource "aws_iam_role" "rds_monitoring" "rds-monitoring-role"
...

エラーハンドリング

importするだけなので本番環境を変更してしまうことはありませんが、念の為スクリプトには以下の対策をしています。

  1. set -euo pipefail

    • 未定義変数の使用を防ぐ
    • パイプライン内のエラーでも停止 ※pipefailをつけないとパイプでコマンドを繋げた場合、最後のコマンドにしか効かない
    • エラーでスクリプト全体を停止
  2. 個別インポートのエラー処理

    • インポート済みリソースの再インポートは失敗するが続行
    • 視覚的なフィードバック(✓/✗)で進捗を把握

Terraform planでのインポート確認

各フェーズ完了後、terraform planで差分を確認します。

terraform plan
# No changes. Your infrastructure matches the configuration. と表示されればOK!

まとめと次回予告

実際にインポート作業を行ってみると、まあTerraformはよくできた仕組みだなと感じます。リソース名とリソースIDの指定はドキュメントを読む必要がありますが、importコマンド自体で苦労することはほぼなく、生成される.tfファイルも個人的にはCloudFormationテンプレートより人間の可読性が高いと感じます。

今回のPhase 1-2で基盤となるネットワークとセキュリティの設定をTerraform管理下に置くことができました。これで後続のフェーズの準備が整いました。
次回はPhase 3以降の、より複雑なリソース(RDS、S3など)のインポートについて解説します。

0
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
0
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?