Terraform を使用して AWS リソースを作成する方法を学習しました
はじめに
最近、Terraform を使用して AWS 上に EC2 インスタンス、インターネットゲートウェイ、ルートテーブルなどのリソースを作成し、EC2 インスタンスに nginx をインストールして、WEB ページを表示させるまでを学習しました。
構成は下記となります。
前提条件
- Terraform がインストールされていること
- AWS アカウントがあり、適切なアクセスキーとシークレットキーが設定されていること
ディレクトリ構成
以下のようなディレクトリ構成を使用します。
├── main.tf
└── modules
├── alb
│ ├── alb.tf
│ ├── variables.tf
│ └── output.tf
├── network
│ ├── internet-gateway.tf
│ ├── route-table.tf
│ ├── subnet.tf
│ ├── vpc.tf
│ ├── variables.tf
│ └── output.tf
├── security-group
│ ├── security-group.tf
│ ├── variables.tf
│ └── output.tf
└── iam
├── iam.tf
├── variables.tf
└── output.tf
main.tf の設定
main.tfファイルには、ネットワーク、IAM、セキュリティグループ、EC2インスタンス、ALBモジュールの設定が含まれています。EC2インスタンスにはnginxがインストールされ、起動時に自動的に開始されるように設定されています
module "network" {
source = "./modules/network"
}
module "iam" {
source = "./modules/iam"
}
module "security-group" {
source = "./modules/security-group"
vpc_id = module.network.vpc_id
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
subnet_id = module.network.subnet1
vpc_security_group_ids = [module.security-group.allow_http_security_group_id]
iam_instance_profile = module.iam.ssm_instance_profile_name
associate_public_ip_address = true
tags = {
Name = "terraform-hands-on"
}
user_data = <<-EOF
#!/bin/bash
sudo apt-get update -y
sudo apt-get install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
EOF
}
module "alb" {
source = "./modules/alb"
allow_http_security_group_id = module.security-group.allow_http_security_group_id
instance_id = aws_instance.web.id
subnet_id_1 = module.network.subnet1
subnet_id_2 = module.network.subnet2
vpc_id = module.network.vpc_id
}
IAM モジュールの設定
modules/iam/iam.tf ファイルには、IAM ロールとインスタンスプロファイルの設定が含まれています。
resource "aws_iam_role" "ssm_role" {
name = "ssm_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
}
resource "aws_iam_instance_profile" "ssm_instance_profile" {
name = "ssm_instance_profile"
role = aws_iam_role.ssm_role.name
}
output "ssm_instance_profile_name" {
value = aws_iam_instance_profile.ssm_instance_profile.name
}
modules/iam/variables.tf ファイルには、変数の設定が含まれています
variable "role_name" {
description = "The name of the IAM role"
type = string
default = "ssm_role"
}
modules/iam/output.tf ファイルには、出力の設定が含まれています
output "ssm_instance_profile_name" {
value = aws_iam_instance_profile.ssm_instance_profile.name
}
インターネットゲートウェイの設定
modules/network/internet-gateway.tf ファイルには、インターネットゲートウェイの設定が含まれています。
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-hands-on"
}
}
ルートテーブルの設定
modules/network/route-table.tf ファイルには、ルートテーブルの設定が含まれています。
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-hands-on"
}
}
resource "aws_route" "public" {
destination_cidr_block = "0.0.0.0/0"
route_table_id = aws_route_table.public.id
gateway_id = aws_internet_gateway.igw.id
}
resource "aws_route_table_association" "association-1" {
subnet_id = aws_subnet.subnet1.id
route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "association-2" {
subnet_id = aws_subnet.subnet2.id
route_table_id = aws_route_table.public.id
}
サブネットの設定
modules/network/subnet.tf ファイルには、サブネットの設定が含まれています。
resource "aws_subnet" "subnet1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-2a"
tags = {
Name = "terraform-hands-on-subnet1"
}
}
resource "aws_subnet" "subnet2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-west-2b"
tags = {
Name = "terraform-hands-on-subnet2"
}
}
VPC の設定
modules/network/vpc.tf ファイルには、VPC の設定が含まれています。
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "terraform-hands-on"
}
}
modules/network/variables.tf ファイルには、変数の設定が含まれています。
variable "vpc_cidr" {
description = "The CIDR block for the VPC"
type = string
default = "10.0.0.0/16"
}
modules/network/output.tf ファイルには、出力の設定が含まれています。
output "vpc_id" {
value = aws_vpc.main.id
}
セキュリティグループの設定
modules/security-group/security-group.tf ファイルには、セキュリティグループの設定が含まれています。
resource "aws_security_group" "allow_http" {
vpc_id = var.vpc_id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "allow_http"
}
}
output "allow_http_security_group_id" {
value = aws_security_group.allow_http.id
}
modules/security-group/variables.tf ファイルには、変数の設定が含まれています。
variable "vpc_id" {
description = "The ID of the VPC"
type = string
}
modules/security-group/output.tf ファイルには、出力の設定が含まれています。
output "allow_http_security_group_id" {
value = aws_security_group.allow_http.id
}
ALB モジュールの設定
modules/alb/alb.tf ファイルには、ALB、ターゲットグループ、リスナーの設定が含まれています。
resource "aws_lb" "alb" {
name = "test-lb-tf"
internal = false
load_balancer_type = "application"
security_groups = [var.allow_http_security_group_id]
subnets = [
var.subnet_id_1,
var.subnet_id_2
]
enable_deletion_protection = false
tags = {
Environment = "terraform-hands-on"
}
}
resource "aws_lb_target_group" "target_group" {
name = "target-group"
target_type = "instance"
protocol_version = "HTTP1"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
tags = {
Name = "terraform-hands-on"
}
health_check {
interval = 10
path = "/"
port = "traffic-port"
protocol = "HTTP"
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 2
matcher = "200,301"
}
}
resource "aws_lb_target_group_attachment" "alb_target_group_attachment" {
target_group_arn = aws_lb_target_group.target_group.arn
target_id = var.instance_id
}
resource "aws_lb_listener" "test_listener" {
load_balancer_arn = aws_lb.alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.target_group.arn
}
}
modules/alb/variables.tf ファイルには、変数の設定が含まれています。
variable "allow_http_security_group_id" {
description = "The ID of the security group that allows HTTP traffic"
type = string
}
variable "subnet_id_1" {
description = "The ID of the first subnet"
type = string
}
variable "subnet_id_2" {
description = "The ID of the second subnet"
type = string
}
variable "vpc_id" {
description = "The ID of the VPC"
type = string
}
variable "instance_id" {
description = "The ID of the instance"
type = string
}
modules/alb/output.tf ファイルには、出力の設定が含まれています。
output "alb_dns_name" {
value = aws_lb.alb.dns_name
}
実行手順
- Terraform の初期化を行います。
terraform init
- Terraform のプランを確認します。
terraform plan
- Terraform を適用してリソースを作成します。
terraform apply
以上で、Terraform を使用して AWS 上に EC2 インスタンス、インターネットゲートウェイ、ルートテーブルなどのリソースを作成する手順は完了です。
動作確認
Terraform の適用が完了したら、ALB の DNS 名を取得します。
取得した DNS 名を WEB ブラウザに入力し、アクセスします。
「Welcome to nginx」のページが表示されれば、設定が正しく行われたことを確認できます。
以上で、Terraform を使用して AWS 上に EC2 インスタンス、インターネットゲートウェイ、ルートテーブルなどのリソースを作成し、動作確認を行う手順を学習しました。
Discussion