はじめに
Terraformを使用して、ALBをオリジンにCloudFrontで配信するWebサーバを構築してみました。
前回ALBまで作成したので今回はALBの変更、CloudFrontディストリビューション、Route53ホストゾーンの作成となります。
※今回の構成では、CloudFrontのIPは不確定でALBのSGではCloudFrontに限定したインバウンドアクセス制御ができないため、ALBへのアクセス制限はない状態です。
※ALBに直接アクセスさせないためにはHostヘッダーの制限をCloudFrontのWhitelistとALBリスナールールで行う必要があります。
構成
ALBリスナーとSGの修正
- HTTPリスナーのデフォルトアクションの変更(forward→redirect)
- HTTPSリスナーの追加
※リスナーで競合エラーが出たら、HTTPリスナーを一度削除してからもう再度追加したらいけます - SGインバウンドルール追加(HTTPS)
resource "aws_lb" "alb" {
name = "MyLoadBalancer"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb_sg.id]
subnets = [
aws_subnet.public1.id,
aws_subnet.public2.id
]
enable_deletion_protection = false
}
# HTTPSリスナーでターゲットグループに転送
resource "aws_lb_listener" "https_listner" {
load_balancer_arn = aws_lb.alb.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01"
certificate_arn = "arn:aws:acm:ap-northeast-1:xxxxxxxxxxxx:certificate/b7f2c39b-71e8-4bb3-8595-8a0cfe3738da" # ALBリージョンの証明書
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.lb_tg.arn
}
}
# HTTPリスナーでHTTPSにリダイレクト
resource "aws_lb_listener" "http_listner" {
load_balancer_arn = aws_lb.alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
protocol = "HTTPS"
port = "443"
status_code = "HTTP_301"
}
}
}
resource "aws_lb_target_group" "lb_tg" {
name = "test-lb-tg"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
path = "/health"
}
}
resource "aws_lb_target_group_attachment" "instance1" {
target_group_arn = aws_lb_target_group.lb_tg.arn
target_id = aws_instance.instance1.id
port = 80
}
resource "aws_lb_target_group_attachment" "instance2" {
target_group_arn = aws_lb_target_group.lb_tg.arn
target_id = aws_instance.instance2.id
port = 80
}
resource "aws_security_group" "alb_sg" {
name = "alb-sg"
description = "Allow HTTP and SSH"
vpc_id = aws_vpc.main.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"]
}
}
CloudFrontディストリビューション
- オリジン:ALB
- プロトコルポリシー:HTTPS ONLY
- キャッシュ:テスト目的のため無効化
- プロトコルポリシー:Redirect HTTP to HTTPS
- 代替ドメイン:example.com
- 証明書:us-east-1で発行した証明書
- 地理的制限:なし
resource "aws_cloudfront_distribution" "test_cf" {
origin {
domain_name = aws_lb.alb.dns_name
origin_id = aws_lb.alb.dns_name
custom_origin_config {
origin_protocol_policy = "https-only"
https_port = 443
http_port = 80
origin_ssl_protocols = ["TLSv1.2"]
}
}
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" # Caching Disabled
origin_request_policy_id = "216adef6-5c7f-47e4-b989-5492eafa07d3" # All Viewer
target_origin_id = aws_lb.alb.dns_name
viewer_protocol_policy = "redirect-to-https"
}
enabled = true # ディストリビューションがリクエストを受け付ける
price_class = "PriceClass_200" # 北米、ヨーロッパ、アジアのエッジロケーションのみ使用
aliases = ["example.com"]
viewer_certificate {
acm_certificate_arn = "arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # us-east-1の証明書
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
}
Route53
- シンプルルーティング
- ホストゾーンを作成してAレコードを追加
- エイリアス:CloudFrontのDNS名
resource "aws_route53_zone" "test_zone" {
name = "example.com"
}
resource "aws_route53_record" "test_record" {
zone_id = aws_route53_zone.test_zone.id
name = "example.com"
type = "A"
alias {
name = aws_cloudfront_distribution.test_cf.domain_name
zone_id = aws_cloudfront_distribution.test_cf.hosted_zone_id
evaluate_target_health = false
}
}
確認
ALB
リクエスト処理
$ curl -I https://example.com
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 615
Connection: keep-alive
Date: Sun, 23 Mar 2025 07:49:39 GMT
Accept-Ranges: bytes
Server: nginx/1.22.1
Last-Modified: Tue, 27 Aug 2024 13:55:08 GMT
ETag: "66cddabc-267"
X-Cache: Miss from cloudfront # リクエストがオリジンに送信されている
Via: 1.1 ccec8f7c8547a994f6578dd30ad7acce.cloudfront.net (CloudFront) # CloudFrontを経由して処理
X-Amz-Cf-Pop: NRT57-P6
X-Amz-Cf-Id: jBOQzTgmJg-WR5HPrRle_fXzuhwa0rRsrU0og1Su6zsB3D8cIY23Bw==