1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

独自ドメインでアクセス:Terraformを使ったVPC設定、Apacheサーバーのデプロイ、ALBおよびACM証明書の設定

Posted at

はじめに

この記事では、前回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で保存して終了します。

main.tf
# 上記の完成した全体のコードをコピーして貼り付けてください。

次に、以下のコマンドで 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.」と表示され、作成が成功したことが確認できました。

スクリーンショット 2024-11-24 20.13.27.png

ブラウザからアクセスしてみる

すべての手順が完了したら、ブラウザで取得したドメイン名(例: https://honda333.blog/)にアクセスします。

スクリーンショット 2024-11-24 20.00.10.png

また、ALBやACMも問題なくインフラのコード化が成功していることが確認できました。

スクリーンショット 2024-11-24 20.00.43.png

まとめ

今回ご紹介したTerraformテンプレートでは、基本的なネットワーク構成の作成からウェブサーバーのデプロイ、HTTPS対応のALB設定までを一貫してコードで構築するプロセスを解説しました。

このテンプレートを活用すれば、再現性のある効率的なインフラ構築が可能です。

この技術検証が、誰かの技術的な支えとなれば嬉しいです!

関連記事

Terraformによるインフラのコード化についても過去の記事で解説しているため、より深く知りたい方は読んでみてください!

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?