皆様こんにちは。
今回はCloudFormationを利用して高可用性アーキテクトの構築をしていきます。
この記事ではCloudFormationよりロードバランサーの一種であるALBの作成を行います。
このブログはCloudFormationによるALBの作成をする上での知識を記事としてまとめ再確認し、皆様と共有するため作成します。

1.高可用性アーキテクト構築目次

目次はこちら

2.ロードバランサーとは

ELB (Elastic Load Balancing) は、アプリケーションへのトラフィックを、1 つまたは複数のアベイラビリティーゾーン (AZ) 内の複数のターゲットおよび仮想アプライアンスに自動的に分散します。
引用:Amazon Elastic Load Balancing

Application Load Balancer(ALB)

ALBはアプリケーションレイヤーで機能し、HTTPトラフィックおよびHTTPSトラフィックの負荷分散をします。

Network Load Balancer(NLB)

NLBはトランスポートレイヤーで機能し、TCP,UDP,TLSにおけるトラフィックの負荷分散します。

Gateway Load Balancer(GWLB)

GWLBはネットワークレイヤーで機能します。
GENEVE をサポートするサードパーティーの仮想アプライアンスのフリートをデプロイおよび管理する必要がある場合は、GWLBを利用します。

Classic Load Balancer(CLB)

CLBは、アプリケーションレイヤーとトランスポートレイヤー両方で機能します。
EC2-Classic ネットワークで既存のアプリケーションを実行している場合は、CLBを利用します。

今回はアプリケーションレイヤーでトラフィックを振り分け負荷分散したいので、ALBを利用します。

類似サービスとしては負荷に応じてリソース数をスケーリングする「AWS Auto Scaling」があげられます。

3フロー図

file
今回のALB構築のフローは以下になります。

  1. ALB本体の作成をします。
  2. ターゲットグループを作成して、ターゲットに前回作成した二つのEC2インスタンスを指定します。
  3. リスナーの追加をします。(Wordpress上でhttps設定を完了するまではHTTPリスナーも追加します)

4.ALB構築

ALBの構築の全体のソースコードは下記の通りです。
ファイル名「ut-ALB-CF」

AWSTemplateFormatVersion: "2010-09-09"
Resources:
#ALB作成
  LoadBalancerResource:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: "ut-ALB"
      Scheme: "internet-facing"
      Type: "application"
      Subnets: 
      - !ImportValue ut-pubsubnet-1-id
      - !ImportValue ut-pubsubnet-2-id
      SecurityGroups: 
      - !ImportValue ut-SG-ALB-id
      IpAddressType: "ipv4"
      Tags:
      -
        Key: "Name"
        Value: "ut-ALB"

#ターゲットグループ作成
  TargetGroupResource:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      Name: "ut-TGN"
      VpcId: !ImportValue ut-vpc-id
      Protocol: "HTTP"
      ProtocolVersion: "HTTP1"
      Port: 80
      TargetType: "instance"
      Targets: 
      - 
        Id: !ImportValue ut-Instance-id-1
        Port: 80
      - 
        Id: !ImportValue ut-Instance-id-2
        Port: 80
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: "/"
      HealthCheckPort: "traffic-port"
      HealthCheckProtocol: "HTTP"
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 5
      UnhealthyThresholdCount: 2
      Matcher: 
        HttpCode: "200,301"
      Tags:
      -
        Key: "Name"
        Value: "ut-TGN"

#リスナー設定
  ListenerResource:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      LoadBalancerArn: !Ref LoadBalancerResource
      Port: 80
      Protocol: "HTTP"
      DefaultActions: 
      - 
        TargetGroupArn: !Ref TargetGroupResource
        Type: "forward"

#Outputsセクション設定  
Outputs:
  ALBOutput1:
    Value: !GetAtt LoadBalancerResource.DNSName
    Export:
      Name: ut-alb-dnsname
  ALBOutput2:
    Value: !GetAtt LoadBalancerResource.CanonicalHostedZoneID
    Export:
      Name: ut-alb-hostzoneid

ALB作成、ターゲットグループ作成、リスナー設定、Outputsセクション設定のソースコードをそれぞれ説明していきます。

4-1.ALB作成

まずALB本体を作成します。
ALBの作成のソースコードは下記の通りです。

