見出し画像

TerraformでのALB構築_ALBとVPCの接続 #483

現在のタスクでインフラ構築をやらせていただいていて、これまで机上でしか触れてこなかった部分に関われているので、記憶が鮮明なうちにアウトプットしようと思います。

アプリケーションの可用性とスケーラビリティを確保するために重要な存在であるALB (Application Load Balancer) について、VPCと接続する部分をTerraformのコードを交えながら書いていきます。

ALBとその役割

ALBは、その名の通りアプリケーション層のロードバランサーで、HTTP/HTTPSトラフィックを特定のターゲットグループにルーティングするために使用されます。複数のコンテナ(ECS)やインスタンス(EC2)にトラフィックを分散させることで、アプリケーションの可用性と応答性を高めることができます。

また、認証機能のCognitoやセキュリティ用のWAFなど、AWSが提供している様々な機能と簡単に連携できる点も魅力です。

VPCの基本

ALBとVPCを接続するうえで、ネットワーク構成を理解しておくことが重要です。VPCはAWSリソースを隔離された環境で実行するための仮想ネットワークであり、ALBもこの中で動作します

VPCのネットワーク設定には以下の概念があります。

サブネット

VPCは複数のサブネットに分割されます。サブネットにはパブリックサブネットとプライベートサブネットがあり、前者がインターネットに接続されているものです。

また、ALBを展開するには異なるアベイラビリティゾーン (AZ) の2つ以上のパブリックサブネットが必要です。シングルAZ構成にしたい場合でも、何も存在しないパブリックサブネットを1つ作って指定します。

ルートテーブル

ルートテーブルはVPC内のトラフィックがどのようにルーティングされるかを定義します。ALBがインターネットに接続するためには、パブリックサブネットのルートテーブルにインターネットゲートウェイへのルートが必要です。

Terraformを使ったALB構築

ALBの実装には以下のリソースが必要です。

  • VPC

  • サブネット(パブリック)

  • インターネットゲートウェイ(IGW)

  • ルートテーブル

  • セキュリティグループ

  • ALB

  • ターゲットグループ

  • リスナー

ではそれぞれ見ていきたいと思います。

VPCとサブネット

VPC1つとサブネット2つを作成します。ここではAZは利用可能なものを自動取得して割り当てる形にしています。

provider "aws" {
  region = "us-west-2"  # リージョンを指定
}

# リージョンで利用可能なAZを取得
data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public" {
  count = 2  # 2つ作成する
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-${count.index + 1}"
  }
}

count = 2は、Terraformにおける繰り返し処理の1つです。ここで指定した数だけリソースを作成し、「count.index」を使ってリソースを区分けしてます。

インターネットゲートウェイとルートテーブル

次に、VPCにインターネットゲートウェイを設置し、パブリックサブネットのルートテーブルを設定します。

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
  
  tags = {
    Name = "main-igw"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"                   # すべての外部トラフィック (0.0.0.0/0) を
    gateway_id = aws_internet_gateway.main.id  # インターネットゲートウェイにルーティング
  }

  tags = {
    Name = "public-route-table"
  }
}

# パブリックサブネットへのルートテーブルの関連付け
resource "aws_route_table_association" "public" {
  count          = 2  # 2つ作成する
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}

サブネットをaws_subnet.public[count.index].idで指定していますが、count を使用した場合、そのリソースには count.index が自動的に割り当てられるためこのように使えます。

ALB

ALB自体の定義です。ALBがVPCのパブリックサブネットにデプロイされるように設定します。

resource "aws_lb" "main" {
  name               = "example-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb_sg.id]
  subnets            = aws_subnet.public[*].id

  enable_deletion_protection = false  # 削除保護を有効にするかどうか

  tags = {
    Name = "example-alb"
  }
}

subnetsのところがaws_subnet.public[*].idとなっていますが、[*]はスプラット演算子と呼ばれるもので、リストやマップの中の特定の属性を抽出して配列として返すために使用されます。

aws_subnet.publiccount = 2で作成したため「2つのサブネットリソースの集合体(リスト)」になっており、スプラット演算子によってここではid属性のリストを抽出([*].id)して使っている形です。

セキュリティグループ

セキュリティグループは「インスタンスレベルで動作するステートフルなファイアウォール」で、これによりALBのingress(受信トラフィック)とegress(送信トラフィック)を制御します。

resource "aws_security_group" "alb_sg" {
  vpc_id = aws_vpc.main.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"  # 送信のプロトコルは何でもOK、とした
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "alb-security-group"
  }
}

ターゲットグループとリスナー

最後に、ALBがリクエストを受け取るリスナーと、ALBからトラフィックをルーティングするターゲットグループを定義します。

resource "aws_lb_target_group" "main" {
  name     = "example-targets"
  port     = 80  # リクエストを受け取るポート(リスナー側はこの設定を元にリクエストを転送してくる)
  protocol = "HTTP"
  vpc_id   = aws_vpc.main.id

  health_check {
    healthy_threshold   = 2
    unhealthy_threshold = 2
    timeout             = 5
    interval            = 30
    path                = "/"
    matcher             = "200"
  }

  tags = {
    Name = "example-target-group"
  }
}
 

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.main.arn
  port              = "443"
  protocol          = "HTTPS"

  ssl_policy        = "ELBSecurityPolicy-2016-08"   # SSLポリシーの指定(指定しなければデフォルトの推奨ポリシーが適用される)
  certificate_arn   = aws_acm_certificate.main.arn  # ACM証明書のARNを指定

  default_action {
    type             = "forward"  # リスナーがリクエストを受け取ったらforword(ターゲットグループへ転送)する、という設定
    target_group_arn = aws_lb_target_group.main.arn
  }
}

リスナーのdefault_actionには、forword以外にもredirect, fixed_responseなどがあります。


ALBを建てる時の基本的な構成について整理しました。
ここまでお読みいただきありがとうございました!!

参考


この記事が気に入ったらサポートをしてみませんか?