Auto Scaling グループで容量を維持する

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

はじめに

ロードバランサーは障害アプリケーションを避けますが、代替サーバーは作成しません。このラボではテンプレートとグループで 2 台を維持し、障害を発生させて新しいインスタンス ID が実際にリクエストを処理することを確認します。

EC2 User Data、ALB ターゲットグループ、アプリケーションのヘルスチェックの知識が必要です。新しい環境にはネットワーク、アプリケーションイメージ、キーペア、HTTP リスナー付きの空ターゲットグループがあり、既存のサーバー群はありません。CLI と接続ファイルは過去のラボとは独立して準備されています。

認定試験との関連

次の試験分野の入門実習になります。

アプリケーション起動テンプレートを作成する

Auto Scaling が各サーバーを起動するときの設定を定義します。

作業ディレクトリに移動し、準備済みネットワーク変数を読み込みます。

cd /home/labex/project
source launch.env

起動テンプレートは AMI、タイプ、セキュリティグループ、起動設定を保存します。提供されたファイルを確認します。

cat launch-template.json
cat application-user-data.sh

JSON は準備済み AMI、t3.micro、report-key、アプリケーションセキュリティグループを指定します。UserData は別途表示するスクリプトの base64 エンコードです。スクリプトはメッセージを Application ready、healthy を true に初期化します。代替サーバーを準備するには毎回適用が必要です。古いサーバー内の変更はテンプレートを変更しません。

テンプレートを作成します。file:// は JSON の内容をパラメーター値として読み込む指定です。

LT_ID=$(aws ec2 \
  create-launch-template \
  --launch-template-name application-template \
  --launch-template-data file://launch-template.json \
  --query 'LaunchTemplate.LaunchTemplateId' \
  --output text)

テンプレートには番号付きのバージョンがあります。グループで明示的に指定する 1 を確認します。

aws ec2 \
  describe-launch-template-versions \
  --launch-template-id "$LT_ID" \
  --versions 1 \
  --query 'LaunchTemplateVersions[].{Version:VersionNumber,AMI:LaunchTemplateData.ImageId,Type:LaunchTemplateData.InstanceType,Key:LaunchTemplateData.KeyName,Groups:LaunchTemplateData.SecurityGroupIds}'

テンプレート作成だけではインスタンスは起動しません。AWS View を開くと ALB とターゲットグループはありますが、登録済みアプリケーションはありません。

サーバー群を起動して接続する

Auto Scaling グループを作り、実際のインスタンスを提供された ALB に接続します。

Auto Scaling グループは最小と最大の範囲で指定台数を維持します。希望容量は維持する台数であり、スループットの測定値ではありません。最小 2、希望 2、最大 3 は 2 台で開始し、1 台の追加を許可します。

ターゲットグループ ARN とロードバランサーの DNS 名を取得します。

TG_ARN=$(aws elbv2 \
  describe-target-groups \
  --names application-targets \
  --query 'TargetGroups[0].TargetGroupArn' \
  --output text)

LB_DNS=$(aws elbv2 \
  describe-load-balancers \
  --names application-alb \
  --query 'LoadBalancers[0].DNSName' \
  --output text)

バージョン 1 と両サブネットでグループを作ります。--target-group-arns はインスタンスを ALB に自動登録します。--health-check-type ELB は置換判断にロードバランサーの状態を含めます。EC2 のチェックだけでは全アプリ障害を検出できません。猶予期間は新インスタンスの起動時間を確保します。ここでは 30 秒ですが、本番では起動時間に合わせます。

aws autoscaling \
  create-auto-scaling-group \
  --auto-scaling-group-name application-fleet \
  --launch-template "LaunchTemplateId=$LT_ID,Version=1" \
  --min-size 2 \
  --max-size 3 \
  --desired-capacity 2 \
  --vpc-zone-identifier "$SUBNET_ID,$SECOND_SUBNET_ID" \
  --target-group-arns "$TG_ARN" \
  --health-check-type ELB \
  --health-check-grace-period 30

グループとインスタンス ID を確認します。

aws autoscaling \
  describe-auto-scaling-groups \
  --auto-scaling-group-names application-fleet \
  --query 'AutoScalingGroups[].{Min:MinSize,Desired:DesiredCapacity,Max:MaxSize,HealthCheck:HealthCheckType,Grace:HealthCheckGracePeriod,Instances:Instances[].InstanceId}'

アプリケーションの準備完了を待ち、ターゲットを確認します。

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

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

正常な ID が 2 つあることを確認します。6 回リクエストし、応答 ID とグループを比較します。

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