#ALB作成
  LoadBalancerResource:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: "ut-ALB"
      Scheme: "internet-facing"
      Type: "application"
      Subnets: 
      - !ImportValue ut-pubsubnet-1-id
      - !ImportValue ut-pubsubnet-2-id
      SecurityGroups: 
      - !ImportValue ut-SG-ALB-id
      IpAddressType: "ipv4"
      Tags:
      -
        Key: "Name"
        Value: "ut-ALB"

設定項目は下記の通りです。

使用するオプション 設定値 説明
Name ut-ALB ALBの名前を入力
Scheme internet-facing 外部に公開するため
Type application ロードバランサの種類はALBを指定
Subnets !ImportValue ut-pubsubnet-1-id
!ImportValue ut-pubsubnet-2-id
二つのパブリックサブネットのIDを参照
SecurityGroups !ImportValue ut-SG-ALB-id ALB用のSGのIDを参照
IpAddressType ipv4 ipv6を使用しないためipv4のみ指定
Tags Key=Name,Value=ut-ALB タグを入力

これでALB作成のソースコードの説明は以上です。

4-2.ターゲットグループ

次にターゲットグループ(以下TGN)の作成をします。
ターゲットグループには前回作成した二つのEC2を指定し、負荷分散の対象にします。

4-2-1.ターゲットグループとは

各ターゲットグループは、1 つ以上の登録されているターゲットにリクエストをルーティングするために使用されます。各リスナーのルールを作成するときに、ターゲットグループと条件を指定します。ルールの条件が満たされると、トラフィックが該当するターゲットグループに転送されます。さまざまなタイプのリクエストに応じて別のターゲットグループを作成できます。
引用:Application Load Balancer のターゲットグループ

4-2-2.ターゲットグループ作成

ターゲットグループ作成のソースコードは下記の通りです。

#ターゲットグループ作成
  TargetGroupResource:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      Name: "ut-TGN"
      VpcId: !ImportValue ut-vpc-id
      IpAddressType: "ipv4"
      Protocol: "HTTP"
      ProtocolVersion: "HTTP1"
      Port: 80
      TargetType: "instance"
      Targets: 
      - 
        Id: !ImportValue ut-Instance-id-1
        Port: 80
      - 
        Id: !ImportValue ut-Instance-id-2
        Port: 80
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: "/"
      HealthCheckPort: "traffic-port"
      HealthCheckProtocol: "HTTP"
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 5
      UnhealthyThresholdCount: 2
      Matcher: 
        HttpCode: "200,301"
      Tags:
      -
        Key: "Name"
        Value: "ut-TGN"

設定項目は下記の通りです。

使用するオプション 設定値 説明
Name ut-TGN TGNのネームを設定
VpcId !ImportValue ut-vpc-id VPCのIDを参照
IpAddressType ipv4 今回はipv6を使用しないため、ipv4のみ指定
Protocol HTTP プロトコルを指定
ProtocolVersion HTTP1 プロトコルのversionを指定
Port 80 ポート番号を指定
TargetType instance ターゲットタイプにインスタンスを指定
Targets !ImportValue ut-Instance-id-1
!ImportValue ut-Instance-id-2
インスタンスIDを参照
HealthCheckEnabled true ヘルスチェックを有効化します
HealthCheckIntervalSeconds 30 間隔
HealthCheckPath / 要件がないためデフォルト
HealthCheckPort traffic-port 要件がないためデフォルト
HealthCheckProtocol HTTP プロトコルの設定
HealthCheckTimeoutSeconds 5 タイムアウト
HealthyThresholdCount 5 正常のしきい値
UnhealthyThresholdCount 2 非正常のしきい値
Matcher HttpCode: "200,301" 成功コードを指定
Tags Key=Name,Value=umemoto-TGN タグを設定

これでターゲットグループ作成のソースコードの説明は以上です。

4-3.リスナー設定

最後にリスナーの設定をします。
WordPress上でhttps設定をするまでは一時的にhttpを使用するのでリスナーに追加します。

4-3-1.リスナーとは

