はじめに
この記事では、前回CloudFormationでインフラをコード化した作業を、Terraformで実現した内容について紹介します。
CloudFormationとTerraformはどちらも「Infrastructure as Code」に対応しており、どちらを使用してもインフラの構築が可能です。
内容は簡易的なAWS構成ですが、自分への備忘録として整理しています。
テンプレート概要
このTerraformテンプレートでは、簡易的な構成ではありますが、以下のリソースをコードで構築しています。
-
VPC (Virtual Private Cloud):
ネットワーク基盤 -
サブネット:
2つのパブリックサブネット -
インターネットゲートウェイとルートテーブル:
外部アクセスを可能にする -
EC2インスタンス:
Apacheサーバーをホスト -
ALB:
トラフィックの分散 -
ACM証明書:
HTTPS接続を実現
補足事項として、今回は事前に取得しておいた独自ドメインでのRoute53への登録作業は手動で行います。
テンプレートのセクションごとの説明
以下に、Terraformコードを6つの重要なセクションに分けて、簡潔に説明します。
1. AWSプロバイダ設定
AWSリージョン(ap-northeast-1
)を設定し、リソースを管理します。
provider "aws" {
region = "ap-northeast-1"
}
2. VPCとサブネット
VPC(仮想プライベートクラウド)と2つのパブリックサブネットを作成します。
resource "aws_vpc" "honda_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "honda-vpc"
}
}
resource "aws_subnet" "public_1" {
vpc_id = aws_vpc.honda_vpc.id
cidr_block = "10.0.0.0/20"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = true
tags = {
Name = "honda-subnet-public1-ap-northeast-1a"
}
}
resource "aws_subnet" "public_2" {
vpc_id = aws_vpc.honda_vpc.id
cidr_block = "10.0.16.0/20"
availability_zone = "ap-northeast-1c"
map_public_ip_on_launch = true
tags = {
Name = "honda-subnet-public2-ap-northeast-1c"
}
}
3. インターネットゲートウェイ
VPCにインターネット接続を提供するために、インターネットゲートウェイを作成します。
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.honda_vpc.id
tags = {
Name = "honda-igw"
}
}
resource "aws_route_table" "public_rtb" {
vpc_id = aws_vpc.honda_vpc.id
tags = {
Name = "honda-rtb-public"
}
}
resource "aws_route" "internet_route" {
route_table_id = aws_route_table.public_rtb.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
4. セキュリティグループ
ALB(アプリケーションロードバランサ)とEC2インスタンス用のセキュリティグループを作成します。
resource "aws_security_group" "alb_sg" {
vpc_id = aws_vpc.honda_vpc.id
ingress {
from_port = 443
to_port = 443
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 = "honda-alb-sg"
}
}
resource "aws_security_group" "ec2_sg" {
vpc_id = aws_vpc.honda_vpc.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb_sg.id]
}
ingress {
from_port = 22
to_port = 22
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 = "honda-ec2-sg"
}
}
ALBにはHTTPS、EC2インスタンスにはHTTPとSSHアクセスを許可します。
5. EC2インスタンス
Apacheウェブサーバーをインストールし、簡単なHTMLページを表示するEC2インスタンスを作成します。
resource "aws_instance" "apache_instance" {
ami = "ami-0b6fe957a0eb4c1b9"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_1.id
key_name = "honda"
vpc_security_group_ids = [aws_security_group.ec2_sg.id]
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<html><body><h1>Terraformでデプロイ成功!</h1></body></html>" > /var/www/html/index.html
EOF
tags = {
Name = "terraform-apache-ec2"
}
}
6. ALBとターゲットグループ
ALBを設定し、HTTPSリスナーを作成してEC2インスタンスにトラフィックを分散させます。
resource "aws_lb" "honda_alb" {
name = "honda-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb_sg.id]
subnets = [aws_subnet.public_1.id, aws_subnet.public_2.id]
enable_deletion_protection = false
tags = {
Name = "honda-alb"
}
}
resource "aws_lb_target_group" "honda_target_group" {
name = "honda-alb-target-group"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.honda_vpc.id
target_type = "instance"
}
resource "aws_lb_target_group_attachment" "target_group_attachment" {
target_group_arn = aws_lb_target_group.honda_target_group.arn
target_id = aws_instance.apache_instance.id
}
resource "aws_lb_listener" "honda_listener" {
load_balancer_arn = aws_lb.honda_alb.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = var.acm_certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.honda_target_group.arn
}
}
実際に完成したコード
ここまでの上記内容を踏まえて、最終的に完成したコードは以下になります。
provider "aws" {
region = "ap-northeast-1"
}
# Variables
variable "acm_certificate_arn" {
default = "arn:aws:acm:ap-northeast-1:340823193247:certificate/4c8e465b-6926-47c7-87e8-06ae27b895bd"
description = "ARN of the ACM Certificate"
}
# VPC
resource "aws_vpc" "honda_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "honda-vpc"
}
}
# Public Subnet 1
resource "aws_subnet" "public_1" {
vpc_id = aws_vpc.honda_vpc.id
cidr_block = "10.0.0.0/20"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = true
tags = {
Name = "honda-subnet-public1-ap-northeast-1a"
}
}
# Public Subnet 2
resource "aws_subnet" "public_2" {
vpc_id = aws_vpc.honda_vpc.id
cidr_block = "10.0.16.0/20"
availability_zone = "ap-northeast-1c"
map_public_ip_on_launch = true
tags = {
Name = "honda-subnet-public2-ap-northeast-1c"
}
}
# Internet Gateway
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.honda_vpc.id
tags = {
Name = "honda-igw"
}
}
# Route Table
resource "aws_route_table" "public_rtb" {
vpc_id = aws_vpc.honda_vpc.id
tags = {
Name = "honda-rtb-public"
}
}
# Default Route
resource "aws_route" "internet_route" {
route_table_id = aws_route_table.public_rtb.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
# Subnet Route Table Associations
resource "aws_route_table_association" "public_1_association" {
subnet_id = aws_subnet.public_1.id
route_table_id = aws_route_table.public_rtb.id
}
resource "aws_route_table_association" "public_2_association" {
subnet_id = aws_subnet.public_2.id
route_table_id = aws_route_table.public_rtb.id
}
# Security Group for ALB
resource "aws_security_group" "alb_sg" {
vpc_id = aws_vpc.honda_vpc.id
ingress {
from_port = 443
to_port = 443
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 = "honda-alb-sg"
}
}
# Security Group for EC2
resource "aws_security_group" "ec2_sg" {
vpc_id = aws_vpc.honda_vpc.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb_sg.id]
}
ingress {
from_port = 22
to_port = 22
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 = "honda-ec2-sg"
}
}
# EC2 Instance
resource "aws_instance" "apache_instance" {
ami = "ami-0b6fe957a0eb4c1b9"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_1.id
key_name = "honda"
vpc_security_group_ids = [
aws_security_group.ec2_sg.id
]
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<html><body><h1>Terraformでデプロイ成功!</h1></body></html>" > /var/www/html/index.html
EOF
tags = {
Name = "terraform-apache-ec2"
}
}
# Load Balancer
resource "aws_lb" "honda_alb" {
name = "honda-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb_sg.id]
subnets = [aws_subnet.public_1.id, aws_subnet.public_2.id]
enable_deletion_protection = false
tags = {
Name = "honda-alb"
}
}
# Target Group
resource "aws_lb_target_group" "honda_target_group" {
name = "honda-alb-target-group"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.honda_vpc.id
target_type = "instance"
}
resource "aws_lb_target_group_attachment" "target_group_attachment" {
target_group_arn = aws_lb_target_group.honda_target_group.arn
target_id = aws_instance.apache_instance.id
}
# Listener
resource "aws_lb_listener" "honda_listener" {
load_balancer_arn = aws_lb.honda_alb.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = var.acm_certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.honda_target_group.arn
}
}
Route 53 のホストゾーンに A レコードを追加する作業は手動で行っていますので、やり方が分からない方は、前回の記事を参考にしてみてください。
実際にやってみた
ここでは、CloudShellでの Terraform のセットアップが完了していることを前提に進めます。
まだセットアップが完了していない方は、過去の記事を参考にしてセットアップを実施してください。
まず、以下のコマンドを入力して、main.tfというファイルを作成します。
vi main.tf
vi
では、ファイル編集後にESCキーを押し、:wq
で保存して終了します。
# 上記の完成した全体のコードをコピーして貼り付けてください。
次に、以下のコマンドで Terraform を初期化します。
terraform init
実際に、以下のように「Terraform has been successfully initialized!
」と表示され、成功が確認できました。
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
次に、以下のコマンドを入力して、確認メッセージが表示されたら「yes
」と入力します。
terraform apply
その後、以下のように「Apply complete! Resources: xxx added, 0 changed, 0 destroyed.
」と表示され、作成が成功したことが確認できました。
ブラウザからアクセスしてみる
すべての手順が完了したら、ブラウザで取得したドメイン名(例: https://honda333.blog/
)にアクセスします。
また、ALBやACMも問題なくインフラのコード化が成功していることが確認できました。
まとめ
今回ご紹介したTerraformテンプレートでは、基本的なネットワーク構成の作成からウェブサーバーのデプロイ、HTTPS対応のALB設定までを一貫してコードで構築するプロセスを解説しました。
このテンプレートを活用すれば、再現性のある効率的なインフラ構築が可能です。
この技術検証が、誰かの技術的な支えとなれば嬉しいです!
関連記事
Terraformによるインフラのコード化についても過去の記事で解説しているため、より深く知りたい方は読んでみてください!