Global Accelerator + ALB で www 付きドメインへのリダイレクトを CloudFormation 一撃してみた
AWS事業本部の梶原@福岡オフィスです。
外部DNSサービスを使用している場合、Zone Apex ドメイン(例:example.com)から www 付きドメイン(例:www.example.com)へのリダイレクトを実現するには、DNSへA レコードの登録が必要で、固定IPアドレスが必要になります。今回は、AWS Global AcceleratorとALBを組み合わせたソリューションをCloudFormationで一発構築する方法をご紹介します。
なお、ドメインをRoute53 で管理している場合、ALIAS レコードを使用することにより固定IPを使用せずに、Zone Apex に対して設定することができますので、以下のような構成で対応することができます。
Zone Apex のドメインをリダイレクトする場合のコストや運用の手間などを鑑みた私のお勧め順です。
実装方法はたくさん紹介されているので割愛します
Route53 で管理して(ALIAS レコードを使って)
- S3 Website Hosting でリダイレクト(HTTPのみ)
- CloudFront + S3 Website Hosting でリダイレクト(HTTPSも)
- CloudFront + Lamada@Edge でリダイレクト
- CloudFront + CloudFunctions でリダイレクト
- API-Gateway + Lambda でリダイレクト
外部のDNS で管理して(A レコードを使って)
- Global Accelerator + ALB でリダイレクト (本ブログ)
- EC2 にEIPつけて、Apache/nginx などで頑張る
他にもあるかと思いますが今回は、Global Accelerator + ALB でリダイレクト をやる機会があるかもよ。ということでブログ書いてみました。
詳細は後述しますが、お急ぎの方は、末尾にあるCloudFormation Template からスタックを作成してください
ユースケース
- Route53ではなく外部DNSサービスを使用していて、ALIASレコードが使用できません
- グローバルに展開するWebサイトで低レイテンシーなリダイレクトが必要です
- リクエスト数が予測できないのでスケールする必要があります
- HTTPのみで良い(HTTPSをサポートする必要がある場合の追加部分は説明補足しています)
- なるはやで
各リソースの説明
ALBリスナーの設定
今回のリダイレクトのメイン処理です。HTTPのみのリスナーのリダイレクトルールを設定しています。
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
Protocol: HTTP
Port: 80
DefaultActions:
- Type: redirect
RedirectConfig:
Protocol: HTTPS
Port: '443'
Host: 'www.#{host}'
Path: '/#{path}'
Query: '#{query}'
StatusCode: HTTP_301
- ホストヘッダーを利用した動的リダイレクトを設定します
- HTTPSへの自動リダイレクトを行います
Global Acceleratorの設定
GlobalAccelerator:
Type: AWS::GlobalAccelerator::Accelerator
Properties:
Name: domain-redirect-accelerator
IpAddressType: IPV4
Enabled: true
- 固定IPv4アドレスを提供します
出力設定
Outputs:
GlobalAcceleratorIPs:
Value: !Join
- ', '
- !GetAtt GlobalAccelerator.Ipv4Addresses
- DNSで設定する固定IPアドレスを出力します
完全なテンプレートはブログ最後で公開しています。
注意点
- 個別ドメイン設定の推奨
- 提示したテンプレートは全てのドメインをwww付きにリダイレクトします
- 本番環境では以下のような特定のドメインに対してリスナールールの使用を推奨します:
ListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Priority: 1
Conditions:
- Field: host-header
Values:
- example.com
Actions:
- Type: redirect
RedirectConfig:
Protocol: HTTPS
Port: '443'
Host: 'www.example.com'
Path: '/#{path}'
Query: '#{query}'
StatusCode: HTTP_301
- HTTPSの実装
- 本番環境ではACM証明書を使用したHTTPSの実装を推奨します
- 証明書の取得と検証が必要です
Certificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: example.com
SubjectAlternativeNames:
- www.example.com
ValidationMethod: DNS
- DNSの設定
Outputに出力されたGlobal Accelerator のIPv4 アドレスをDNSに登録してください
example.com. A <Global Accelerator IP 1>
example.com. A <Global Accelerator IP 2>
まとめ
CloudFormationを使用することで、Global AcceleratorとALBを組み合わせたwwwリダイレクト環境を簡単に構築できます。
Route53以外のDNSサービスを使用している場合の実装の参考になれば幸いです
参考
テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Apex Domain to www redirect using ALB with optional Global Accelerator'
Parameters:
UseGlobalAccelerator:
Type: String
Description: 'Whether to use Global Accelerator'
AllowedValues:
- 'true'
- 'false'
Default: 'false'
Conditions:
CreateGlobalAccelerator: !Equals [!Ref UseGlobalAccelerator, 'true']
Resources:
# VPC for ALB
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: RedirectVPC
# Public Subnets
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: RedirectPublicSubnet1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: RedirectPublicSubnet2
# Internet Gateway
InternetGateway:
Type: AWS::EC2::InternetGateway
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# Route Table
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
# Application Load Balancer
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for ALB
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
SecurityGroups:
- !Ref ALBSecurityGroup
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
Type: application
# ALB Listener
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: 80
Protocol: HTTP
DefaultActions:
- Type: redirect
RedirectConfig:
Protocol: HTTPS
Port: '443'
Host: 'www.#{host}'
Path: '/#{path}'
Query: '#{query}'
StatusCode: HTTP_301
# Global Accelerator (Conditional)
GlobalAccelerator:
Type: AWS::GlobalAccelerator::Accelerator
Condition: CreateGlobalAccelerator
Properties:
Name: domain-redirect-accelerator
IpAddressType: IPV4
Enabled: true
Listener:
Type: AWS::GlobalAccelerator::Listener
Condition: CreateGlobalAccelerator
Properties:
AcceleratorArn: !Ref GlobalAccelerator
PortRanges:
- FromPort: 80
ToPort: 80
Protocol: TCP
EndpointGroup:
Type: AWS::GlobalAccelerator::EndpointGroup
Condition: CreateGlobalAccelerator
Properties:
ListenerArn: !Ref Listener
EndpointGroupRegion: !Ref 'AWS::Region'
EndpointConfigurations:
- EndpointId: !Ref ApplicationLoadBalancer
Weight: 100
ClientIPPreservationEnabled: true
Outputs:
EndpointToUse:
Description: Endpoint to use for DNS configuration
Value: !If
- CreateGlobalAccelerator
- !GetAtt GlobalAccelerator.DnsName
- !GetAtt ApplicationLoadBalancer.DNSName
GlobalAcceleratorIPs:
Condition: CreateGlobalAccelerator
Description: Static IP addresses for Global Accelerator (use these for Apex domain A records)
Value: !Join
- ', '
- !GetAtt GlobalAccelerator.Ipv4Addresses