TerraformでシンプルなAWS構成を作ろう
この章では、Terraformを使ったシンプルなAWSインフラの構築をハンズオン形式で学習します。これにより、VPC・サブネット・セキュリティグループ・EC2をコードで構築できるようになります。
1. 本章の概要
1.1 本章の目的
これまで学んだTerraformの基本を1つのシステム構成として組み立ててみる集大成のハンズオンです。VPC・サブネット・EC2など複数リソースを組み合わせて、AWS講座で手動で作成したものと同様の構成をコードで再現します。
1.2 ハンズオンの流れ
VPC・サブネット・インターネットゲートウェイ・ルートテーブル・セキュリティグループ・EC2インスタンスをTerraformで定義し、terraform applyで一括構築します。

1.3 事前準備
必要なツール
この章では、以下のツールを使用します。まだインストールしていない場合は、リンク先の手順に沿って準備をお願いします。
| ツール名 | 関連箇所 | 理由 |
|---|---|---|
| Visual Studio Code | Visual Studio Codeのインストール | Terraformコードを記述するエディタとして使用する |
| AWS CLI | AWS CLIのインストール | TerraformがAWSに接続する際の認証情報を設定するために使用する |
| Terraform | Terraformのインストール | 本章で扱うIaCツール本体 |
必要なアカウント
この章では、以下のアカウントを使用します。まだ用意していない場合は、リンク先の手順に沿って準備をお願いします。
| アカウント名 | 関連箇所 | 理由 |
|---|---|---|
| AWSアカウント | AWSアカウントの作成 | Terraformでリソースを構築するAWS環境として使用する |
2. プロジェクトの準備
2.1 作業フォルダの作成
任意の場所にterraform-aws-basicフォルダを作成し、Visual Studio Codeの「ファイル」→「フォルダーを開く」から、作成したterraform-aws-basicフォルダを開きます。
terraform-aws-basic ← このフォルダを作成
3. プロバイダーの設定
最初に、AWSプロバイダーを設定するmain.tfファイルを作成します。Visual Studio Codeのエクスプローラーでterraform-aws-basicフォルダを右クリックし、「新しいファイル」を選択してmain.tfという名前で作成してください。
terraform-aws-basic
└── main.tf ← このファイルを作成
作成したファイルに以下の内容を記述して保存します。
# AWSプロバイダーの設定
provider "aws" {
region = "ap-northeast-1"
}
4. Terraformの初期化
プロバイダーの設定が完了したら、Terraformを初期化します。ターミナルでterraform-aws-basicフォルダに移動し、以下のコマンドを実行してください。
terraform init
以下のような出力が表示されれば成功です。
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v5.x.x...
- Installed hashicorp/aws v5.x.x (signed by HashiCorp)
Terraform has been successfully initialized!
| ⚠️ 「error configuring Terraform AWS Provider」エラーが出る場合 |
|---|
AWS CLIの認証情報が正しく設定されているか確認してください。aws configureコマンドで設定を確認・更新できます。 |
これで、コードを追加するたびにterraform planで差分を確認し、terraform applyで反映できる状態になりました。
5. VPCの作成

