Terraformでメンテナンス専用のALBを作成する

概要

ALBでは固定レスポンスを返すことができるため、メンテナンス専用のALBを作成して、Route53でDNSを切り替えてメンテナンスページを表示することができます。
AレコードのAliasを指定した場合、TTLが設定できませんが、digで確認する限り60秒なので最長でも60秒でALBに切り替わる想定です。

Terraform

80は443へ301リダイレクトをして、443では503のステータスコードと、固定のHTMLを返すようにします。

  name                       = "maintenance"
  internal                   = false
  load_balancer_type         = "application"
  security_groups            = [aws_security_group.maintenance.id]
  subnets                    = [aws_subnet.public-1a.id]
  enable_deletion_protection = true
}

resource "aws_alb_listener" "maintenance-HTTP" {
  load_balancer_arn = aws_lb.maintenance.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

resource "aws_alb_listener" "maintenance-HTTPS" {
  load_balancer_arn = aws_lb.maintenance.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-2015-05"
  certificate_arn   = aws_acm_certificate.cert-general.arn

  default_action {
    type = "fixed-response"
    fixed_response {
      content_type = "text/html"
      message_body = var.maintenance_body
      status_code  = "503"
    }
  }
}

HTMLは長いので変数に切り出しておきます。

  default = <<EOF
<html>
<head>
<meta charset="utf-8">
<title>Maintenance</title>
<style>
    html{
        margin: 0;
        padding: 0;
        text-align: center;
        height: 100%;
    }
    body{
        position: relative;
        height: 100%;
        background: #eee;
    }
    div{
        position: absolute;
        left: 50%;
        top: 30%;
        margin-left: -300px;
        width: 600px;
        border: 2px solid #666;
        padding: 64px 32px;
        box-sizing: border-box;
        background: #fff;
        text-align: center;
    }   
    .message{
        font-size: 34px;
        margin-bottom: 24px;
        font-weight: bold;
    }
    .date{
        color: #fff;
        padding: 8px;
        background: #cc0000;
        width: 90%;
        margin: 0 auto 16px;
    }
</style>
</head>
<body>
<div>
    <p class="message">ただいまメンテナンス中です</p>
    <p class="date">【メンテナンス日時】2020年12月12日 2:00~7:00</p>
    <p>ご利用の皆様にはご迷惑をおかけし、大変申し訳ございません。<br>
    メンテナンス終了までしばらくお待ちください。</p>
</div>
</body>
</html>
  EOF
}

セキュリティグループです

  name        = "maintenance"
  description = "maintenance"
  vpc_id      = aws_vpc.boy-studio.id

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

  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 = "alb"
  }
}

参考ドキュメント

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener