0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWSコンソールでの構築経験をもとにTerraformを学ぶ【②EC2・ALB・RDS編】

0
Last updated at Posted at 2026-09-29

1. はじめに

前回の記事「AWSコンソールでの構築経験をもとにTerraformを学ぶ【①ネットワーク編】
」では、Terraformの基本的な使い方を確認しながら、VPC・サブネット・インターネットゲートウェイ・ルートテーブル・セキュリティグループを構築しました。

今回はその続きとして、構築したネットワーク上にEC2・ALB・RDSをTerraformで構築します。

前回と同様、実務でAWSコンソールから構築した環境を一部簡略化したサンプル環境を使用し、コンソールで行っていた構築をTerraformではどのように表現するのかをまとめます。

2. EC2

今回は、Bastionサーバを1台、Webサーバを2台作成します。
Bastionはパブリックサブネット、Webサーバはそれぞれ異なるAZのプライベートサブネットに配置します。

■ AMIの取得

EC2で使用するAMIは、AMI IDを直接指定するのではなく、data を使ってAmazon Linux 2023のAMIを取得します。

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-2023.*-x86_64"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }
}

resource がTerraformで作成・管理するリソースであるのに対して、data は既存の情報を取得して利用するために使用します。

■ EC2の作成

取得したAMIは、EC2の ami から参照します。

resource "aws_instance" "web_1a" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t3.micro"

  subnet_id                   = aws_subnet.private_1a.id
  vpc_security_group_ids      = [aws_security_group.web.id]
  associate_public_ip_address = false

  tags = {
    Name = "sample-web-1a"
  }
}

Webサーバはプライベートサブネットに配置し、パブリックIPアドレスを付与しない構成としています。

一方、Bastionサーバはパブリックサブネットに配置し、外部からSSH接続できる構成とします。

3. ALB

2台のWebサーバへ通信を振り分けるため、ALBを作成します。
今回は外部公開用ではなく、VPC内部から利用するInternal ALBとして構築します。

■ ALBの作成

ALBは2つのプライベートサブネットに配置します。

resource "aws_lb" "web" {
  name               = "sample-web-alb"
  internal           = true
  load_balancer_type = "application"

  security_groups = [aws_security_group.alb.id]

  subnets = [
    aws_subnet.private_1a.id,
    aws_subnet.private_1c.id
  ]
}

internal = true を指定することで、Internal ALBとして作成できます。

■ ターゲットグループとEC2の関連付け

ALBから通信を転送するためのターゲットグループを作成し、Webサーバを登録します。

resource "aws_lb_target_group_attachment" "web_1a" {
  target_group_arn = aws_lb_target_group.web.arn
  target_id        = aws_instance.web_1a.id
  port             = 80
}

■ リスナーの設定

ALBが受け付けたHTTP通信をターゲットグループへ転送するよう、リスナーを設定します。

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.web.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.web.arn
  }
}

ALBを構築する場合はALB本体だけでなく、ターゲットグループ・EC2の登録・リスナーなど、通信を転送するための設定もそれぞれTerraformで定義します。

4. RDS

最後に、Webサーバから接続するデータベースとして、RDS for PostgreSQLを作成します。

RDSはプライベートサブネットに配置し、インターネットから直接アクセスできない構成とします。

■ DBサブネットグループ

まず、RDSを配置するサブネットをDBサブネットグループとして定義します。

resource "aws_db_subnet_group" "main" {
  name = "sample-db-subnet-group"

  subnet_ids = [
    aws_subnet.private_1a.id,
    aws_subnet.private_1c.id
  ]
}

2つのAZのプライベートサブネットを指定しています。

■ RDSの作成

作成したDBサブネットグループとDB用セキュリティグループを指定して、RDSを作成します。

resource "aws_db_instance" "postgres" {
  identifier = "sample-postgres"

  engine            = "postgres"
  instance_class    = "db.t3.micro"
  allocated_storage = 20
  storage_type      = "gp3"

  username = var.db_username
  password = var.db_password

  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.db.id]

  publicly_accessible = false
  multi_az            = false

  skip_final_snapshot = true
  deletion_protection = false
}

DBのユーザー名とパスワードはコードへ直接記述せず、variable として定義しています。

variable "db_username" {
  type      = string
  sensitive = true
}

variable "db_password" {
  type      = string
  sensitive = true
}

値は terraform.tfvars から渡し、terraform.tfvars はGitの管理対象外としています。

■ Aurora PostgreSQLについて

当初は実務で使用したAurora PostgreSQLをTerraformで構築する予定でした。

Aurora PostgreSQLの場合、通常のRDSとは異なり、aws_rds_cluster でクラスターを作成し、aws_rds_cluster_instance でDBインスタンスを作成します。

resource "aws_rds_cluster" "aurora_postgres" {
  cluster_identifier = "sample-aurora-postgres"
  engine             = "aurora-postgresql"

  master_username = var.db_username
  master_password = var.db_password

  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.db.id]

  skip_final_snapshot = true
  deletion_protection = false
}

今回は使用しているAWSアカウントのFree Planのため、想定していた構成ではAuroraクラスターを作成できませんでした。

そのため、検証環境ではRDS for PostgreSQLを構築し、Aurora PostgreSQLのTerraformコードは参考実装としてリポジトリに残しています。

5. Terraformで再構築して学んだこと

今回、AWSコンソールで一度構築した環境をTerraformで再構築したことで、コンソール上で行っていた操作を、コードではどのように表現するのかを学ぶことができました。

特に、ルートテーブルとサブネットの関連付けや、ALB・ターゲットグループ・EC2の関連付けなど、コンソールでは画面上で設定していた内容が、Terraformではそれぞれのリソースの定義や参照として明示される点が印象に残りました。

また、fmt・validate・plan・apply といった基本的な実行の流れや、resource・data・variable の使い分けについても、実際に環境を構築することで理解を深めることができました。

今後は、今回対象外としたAWSリソースについてもTerraformでの構築を試し、IaCへの理解を深めていきたいと思います。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?