5.1 コードの記載
ここでは、AWSのネットワークの土台となるVPC(Virtual Private Cloud)を作成します。Terraformでは、resource "aws_vpc"を使ってVPCを定義します。以下の内容をmain.tfに追記してください。
# ====================
# VPC
# ====================
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "terraform-vpc"
}
}
今回設定した内容について解説します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| cidr_block(VPCのIPv4 CIDRブロック) | 10.0.0.0/16 | 約65,000個のIPアドレスを確保できる範囲のため |
| enable_dns_hostnames(DNSホスト名の有効化) | true | EC2インスタンスにDNSホスト名を付与するため |
| enable_dns_support(DNS解決の有効化) | true | VPC内でDNS解決を有効にするため |
| tags.Name(AWSコンソールに表示される名前タグ) | terraform-vpc | リソースを識別するため |
5.2 差分の確認
terraform planで作成されるリソースを確認します。
terraform plan
以下のような実行結果が表示されます。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
+ create
Terraform will perform the following actions:
# aws_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ cidr_block = "10.0.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_dns_hostnames = true
+ enable_dns_support = true
+ enable_network_address_usage_metrics = (known after apply)
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_network_border_group = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Name" = "terraform-vpc"
}
+ tags_all = {
+ "Name" = "terraform-vpc"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
+ createの記号が示すとおり、VPCが1つ新規作成されることがわかります。cidr_blockやenable_dns_hostnamesなど、コードで指定した値が反映されていることを確認してください。(known after apply)と表示されている項目は、実際にリソースが作成された後にAWSから割り当てられる値です。
5.3 AWSへの反映
問題なければterraform applyで反映します。
terraform apply
確認プロンプトが表示されたら、yesと入力して実行します。以下のように、VPCが1件作成されたことを確認します。
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
5.4 AWSコンソールでの確認
AWSマネジメントコンソールで VPC のダッシュボードを開き、「terraform-vpc」という名前のVPCが作成されていることを確認してください。VPCを選択し、以下の項目がコードで設定した内容と一致していることも確認しましょう。
- IPv4 CIDR が「10.0.0.0/16」であること
- DNSホスト名 が「有効」であること
- DNS解決 が「有効」であること

6. サブネットの作成

6.1 コードの記載
ここでは、VPC内にEC2インスタンスを配置するためのパブリックサブネットを作成します。Terraformでは、resource "aws_subnet"を使ってサブネットを定義します。以下の内容をmain.tfに追記してください。
# ====================
# サブネット
# ====================
# パブリックサブネット
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = true
tags = {
Name = "terraform-public-subnet"
}
}
今回設定した内容について解説します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| vpc_id(サブネットを作成するVPC) | aws_vpc.main.id | 作成したVPCに所属させるため(リソース参照) |
| cidr_block(サブネットのIPv4 CIDRブロック) | 10.0.1.0/24 | 約250個のIPアドレスを確保できる範囲のため |
| availability_zone(サブネットを配置するアベイラビリティゾーン) | ap-northeast-1a | 東京リージョンのAZを指定するため |
| map_public_ip_on_launch(パブリックIP自動割り当て) | true | EC2起動時に自動でパブリックIPを付与するため |
| tags.Name(AWSコンソールに表示される名前タグ) | terraform-public-subnet | リソースを識別するため |
| 💡 ポイント |
|---|
vpc_id = aws_vpc.main.idの部分で、先ほど定義したVPCのIDを参照しています。前の章 リソース間の参照 で学んだ考え方を活用しています。Terraformはこの参照を解析し、VPCが作成されてからサブネットを作成します。 |
6.2 差分の確認
terraform planで差分を確認します。
terraform plan
以下のような実行結果が表示されます。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
+ create
Terraform will perform the following actions:
# aws_subnet.public will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "ap-northeast-1a"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.0.1.0/24"
+ enable_dns64 = false
+ enable_resource_name_dns_a_record_on_launch = false
+ enable_resource_name_dns_aaaa_record_on_launch = false
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ ipv6_native = false
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ private_dns_hostname_type_on_launch = (known after apply)
+ tags = {
+ "Name" = "terraform-public-subnet"
}
+ tags_all = {
+ "Name" = "terraform-public-subnet"
}
+ vpc_id = "vpc-xxxxxxxxxxxxxxxxx"
}
Plan: 1 to add, 0 to change, 0 to destroy.
パブリックサブネットが1つ作成されることがわかります。map_public_ip_on_launch = trueが設定されていることを確認してください。また、vpc_idには先ほど作成したVPCのIDが自動的に設定されています。
6.3 AWSへの反映
問題なければterraform applyで反映します。
terraform apply
確認プロンプトが表示されたら、yesと入力して実行します。以下のように、サブネットが1件作成されたことを確認します。
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
6.4 AWSコンソールでの確認
AWSマネジメントコンソールで VPC > サブネット を開き、「terraform-public-subnet」が作成されていることを確認してください。サブネットを選択し、以下の項目がコードで設定した内容と一致していることも確認しましょう。
- VPC が「terraform-vpc」であること
- IPv4 CIDR が「10.0.1.0/24」であること
- アベイラビリティゾーン が「ap-northeast-1a」であること
- パブリックIPv4アドレスを自動割り当て が「はい」であること

7. インターネットゲートウェイの作成

