- 公開日
- 最終更新日
【Terraform】for_eachとcountを使ってVPCとEC2を構築
この記事を共有する
目次
はじめに
皆さんこんにちは!サービスGの榎本です。
本記事では、Terraformの for_each と count を活用してVPCとEC2を構築するハンズオンを紹介します。
for_eachとcountの使い分け
for_each
動的に異なる値やキーを使ってリソースを構築する場合に便利です。例えば、CIDRブロックやタグが異なる複数のVPCを作る場合に使用します。
本記事ではVPCのサブネット作成時に使用します。
count
同じ定義で複数のリソースを作成したい場合に便利です。例えば、リソース数が固定されている場合に適しています。
本記事ではEC2作成時に使用します。
前提
Terraform開発環境が構築済みであること。
目的
・for_eachを使って動的なキーを基にVPCを構築する方法を理解する。
・countを使ったシンプルな複数EC2の構築方法を学ぶ。
for_each手順(VPC構築)
1. for_eachとcountハンズオン用のディレクトリを作成する
# ディレクトリ作成
mkdir -p terraform-handson/for_each-count/
2. 作成したディレクトリに移動する
# ディレクトリ移動
cd terraform-handson/for_each-count/
3. countでVPCを作成するためのmain.tfファイルを作成する
# main.tfファイル作成
touch main.tf
4. 作成したmain.tfファイルに以下内容を記載する
provider "aws" {
region = "ap-northeast-1" # 東京リージョン
}
# VPCを作成
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "terraform-handson-vpc"
}
}
# インターネットゲートウェイを作成
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-handson-igw"
}
}
# サブネットの定義
locals {
subnets = {
"public-1a" = { az = "ap-northeast-1a", cidr = "10.0.1.0/24", type = "public" }
"private-1a" = { az = "ap-northeast-1a", cidr = "10.0.2.0/24", type = "private" }
"public-1c" = { az = "ap-northeast-1c", cidr = "10.0.3.0/24", type = "public" }
"private-1c" = { az = "ap-northeast-1c", cidr = "10.0.4.0/24", type = "private" }
}
}
# サブネットを作成
resource "aws_subnet" "main" {
for_each = local.subnets
vpc_id = aws_vpc.main.id
cidr_block = each.value.cidr
availability_zone = each.value.az
map_public_ip_on_launch = each.value.type == "public"
tags = {
Name = each.key
Type = each.value.type
}
}
# パブリックルートテーブル
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = {
Name = "public-route-table"
}
}
# プライベートルートテーブル
resource "aws_route_table" "private" {
vpc_id = aws_vpc.main.id
tags = {
Name = "private-route-table"
}
}
# パブリックサブネットとルートテーブルの関連付け
resource "aws_route_table_association" "public" {
for_each = { for key, value in local.subnets : key => value if value.type == "public" }
subnet_id = aws_subnet.main[each.key].id
route_table_id = aws_route_table.public.id
}
# プライベートサブネットとルートテーブルの関連付け
resource "aws_route_table_association" "private" {
for_each = { for key, value in local.subnets : key => value if value.type == "private" }
subnet_id = aws_subnet.main[each.key].id
route_table_id = aws_route_table.private.id
}
# インターネットゲートウェイへのルート
resource "aws_route" "internet_access" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
5. コマンドを順番に実行する
terraform init
terraform plan
terraform apply
6. マネジメントコンソールのVPCコンソールを開き、リソースが作成されていることを確認する
count手順
1. 同ディレクトリのmain.tfファイルに以下内容を追記する
本記事ではプライベートサブネットのみにEC2を構築するコードを記載する。
※以下追記コードと、追記コード反映済みのmain.tfコード全体内容を示す。
▼追記コード
# private サブネットのみに対応するリストを作成
locals {
private_subnets = [for key, value in local.subnets : key if value.type == "private"]
}
# プライベートサブネットのみにEC2を作成
resource "aws_instance" "private_ec2" {
count = length(local.private_subnets) # プライベートサブネット数分インスタンスを作成
ami = "ami-023ff3d4ab11b2525" # AmazonLinux2023 の AMI ID
instance_type = "t2.micro"
# 各インスタンスのサブネットを指定
subnet_id = aws_subnet.main[local.private_subnets[count.index]].id
# 各インスタンスの名前タグ
tags = {
Name = "Instance-${local.private_subnets[count.index]}"
}
}
▼main.tfコード全体
provider "aws" {
region = "ap-northeast-1" # 東京リージョン
}
# VPCを作成
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "terraform-handson-vpc"
}
}
# インターネットゲートウェイを作成
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-handson-igw"
}
}
# サブネットの定義
locals {
subnets = {
"public-1a" = { az = "ap-northeast-1a", cidr = "10.0.1.0/24", type = "public" }
"private-1a" = { az = "ap-northeast-1a", cidr = "10.0.2.0/24", type = "private" }
"public-1c" = { az = "ap-northeast-1c", cidr = "10.0.3.0/24", type = "public" }
"private-1c" = { az = "ap-northeast-1c", cidr = "10.0.4.0/24", type = "private" }
}
}
# サブネットを作成
resource "aws_subnet" "main" {
for_each = local.subnets
vpc_id = aws_vpc.main.id
cidr_block = each.value.cidr
availability_zone = each.value.az
map_public_ip_on_launch = each.value.type == "public"
tags = {
Name = each.key
Type = each.value.type
}
}
# パブリックルートテーブル
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = {
Name = "public-route-table"
}
}
# プライベートルートテーブル
resource "aws_route_table" "private" {
vpc_id = aws_vpc.main.id
tags = {
Name = "private-route-table"
}
}
# パブリックサブネットとルートテーブルの関連付け
resource "aws_route_table_association" "public" {
for_each = { for key, value in local.subnets : key => value if value.type == "public" }
subnet_id = aws_subnet.main[each.key].id
route_table_id = aws_route_table.public.id
}
# プライベートサブネットとルートテーブルの関連付け
resource "aws_route_table_association" "private" {
for_each = { for key, value in local.subnets : key => value if value.type == "private" }
subnet_id = aws_subnet.main[each.key].id
route_table_id = aws_route_table.private.id
}
# インターネットゲートウェイへのルート
resource "aws_route" "internet_access" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
# private サブネットのみに対応するリストを作成
locals {
private_subnets = [for key, value in local.subnets : key if value.type == "private"]
}
# プライベートサブネットのみにEC2を作成
resource "aws_instance" "private_ec2" {
count = length(local.private_subnets) # プライベートサブネット数分インスタンスを作成
ami = "ami-023ff3d4ab11b2525" # AmazonLinux2023 の AMI ID
instance_type = "t2.micro"
# 各インスタンスのサブネットを指定
subnet_id = aws_subnet.main[local.private_subnets[count.index]].id
# 各インスタンスの名前タグ
tags = {
Name = "Instance-${local.private_subnets[count.index]}"
}
}
2. コマンドを順番に実行する
terraform init
terraform plan
terraform apply
3. マネジメントコンソールのEC2コンソールを開き、リソースが作成されていることを確認する
4. 構築した環境を削除する
terraform destroy
まとめ
for_eachとcountを利用することで、コードの行数を減らすことが可能です!
ただ多用すると可読性低下の可能性があるため注意してください!
この記事は私が書きました
榎本 将希
2024 Japan AWS All Certifications Engineers サッカー観戦とサウナが好きです! 機械学習を勉強中です!