Application Load Balancer でリクエストを振り分ける

AWSBeginner
オンラインで実践に進む

はじめに

チームには 2 台のアプリケーションサーバーがありますが、クライアントには共通のサービスアドレスが必要です。このラボでは Application Load Balancer を作成し、リスナーをターゲットグループに接続して両方のサーバーを登録します。実際の HTTP 応答で、各リクエストを処理したサーバーを確認できます。

前のコースで学んだ EC2 インスタンス、VPC サブネット、セキュリティグループを理解していることが前提です。環境にはネットワークと稼働中のサーバーが用意され、AWS CLI も設定済みです。負荷分散リソースを作成し、最後に削除します。

認定試験との関連

このラボでは、次の試験項目に関する入門的な実践を行います。

Application Load Balancer を作成する

このステップでは、用意された 2 台のサーバーへの共通の入口を作成します。

Application Load Balancer(ALB)は HTTP または HTTPS リクエストをアプリケーションサーバーに振り分けます。Network Load Balancer(NLB)は TCP や UDP などのトランスポート接続を扱います。この HTTP アプリケーションには ALB が適しているため、ラボ全体で ALB を使います。

用意された作業ディレクトリに移動します。

cd /home/labex/project

launch.env には提供されたネットワークの識別子が記載されています。内容を確認してから、source で変数の代入を現在のシェルに読み込みます。

cat launch.env
source launch.env

SUBNET_ID と SECOND_SUBNET_ID は異なる 2 つのアベイラビリティーゾーンのサブネットを示します。ALB には少なくともこのような 2 つのサブネットが必要です。ALB_SECURITY_GROUP_ID はポート 80 の HTTP リスナー通信を許可する用意済みグループです。サーバーにはアプリケーションポート用の別のグループがあります。

application-alb という名前でインターネット向け ALB を作成します。インターネット向けはアドレス方式を表します。--query は ARN のみを抽出し、--output text は再利用しやすい形式で出力します。シェルの $(...) は出力を LB_ARN に保存します。

LB_ARN=$(aws elbv2 \
  create-load-balancer \
  --name application-alb \
  --type application \
  --scheme internet-facing \
  --subnets "$SUBNET_ID" "$SECOND_SUBNET_ID" \
  --security-groups "$ALB_SECURITY_GROUP_ID" \
  --query 'LoadBalancers[0].LoadBalancerArn' \
  --output text)

Amazon Resource Name(ARN)は AWS リソースを識別します。保存した ARN を使ってロードバランサーを確認します。

aws elbv2 \
  describe-load-balancers \
  --load-balancer-arns "$LB_ARN" \
  --query 'LoadBalancers[].{Name:LoadBalancerName,Type:Type,Scheme:Scheme,DNS:DNSName}'

名前 application-alb、タイプ application、方式 internet-facing を確認します。DNS 名はクライアントが使うアドレスで、環境ごとに異なります。ロードバランサーを作成しただけでは、サーバーはまだ接続されていません。

Terminal の隣の AWS View をクリックします。このページは CLI と同じリソース状態を読み取り、application-alb を表示します。まだ接続していないため、ターゲットグループとターゲットの領域は空です。

ターゲットグループ接続前の ALB

画像は作成直後の確認ポイントです。リソース名はラボと同じですが、DNS 名は例です。

リスナーをターゲットグループに接続する

このステップでは、受信した HTTP リクエストの転送先を定義します。

ターゲットグループにはアプリケーションを提供するサーバーが含まれます。そのポートはサーバーへの接続に使われます。リスナーはロードバランサーでクライアント接続を受け付け、アクションで転送先を決めます。ここではクライアントはポート 80 を使い、サーバーのアプリケーションは 8081 で動作します。

提供された VPC にインスタンスタイプのターゲットグループを作成します。--target-type instance は EC2 インスタンス ID を登録することを意味します。/health はアプリケーションの準備状態を確認するエンドポイントです。

TG_ARN=$(aws elbv2 \
  create-target-group \
  --name application-targets \
  --protocol HTTP \
  --port 8081 \
  --vpc-id "$VPC_ID" \
  --target-type instance \
  --health-check-path /health \
  --query 'TargetGroups[0].TargetGroupArn' \
  --output text)

HTTP リスナーを作成します。デフォルトアクションは TG_ARN にリクエストを転送します。CLI の短縮形式 Type=forward,TargetGroupArn=... でこのアクションを指定します。

LISTENER_ARN=$(aws elbv2 \
  create-listener \
  --load-balancer-arn "$LB_ARN" \
  --protocol HTTP \
  --port 80 \
  --default-actions "Type=forward,TargetGroupArn=$TG_ARN" \
  --query 'Listeners[0].ListenerArn' \
  --output text)

作成したリスナーを確認します。

aws elbv2 \
  describe-listeners \
  --load-balancer-arn "$LB_ARN" \
  --query 'Listeners[].{Protocol:Protocol,Port:Port,Actions:DefaultActions}'

出力には HTTP ポート 80 と、自分のターゲットグループへの転送アクションが表示されます。AWS View では ALB とサーバー領域の間にグループが表示されます。まだターゲットが登録されていないため、サーバーを接続する必要があります。