Application Load Balancer の使用を開始する前に、1 つまたは複数のリスナーを追加する必要があります。リスナーとは、設定したプロトコルとポートを使用して接続リクエストをチェックするプロセスです。リスナーに対して定義したルールにより、ロードバランサーが登録済みターゲットにリクエストをルーティングする方法が決まります。
引用:Application Load Balancer のリスナー

4-3-2.リスナー作成

リスナー設定のソースコードは下記の通りです。

#リスナー設定
  ListenerResource:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      LoadBalancerArn: !Ref LoadBalancerResource
      Port: 80
      Protocol: "HTTP"
      DefaultActions: 
      - 
        TargetGroupArn: !Ref TargetGroupResource
        Type: "forward"

設定項目は下記の通りです。

使用するオプション 設定値 説明
LoadBalancerArn !Ref LoadBalancerResource  ALBのARNを参照
Port 80 ポート番号を入力
Protocol HTTP プロトコルを指定
DefaultActions TargetGroupArn: !Ref TargetGroupResource
Type: "forward"
TGNのARNを参照

これでリスナー設定のソースコードの説明は以上です。

4-4.Outputsセクション設定

Outputsセクション設定のソースコードは下記の通りです。

#Outputsセクション設定  
Outputs:
  ALBOutput1:
    Value: !GetAtt LoadBalancerResource.DNSName
    Export:
      Name: ut-alb-dnsname
  ALBOutput2:
    Value: !GetAtt LoadBalancerResource.CanonicalHostedZoneID
    Export:
      Name: ut-alb-hostzoneid

設定項目は下記の通りです。

使用するオプション 設定値 説明
Value !GetAtt LoadBalancerResource.DNSName
!GetAtt LoadBalancerResource.CanonicalHostedZoneID 
ALBのDNS名とホストゾーンIDを参照
Name ut-alb-dnsname
ut-alb-hostzoneid
設定した名前で出力

これでOutputsセクション設定のソースコードの説明は以上です。

5.検証

スタック作成後、ALBの検証を行っていきます。

5-1.疎通確認

PowershellのTest-NetConnectionコマンドを利用して今回作成したALBに対し通信確認を行います。
検証のため、ALBのDNS名を利用し以下のコマンドを使用します。

Test-NetConnection ut-ALB-878921977.ap-northeast-2.elb.amazonaws.com -port 80

出力

ComputerName     : ut-ALB-878921977.ap-northeast-2.elb.amazonaws.com
RemoteAddress    : 13.209.120.244
RemotePort       : 80
InterfaceAlias   : Wi-Fi
SourceAddress    : 192.168.1.11
TcpTestSucceeded : True

以上の出力からALBに対しHTTPで接続できることを確認できました。

5-2.フェイルオーバー検証

現在ALBを利用して二台のEC2インスタンスを負荷分散しながら運用していますが、ここで片方のEC2インスタンスを停止させてもWordpressを正常に動作させ続けられるかの検証を行います。
作成時同様EC2インスタンスの操作はCLIで行います。
※こちらの検証はACM構築後に行っています。

①まずWordpressのダッシュボードに移動しページを表示しておきます。
file
②片方のEC2インスタンスを停止するため以下のコマンドを使用します。

aws ec2 stop-instances --instance-ids [instance_id]

出力

{
    "StoppingInstances": [
        {
            "CurrentState": {
                "Code": 64,
                "Name": "stopping"
            },
            "InstanceId": "i-xxxxx",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}

③停止できたか、以下のコマンドを使用して確認します。

aws ec2 describe-instances --instance-ids i-xxxxx --query "Reservations[].Instances[].State[].{InstanceStatus:Name}"

出力

[
    {
        "InstanceStatus": "stopped"
    }
]

停止を確認できました。

④最後にダッシュボードのページを再表示してもエラーにならないか確認します。「F5キー」でリロードします。
file

再度問題なく表示することができました。

これで検証を終わります。

6.感想

特に問題なくALBの作成を行うことができました。
次回はRoute53の設定を行っていきます。

7.参照

AWS CloudFormation – AWS::ElasticLoadBalancingV2::LoadBalancer
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html
AWS CloudFormation – AWS::ElasticLoadBalancingV2::TargetGroup
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html
AWS CloudFormation – AWS::ElasticLoadBalancingV2::Listener
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listener.html

Last modified: 2022-06-22

Author