7.1 コードの記載
ここでは、VPCからインターネットへ接続するためのインターネットゲートウェイを作成します。Terraformでは、resource "aws_internet_gateway"を使ってインターネットゲートウェイを定義します。以下の内容をmain.tfに追記してください。
# ====================
# インターネットゲートウェイ
# ====================
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-igw"
}
}
今回設定した内容について解説します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| vpc_id(アタッチするVPC) | aws_vpc.main.id | 作成したVPCにインターネットゲートウェイをアタッチするため |
| tags.Name(AWSコンソールに表示される名前タグ) | terraform-igw | リソースを識別するため |
7.2 差分の確認
terraform planで差分を確認します。
terraform plan
以下のような実行結果が表示されます。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
+ create
Terraform will perform the following actions:
# aws_internet_gateway.main will be created
+ resource "aws_internet_gateway" "main" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Name" = "terraform-igw"
}
+ tags_all = {
+ "Name" = "terraform-igw"
}
+ vpc_id = "vpc-xxxxxxxxxxxxxxxxx"
}
Plan: 1 to add, 0 to change, 0 to destroy.
インターネットゲートウェイが1つ作成されることがわかります。vpc_idに先ほど作成したVPCのIDが設定されていることを確認してください。
7.3 AWSへの反映
問題なければterraform applyで反映します。
terraform apply
確認プロンプトが表示されたら、yesと入力して実行します。以下のように、インターネットゲートウェイが1件作成されたことを確認します。
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
7.4 AWSコンソールでの確認
AWSマネジメントコンソールで VPC > インターネットゲートウェイ を開き、「terraform-igw」が作成されていることを確認してください。以下の項目がコードで設定した内容と一致していることも確認しましょう。
- 状態 が「Attached」であること
- VPC ID が「terraform-vpc」のVPCであること

8. ルートテーブルの作成

8.1 コードの記載
ここでは、パブリックサブネットからインターネットへの通信経路を定義するルートテーブルを作成し、サブネットに関連付けます。Terraformでは、resource "aws_route_table"でルートテーブルを定義し、resource "aws_route_table_association"でサブネットとの関連付けを行います。以下の内容をmain.tfに追記してください。
# ====================
# ルートテーブル
# ====================
# パブリックサブネット用ルートテーブル
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "terraform-public-rt"
}
}
# ルートテーブルとサブネットの関連付け
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
今回設定した内容について解説します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| vpc_id(ルートテーブルを作成するVPC) | aws_vpc.main.id | 作成したVPCに所属させるため |
| route.cidr_block(ルートの送信先) | 0.0.0.0/0 | すべてのトラフィックを対象にするため |
| route.gateway_id(ルートのターゲット) | aws_internet_gateway.main.id | インターネットゲートウェイに転送するため |
| tags.Name(AWSコンソールに表示される名前タグ) | terraform-public-rt | リソースを識別するため |
| subnet_id(関連付けるサブネット) | aws_subnet.public.id | パブリックサブネットにルートテーブルを適用するため |
| route_table_id(関連付けるルートテーブル) | aws_route_table.public.id | 作成したルートテーブルを使用するため |
| 📝 ルートテーブルとは |
|---|
ルートテーブルは、サブネット内のトラフィックの送信先を決定します。0.0.0.0/0(すべての宛先)をインターネットゲートウェイに向けることで、パブリックサブネットからインターネットへのアクセスが可能になります。 |
8.2 差分の確認
terraform planで差分を確認します。
terraform plan
以下のような実行結果が表示されます。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
+ create
Terraform will perform the following actions:
# aws_route_table.public will be created
+ resource "aws_route_table" "public" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = [
+ {
+ cidr_block = "0.0.0.0/0"
+ gateway_id = (known after apply)
+ carrier_gateway_id = ""
+ core_network_arn = ""
+ destination_prefix_list_id = ""
+ egress_only_gateway_id = ""
+ ipv6_cidr_block = ""
+ local_gateway_id = ""
+ nat_gateway_id = ""
+ network_interface_id = ""
+ transit_gateway_id = ""
+ vpc_endpoint_id = ""
+ vpc_peering_connection_id = ""
},
]
+ tags = {
+ "Name" = "terraform-public-rt"
}
+ tags_all = {
+ "Name" = "terraform-public-rt"
}
+ vpc_id = "vpc-xxxxxxxxxxxxxxxxx"
}
# aws_route_table_association.public will be created
+ resource "aws_route_table_association" "public" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = "subnet-xxxxxxxxxxxxxxxxx"
}
Plan: 2 to add, 0 to change, 0 to destroy.
ルートテーブルとサブネットの関連付けの2つが作成されることがわかります。ルートテーブルのrouteにcidr_block = "0.0.0.0/0"が設定されており、すべてのトラフィックがインターネットゲートウェイに向けられることを確認してください。
8.3 AWSへの反映
問題なければterraform applyで反映します。
terraform apply
確認プロンプトが表示されたら、yesと入力して実行します。以下のように、ルートテーブルとサブネットの関連付けの2件が作成されたことを確認します。
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
8.4 AWSコンソールでの確認
AWSマネジメントコンソールで VPC > ルートテーブル を開き、「terraform-public-rt」が作成されていることを確認してください。ルートテーブルを選択し、以下の項目がコードで設定した内容と一致していることも確認しましょう。
- VPC が「terraform-vpc」であること
- 「ルート」タブで、送信先
0.0.0.0/0のターゲットが「terraform-igw」(インターネットゲートウェイ)になっていること - 「サブネットの関連付け」タブで、「terraform-public-subnet」が関連付けられていること

