1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ALBを1 AZ, 1 subnetで使う方法 with Terraform

Last updated at Posted at 2023-04-16

Version

required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "4.59.0"
  }
}

ALBにはAvailability Zoneが2つ必要

ALBにはAvailability Zoneが2つ必要である。
Availability Zoneを1つにしてALBを作ろうとすると次のようなエラーが出る。

│ Error: creating ELBv2 application Load Balancer (alb-qiita-production-alb): ValidationError: At least two subnets in two different Availability Zones must be specified
│       status code: 400, request id: 94fc711b-2ad0-4161-a15b-f0e65488f099
│ 
│   with aws_lb.application_load_balancer,
│   on alb.tf line 1, in resource "aws_lb" "application_load_balancer":
│    1: resource "aws_lb" "application_load_balancer" {

しかし、可用性が低くても問題にならないサービスでは、Availability Zoneもサブネットも1つで運用したいときがある。
そのようなときには、ALBに何も存在しないダミーサブネットを設定すればよい。

VPCなど

variablesなど省略している部分がある。

resource "aws_vpc" "aws_vpc" {
  cidr_block           = "10.10.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name        = "${var.product_name}-vpc"
    Environment = var.app_environment
  }
}

resource "aws_internet_gateway" "aws_igw" {
  vpc_id = aws_vpc.aws_vpc.id
  tags = {
    Name        = "${var.product_name}-igw"
    Environment = var.app_environment
  }
}

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.aws_vpc.id
  cidr_block              = var.public_subnet
  availability_zone       = var.availability_zone
  map_public_ip_on_launch = true

  tags = {
    Name        = "${var.product_name}-public-subnet"
    Environment = var.app_environment
  }
}

# ダミーサブネットを定義
resource "aws_subnet" "public_dummy" {
  vpc_id                  = aws_vpc.aws_vpc.id
  cidr_block              = var.public_dummy_subnet
  availability_zone       = var.availability_zone_dummy
  map_public_ip_on_launch = true

  tags = {
    Name        = "${var.product_name}-public-dummy-subnet"
    Environment = var.app_environment
  }
}

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

  tags = {
    Name        = "${var.product_name}-routing-table-public"
    Environment = var.app_environment
  }
}

resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.aws_igw.id
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# 必ずダミーサブネットもinternet gatewayに接続!!
resource "aws_route_table_association" "public_dummy" {
  subnet_id      = aws_subnet.public_dummy.id
  route_table_id = aws_route_table.public.id
}

ALB

variablesなど省略している部分がある。

resource "aws_lb" "application_load_balancer" {
  name               = "${var.product_name}-${var.app_environment}-alb"
  internal           = false
  load_balancer_type = "application"
  # サブネットにサービスのあるパブリックサブネットとダミーサブネットを指定
  subnets            = [aws_subnet.public.id, aws_subnet.public_dummy.id]
  security_groups    = [aws_security_group.load_balancer_security_group.id]

  tags = {
    Name        = "${var.product_name}-alb"
    Environment = var.app_environment
  }
}

resource "aws_security_group" "load_balancer_security_group" {
  vpc_id = aws_vpc.aws_vpc.id

  ingress {
    from_port        = 80
    to_port          = 80
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = {
    Name        = "${var.product_name}-sg"
    Environment = var.app_environment
  }
}

resource "aws_lb_target_group" "target_group" {
  name        = "${var.product_name}-${var.app_environment}-tg"
  port        = 8080
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_vpc.aws_vpc.id

  health_check {
    interval            = 30
    path                = "/health"
    port                = 8080
    protocol            = "HTTP"
    timeout             = 5
    unhealthy_threshold = 2
    matcher             = 200
  }

  tags = {
    Name        = "${var.product_name}-lb-tg"
    Environment = var.app_environment
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_lb_listener" "listener" {
  load_balancer_arn = aws_lb.application_load_balancer.id
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.target_group.id
  }
}

詰まりやすいところ

ここで重要なのは、ALBに設定するサブネットは2つともパブリックサブネットでなければならないという点である。
google chrome - AWS Elastic Load Balancing: Seeing extremely long initial connection time - Stack Overflow

つまり、何も存在しないサブネットだとしても、ダミーサブネットはinternet gatewayに接続されていなければならない。
必ずダミーサブネットにもaws_route_table_associationを指定しよう。

これをしなければInitial Connectに1分から2分程度かかることになる。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?