AWS View で容量 2、正常ターゲット 2 台を確認し、Send request で両 ID の実際の 200 応答を観察します。サブネットや可用性ゾーンの表示は設定を表します。この実習では物理的なゾーン間耐障害性は測定しません。

自動障害置換を観察する

アプリケーション障害を発生させ、手動修復せずにグループによる置換を待ちます。

現在のグループから 1 台選び、SSH 用のパブリックアドレスを取得します。

OLD_ID=$(aws autoscaling \
  describe-auto-scaling-groups \
  --auto-scaling-group-names application-fleet \
  --query 'AutoScalingGroups[0].Instances[0].InstanceId' \
  --output text)

OLD_IP=$(aws ec2 \
  describe-instances \
  --instance-ids "$OLD_ID" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

healthy だけを変更し 503 を返させます。前のラボ同様、一時 JSON ファイルで読み込み中の上書きを防ぎます。

ssh -F ssh_config "ubuntu@$OLD_IP" \
  'sudo jq ".healthy = false" /etc/report-app/config.json > /tmp/report-config.json && sudo install -m 644 /tmp/report-config.json /etc/report-app/config.json'

ssh -F ssh_config "ubuntu@$OLD_IP" \
  'curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8081/health'

503 を確認します。インスタンスは動作中でもアプリケーションが故障しています。ALB が検出し、猶予期間後にグループがインスタンスを置換して希望容量を復元します。同じテンプレートが正常設定で代替サーバーを起動します。

AWS View を開いて ID と状態の変化を観察します。検出直後に置換されるため異常状態は短い場合があります。新ターゲットは最初 initial と表示される場合があります。修復や追加の run-instances は実行しません。

古いインスタンスの終了とターゲットの正常化を待ちます。

aws ec2 \
  wait instance-terminated \
  --instance-ids "$OLD_ID"

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

古いインスタンスと現在のグループを確認します。

aws ec2 \
  describe-instances \
  --instance-ids "$OLD_ID" \
  --query 'Reservations[].Instances[].{Instance:InstanceId,State:State.Name}'

aws autoscaling \
  describe-auto-scaling-groups \
  --auto-scaling-group-names application-fleet \
  --query 'AutoScalingGroups[].{Desired:DesiredCapacity,Instances:Instances[].InstanceId}'

古い ID は terminated になり、希望容量 2 のまま新 ID が加わります。代替サーバーは新たに初期化されるため、古いサーバー内だけの変更は自動保存されません。

再度 6 回リクエストします。

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

古い ID がなく、新 ID を含む現在の 2 つの ID を確認します。AWS View で正常ターゲット 2 台を確認し、Send request で代替サーバーの実応答を観察します。資源数だけではアプリの動作は証明できません。

代替インスタンスの応答

例:希望容量は 2 のまま、新インスタンスが HTTP 200 を返します。実際の ID は異なります。

サーバー群とテンプレートを削除する

作成したグループ、インスタンス、テンプレートを削除し、提供された ALB とネットワークを残します。

最小容量が 2 でも終了できるよう --force-delete でグループを削除します。テンプレートだけの削除では実行中インスタンスは停止しません。

aws autoscaling \
  delete-auto-scaling-group \
  --auto-scaling-group-name application-fleet \
  --force-delete

aws ec2 \
  wait instance-terminated \
  --filters "Name=tag:aws:autoscaling:groupName,Values=application-fleet"

aws ec2 \
  delete-launch-template \
  --launch-template-id "$LT_ID"

待機コマンドは Auto Scaling の自動タグでグループのインスタンスを選び、置換済みの古いインスタンスを含め全終了を待ちます。グループ不在、テンプレート一覧、ターゲット登録を確認します。

aws autoscaling \
  describe-auto-scaling-groups \
  --auto-scaling-group-names application-fleet \
  --query 'AutoScalingGroups[].AutoScalingGroupName'

aws ec2 \
  describe-launch-templates \
  --query 'LaunchTemplates[].LaunchTemplateName'

aws elbv2 \
  describe-target-health \
  --target-group-arn "$TG_ARN" \
  --query 'TargetHealthDescriptions[].Target.Id'

3 つとも [] が期待値です。登録解除に時間がかかる場合は少し待って最後の照会を繰り返します。AWS View には ALB とターゲットグループが残り、サーバー群と登録ターゲットは消えます。提供されたネットワーク、AMI、キーペアは残します。

まとめ

バージョン付き起動テンプレートと 2 台を維持するグループを作成しました。ALB ヘルスチェックを置換判断に使い、障害後に新 ID の実応答を検証しました。最後にグループ、インスタンス、テンプレートを削除し、ALB とネットワークを残しました。

次のラボでは単純スケーリングポリシーで希望容量を変更し、上下限を試します。