2 台のサーバーを登録してテストする

このステップでは稼働中の 2 台を登録し、実際のリクエストが両方に到達することを確認します。

用意されたサーバーを一覧表示します。名前フィルターでタグを選択し、クエリで接続に役立つ項目を表示します。

aws ec2 \
  describe-instances \
  --filters 'Name=tag:Name,Values=app-a,app-b' \
  --query 'Reservations[].Instances[].{Instance:InstanceId,Name:Tags[?Key==`Name`].Value|[0],State:State.Name,PrivateIP:PrivateIpAddress}' \
  --output table

両方のインスタンスが running であることを確認します。名前ごとに ID を個別に取得すると、一覧の順序に依存しません。

APP_A=$(aws ec2 \
  describe-instances \
  --filters 'Name=tag:Name,Values=app-a' \
  --query 'Reservations[0].Instances[0].InstanceId' \
  --output text)
APP_B=$(aws ec2 \
  describe-instances \
  --filters 'Name=tag:Name,Values=app-b' \
  --query 'Reservations[0].Instances[0].InstanceId' \
  --output text)

ターゲットの登録で、この ID がターゲットグループに接続されます。Port を明示的に上書きしない場合、各ターゲットはグループのポート 8081 を使います。

aws elbv2 \
  register-targets \
  --target-group-arn "$TG_ARN" \
  --targets "Id=$APP_A" "Id=$APP_B"

ALB は /health を調べて可用性を判断します。ターゲットが正常になるまで待ちます。CLI の waiter は、条件を満たすかタイムアウトするまで読み取り専用の状態確認を繰り返します。

aws elbv2 \
  wait target-in-service \
  --target-group-arn "$TG_ARN"

登録したターゲットの ID、ポート、ヘルス状態を確認します。

aws elbv2 \
  describe-target-health \
  --target-group-arn "$TG_ARN" \
  --query 'TargetHealthDescriptions[].{Instance:Target.Id,Port:Target.Port,Health:TargetHealth.State}' \
  --output table

両方にポート 8081 と状態 healthy が表示されるはずです。ロードバランサーの DNS 名を保存します。

LB_DNS=$(aws elbv2 \
  describe-load-balancers \
  --load-balancer-arns "$LB_ARN" \
  --query 'LoadBalancers[0].DNSName' \
  --output text)

HTTP クライアント curl でヘルスエンドポイントにリクエストします。--config client.conf は提供された接続設定を読み込み、-sS は進捗を隠しつつエラーを表示します。

curl --config client.conf -sS "http://$LB_DNS/health"

成功した応答は次の例のようになります。インスタンス ID は例です。

{"service":"Report server","message":"Application ready","instance_id":"i-..."}

6 回の独立したリクエストを送信します。for ループは同じリクエストを繰り返し、echo は応答ごとに改行します。

for request in 1 2 3 4 5 6; do
  curl --config client.conf -sS "http://$LB_DNS/health"
  echo
done

応答に APP_A と APP_B の値があることを確認します。これは 2 台への分配を示すもので、リクエスト数から性能や容量は判断しないでください。デフォルトのアルゴリズムはラウンドロビンです。本番環境では接続や他の設定も分配に影響します。

AWS View を開き、両方が正常であることを確認します。Send request を何度かクリックし、応答の instance_id を読みます。リクエストはリスナーを通ってアプリケーションに届きます。カードはリソース状態を示し、応答は実際に処理したサーバーを示します。

正常な 2 つのターゲットと実際の応答

例には正常な 2 つのターゲットと成功したリクエストが表示されています。あなたの ID は異なるため、自分のターゲット ID と照合してください。

負荷分散リソースを削除する

このステップでは、自分が作成したリソースを削除し、提供されたサーバーとネットワークを残します。

最初にリスナーを削除して、ターゲットグループへの転送依存関係を解除します。

aws elbv2 \
  delete-listener \
  --listener-arn "$LISTENER_ARN"

ロードバランサーを削除してから、そのターゲットグループを削除します。

aws elbv2 \
  delete-load-balancer \
  --load-balancer-arn "$LB_ARN"
aws elbv2 \
  delete-target-group \
  --target-group-arn "$TG_ARN"

両方の負荷分散リソース一覧が空であることを確認します。

aws elbv2 \
  describe-load-balancers \
  --query 'LoadBalancers[].LoadBalancerName'
aws elbv2 \
  describe-target-groups \
  --query 'TargetGroups[].TargetGroupName'

各クエリは [] を返すはずです。AWS View にロードバランサーとグループがないことを確認します。提供された EC2 サーバーは稼働したままです。これらは準備リソースであり、あなたの削除対象ではありません。

まとめ

Application Load Balancer を作成し、HTTP リスナーをターゲットグループに接続して 2 台の EC2 サーバーを登録しました。ヘルス状態を確認し、実際の応答から両方のサーバーを識別しました。最後に、自分の負荷分散リソースを削除し、用意されたサーバーとネットワークを残しました。

次のラボでは、ヘルスチェックがアプリケーション障害を検出し、正常なターゲットでサービスを継続し、復旧したターゲットを再参加させる仕組みを学びます。