9. セキュリティグループの作成

9.1 コードの記載
ここでは、EC2インスタンスへの通信を制御するセキュリティグループを作成します。Terraformでは、resource "aws_security_group"を使ってセキュリティグループを定義し、ingressブロックで受信ルール、egressブロックで送信ルールを設定します。以下の内容をmain.tfに追記してください。
# ====================
# セキュリティグループ
# ====================
resource "aws_security_group" "ec2" {
name = "terraform-ec2-sg"
description = "Security group for EC2 instance"
vpc_id = aws_vpc.main.id
# SSH接続を許可
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow SSH"
}
# HTTP接続を許可
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow HTTP"
}
# アウトバウンド通信を全て許可
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow all outbound traffic"
}
tags = {
Name = "terraform-ec2-sg"
}
}
今回設定した内容について解説します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| name(セキュリティグループ名) | terraform-ec2-sg | リソースを識別するため |
| description(セキュリティグループの説明) | Security group for EC2 instance | セキュリティグループの用途を明示するため |
| vpc_id(セキュリティグループを作成するVPC) | aws_vpc.main.id | 作成したVPCに所属させるため |
| ingress(SSH用インバウンドルール) | ポート22, TCP, 0.0.0.0/0 | SSH接続を許可するため |
| ingress(HTTP用インバウンドルール) | ポート80, TCP, 0.0.0.0/0 | HTTP接続を許可するため |
| egress(アウトバウンドルール) | 全ポート, 全プロトコル, 0.0.0.0/0 | すべてのアウトバウンド通信を許可するため |
| tags.Name(AWSコンソールに表示される名前タグ) | terraform-ec2-sg | リソースを識別するため |
| 💡 ポイント |
|---|
このセクションでは簡略化のため、SSH接続を0.0.0.0/0(全世界)から許可しています。本番環境では、自分のIPアドレスのみを許可するなど、適切なセキュリティ設定を行ってください。 |
9.2 差分の確認
terraform planで差分を確認します。
terraform plan
以下のような実行結果が表示されます。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
+ create
Terraform will perform the following actions:
# aws_security_group.ec2 will be created
+ resource "aws_security_group" "ec2" {
+ arn = (known after apply)
+ description = "Security group for EC2 instance"
+ egress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow all outbound traffic"
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = false
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow HTTP"
+ from_port = 80
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 80
},
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow SSH"
+ from_port = 22
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 22
},
]
+ name = "terraform-ec2-sg"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags = {
+ "Name" = "terraform-ec2-sg"
}
+ tags_all = {
+ "Name" = "terraform-ec2-sg"
}
+ vpc_id = "vpc-xxxxxxxxxxxxxxxxx"
}
Plan: 1 to add, 0 to change, 0 to destroy.
セキュリティグループが1つ作成されることがわかります。ingressにSSH(ポート22)とHTTP(ポート80)の2つのインバウンドルール、egressにすべてのアウトバウンドトラフィックを許可するルールが設定されていることを確認してください。
9.3 AWSへの反映
問題なければterraform applyで反映します。
terraform apply
確認プロンプトが表示されたら、yesと入力して実行します。以下のように、セキュリティグループが1件作成されたことを確認します。
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
9.4 AWSコンソールでの確認
AWSマネジメントコンソールで EC2 > セキュリティグループ を開き、「terraform-ec2-sg」が作成されていることを確認してください。セキュリティグループを選択し、以下の項目がコードで設定した内容と一致していることも確認しましょう。
- セキュリティグループ名 が「terraform-ec2-sg」であること
- 説明 が「Security group for EC2 instance」であること
- VPC が「terraform-vpc」であること
- 「インバウンドルール」タブで、SSH(ポート22, TCP, ソース0.0.0.0/0)が許可されていること
- 「インバウンドルール」タブで、HTTP(ポート80, TCP, ソース0.0.0.0/0)が許可されていること
- 「アウトバウンドルール」タブで、すべてのトラフィック(全プロトコル, 送信先0.0.0.0/0)が許可されていること

10. EC2インスタンスの作成

10.1 コードの記載
ここでは、パブリックサブネット上にEC2インスタンス(仮想サーバ)を作成します。Terraformでは、resource "aws_instance"を使ってEC2インスタンスを定義します。以下の内容をmain.tfに追記してください。
# ====================
# EC2インスタンス
# ====================
resource "aws_instance" "web" {
ami = "ami-088b486f20fab3f0e"
instance_type = "t2.micro"
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.ec2.id]
tags = {
Name = "terraform-ec2"
}
}
| 💡 ポイント |
|---|
| 本章ではAMI IDを直接指定しています。AMI IDはリージョンや更新によって変わるため、もしEC2の作成時にAMIが見つからないエラーが出た場合は、AWSコンソールの EC2 > AMIカタログ で「Amazon Linux 2023」の最新のAMI IDを確認し、値を置き換えてください。後の章で扱うデータソース(data source)を使うと、最新のAMI IDを動的に取得できるため、実際のプロジェクトではデータソースを使うのが適切です。 |
今回設定した内容について解説します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| ami(AMI ID) | ami-088b486f20fab3f0e | Amazon Linux 2023を使用するため(AMI IDは環境により異なる) |
| instance_type(インスタンスタイプ) | t2.micro | 無料利用枠の範囲内に収めるため |
| subnet_id(配置先サブネット) | aws_subnet.public.id | パブリックサブネットに配置するため |
| vpc_security_group_ids(適用するセキュリティグループ) | [aws_security_group.ec2.id] | 作成したセキュリティグループを適用するため |
| tags.Name(AWSコンソールに表示される名前タグ) | terraform-ec2 | リソースを識別するため |
11. 出力の定義
11.1 コードの記載
ここでは、作成したリソースのIDやIPアドレスなどの情報をterraform applyの実行結果に表示するための出力(output)を定義します。Terraformでは、outputブロックを使って出力値を定義します。以下の内容をmain.tfに追記してください。
# ====================
# 出力
# ====================
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main.id
}
output "public_subnet_id" {
description = "Public Subnet ID"
value = aws_subnet.public.id
}
output "ec2_public_ip" {
description = "EC2 Public IP"
value = aws_instance.web.public_ip
}
output "ec2_instance_id" {
description = "EC2 Instance ID"
value = aws_instance.web.id
}
11.2 差分の確認
terraform planで差分を確認します。
terraform plan
以下のような実行結果が表示されます。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
+ create
Terraform will perform the following actions:
# aws_instance.web will be created
+ resource "aws_instance" "web" {
+ ami = "ami-088b486f20fab3f0e"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t2.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = "subnet-xxxxxxxxxxxxxxxxx"
+ tags = {
+ "Name" = "terraform-ec2"
}
+ tags_all = {
+ "Name" = "terraform-ec2"
}
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_destroy = false
+ vpc_security_group_ids = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ ec2_instance_id = (known after apply)
+ ec2_public_ip = (known after apply)
+ public_subnet_id = "subnet-xxxxxxxxxxxxxxxxx"
+ vpc_id = "vpc-xxxxxxxxxxxxxxxxx"
EC2インスタンスが1つ作成されることがわかります。amiにはAmazon Linux 2023のAMI IDが、instance_typeにはt2.microが、subnet_idにはパブリックサブネットのIDが設定されていることを確認してください。末尾のChanges to Outputsには、outputで定義した出力値が表示されています。
11.3 AWSへの反映
問題なければterraform applyで反映します。
terraform apply
確認プロンプトが表示されたら、yesと入力して実行します。以下のように、EC2インスタンスが1件作成され、定義した出力が表示されることを確認します。
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
ec2_instance_id = "i-xxxxxxxxxxxxxxxxx"
ec2_public_ip = "xx.xx.xx.xx"
public_subnet_id = "subnet-xxxxxxxxxxxxxxxxx"
vpc_id = "vpc-xxxxxxxxxxxxxxxxx"
11.4 AWSコンソールでの確認
AWSマネジメントコンソールで EC2 > インスタンス を開き、「terraform-ec2」が作成されていることを確認してください。インスタンスを選択し、以下の項目がコードで設定した内容と一致していることも確認しましょう。
- AMI が「Amazon Linux 2023」であること
- インスタンスタイプ が「t2.micro」であること
- サブネット が「terraform-public-subnet」であること
- セキュリティグループ が「terraform-ec2-sg」であること
- パブリックIPv4アドレス が割り当てられていること

| 💡 ポイント |
|---|
ec2_public_ipに表示されたIPアドレスを使って、EC2インスタンスに接続できます。ただし、このセクションではキーペアを設定していないため、SSHログインはできません。接続が必要な場合は、EC2 Instance Connectやセッションマネージャーを使用してください。 |
Terraformでも現在の状態を確認できます。terraform showコマンドで、管理しているすべてのリソースの詳細を表示できます。
terraform show
特定の出力だけを確認したい場合は、以下のコマンドを使用します。
terraform output ec2_public_ip
12. リソースの変更

Terraformの強みは、コードを変更するだけでインフラを更新できることです。試しにEC2インスタンスの名前を変更してみましょう。
12.1 コードの変更
main.tfのEC2インスタンスのタグを以下のように編集します。Nameの値を"terraform-ec2"から"terraform-web-server"に変更してください。
tags = {
Name = "terraform-web-server"
}
12.2 差分の確認
変更を保存したら、terraform planで差分を確認します。
terraform plan
以下のような実行結果が表示されます。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
~ update in-place
Terraform will perform the following actions:
# aws_instance.web will be updated in-place
~ resource "aws_instance" "web" {
id = "i-xxxxxxxxxxxxxxxxx"
~ tags = {
~ "Name" = "terraform-ec2" -> "terraform-web-server"
}
~ tags_all = {
~ "Name" = "terraform-ec2" -> "terraform-web-server"
}
# (30 unchanged attributes hidden)
# (8 unchanged blocks hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
~ update in-placeの記号は、リソースを削除・再作成せず、その場で更新されることを示しています。"terraform-ec2" -> "terraform-web-server"と表示され、名前タグだけが変更されることがわかります。
12.3 AWSへの反映
問題なければterraform applyで反映します。
terraform apply
確認プロンプトが表示されたら、yesと入力して実行します。以下のように、1件のリソースが変更されたことを確認します。
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
12.4 AWSコンソールでの確認
AWSマネジメントコンソールで EC2 > インスタンス を開き、インスタンスの名前が「terraform-web-server」に変更されていることを確認してください。

このように、Terraformではコードを変更してterraform planで差分を確認し、terraform applyで反映するだけで、インフラの変更が可能です。
13. 不要リソースの削除
ハンズオンが終わったら、課金を避けるため、作成したリソースを削除します。
terraform destroy
確認プロンプトが表示されたら、yesと入力して実行します。
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
削除が完了すると、以下のように表示されます。
Destroy complete! Resources: 6 destroyed.
| 💡 ポイント |
|---|
terraform destroyは、Terraformで管理しているすべてのリソースを削除します。Terraformはリソース間の依存関係を理解しているため、正しい順序(EC2 → サブネット → VPCなど)で削除を行います。 |
13.1 作業フォルダの削除(任意)
プロジェクトフォルダを削除する場合は、以下のコマンドを実行します。
rm -rf ~/terraform-aws-basic
14. まとめ
この章では、TerraformでシンプルなAWS構成を作る流れを体験しました。
- VPC・サブネット・インターネットゲートウェイをTerraformコードで定義し、AWS上に構築できる
- ルートテーブルにより、パブリックサブネットからインターネットへのアクセス経路を設計できる
- セキュリティグループにより、EC2への通信を制御する構成を組める
- リソース間の参照により、依存関係のあるリソースを順序どおりに作成できる
terraform planで差分を確認しつつ、terraform applyで反映、AWSコンソールで確認する開発サイクルを回せるterraform planの~ update in-placeにより、リソースを再作成せずに変更を反映できるterraform destroyにより、作成したリソースを一括削除できる
次の章では、Terraformの制御構文を学びつつ、実際にコードで扱いを確かめます。