はじめに
本ブログではAmazon ECS on AWS Fargate(以下、ECS on Fargate)のスケーリングポリシーを実際に動かして理解します
ECS on Fargateのスケーリングポリシーとは
ECS on Fargateのアーキテクチャで構成されたサービスコンポーネント内のタスクを自動的にスケールイン/スケールアウトさせる仕組みです
Amazon ECS サービスを自動的にスケールする - Amazon Elastic Container Service
前提
構成
ベースとするアーキテクチャはAWS公式ドキュメントのECSサンプルをデプロイしたものです
https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/ecs_example.html
- Amazon ECR 上のパブリックイメージを利用
- インターネットから接続できるApplication Load Balancer が前面にある
- データプレーンはAmazon ECS on Fargate を利用
構成図
デプロイ
- デプロイ方法:AWS CDK
- 言語:TypeScript
デプロイ手順
詳細は公式ドキュメントをご参照ください
ちなみにですが、CDK初期化した状態から以下の数行のソースコードの修正のみで簡単にECS on Fargate 構成のPHP Webアプリケーションをデプロイできます
CDKめちゃめちゃ便利ですね
ファイル:lib/my_ecs_construct-stack.ts
- インポート
import * as ec2 from "aws-cdk-lib/aws-ec2"; import * as ecs from "aws-cdk-lib/aws-ecs"; import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns";
- コンストラクタ
const vpc = new ec2.Vpc(this, "MyVpc", { maxAzs: 3 // Default is all AZs in region }); const cluster = new ecs.Cluster(this, "MyCluster", { vpc: vpc }); // Create a load-balanced Fargate service and make it public new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { cluster: cluster, // Required cpu: 512, // Default is 256 desiredCount: 6, // Default is 1 taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, memoryLimitMiB: 2048, // Default is 512 publicLoadBalancer: true // Default is true });
デプロイが完了すると、ブラウザでインターネットからアクセスできるPHPのサンプルwebサイトが起動します
- URL確認方法:サービス > 設定とネットワークタブ > ネットワーク設定 > DNS名
リソース情報
デプロイされる各リソースの概要は以下の通りです
コンテナイメージ(Amazon ECR)
使用するイメージはAmazon ECR Public Galleryのamazon/amazon-ecs-sampleです amazon/amazon-ecs-sample
タスク定義
CDKのソースコードで定義されている部分は以下の通りでしたが、デフォルトの設定値のままでは少し過剰なリソースなので、一部Default値へ変更することにしました。
変更前
new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { cluster: cluster, // Required cpu: 512, // Default is 256 desiredCount: 6, // Default is 1 taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, memoryLimitMiB: 2048, // Default is 512 publicLoadBalancer: true // Default is true
変更後
new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", { cluster: cluster, // Required cpu: 256, // Default is 256 desiredCount: 1, // Default is 1 taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") }, memoryLimitMiB: 512, // Default is 512 publicLoadBalancer: true // Default is true });
各コンポーネントの要素数
リソース | 数 変更前 |
数 変更後 |
ソースコード指定箇所 |
---|---|---|---|
クラスター | 1 | 1 | new ecs.Cluster(); |
サービス | 1 | 1 | new ecs_patterns.ApplicationLoadBalancedFargateService(): |
タスク | 6 | 1 | desiredCount: |
クラスター
クラスターとはECSを司る最も大きなコンポーネントです。 サンプルCDKでは1つのクラスターが定義されており、この中にサービス>タスクが起動します。
クラスターのページでは以下のような情報が確認できます
サービス
クラスター内で起動されているサービスの数が表示されます
タスク
クラスター内で実行されているタスクの、保留中と実行中の数が表示されます 保留中や実行中とは、ECSのライフサイクル状態を指しています
Amazon ECS タスクライフサイクル - Amazon Elastic Container Service
タスクはサービスの一部として開始されてから終了あるいは停止されるまでさまざまな状態を経由します
以下は公式ドキュメントに記載されていたECSのライフサイクルフロー図です
サンプルのデプロイが完了するとこのうちPending(保留中)の0件とRunning(実行中)が表示されます
なお、CodeDeployなどのCI/CDパイプラインも自動で作成されますが本ブログでは割愛します
タスクの数を手動で変更してみる
サービスを更新より、必要なタスクを1から0、または0から1へ変更してみます
タスク数の変化に応じて保留中や実行中の表示が切り替わることを確認できます
必要なタスクを1から0へ更新直後
必要なタスクを0から1へ更新直後自動でタスク数をスケールさせる
本ブログのメインテーマです
ターゲットメトリクス値を使用してサービス内のタスク数をスケールさせることができます
詳細や考慮事項については以下公式ドキュメントを参照してください
ターゲットメトリクス値を使用して Amazon ECS サービスをスケールする - Amazon Elastic Container Service
スケーリングポリシーを設定する
AutoScalingのスケーリングポリシー同様に任意のメトリクスを指標にして自動でタスク数をスケールイン、スケールアウトする様設定します
手動で変更した時と同様に、「サービスを更新」より 「サービスの自動スケーリング - オプション」項目からタスクの最小数とタスクの最大数を更新します
「サービスの自動スケーリングを使用」をチェックし、タスクの最大数を2に設定します
スケーリングポリシーを以下の通り設定します
- タスクの最小数:1
- タスクの最大数:2
- スケーリングポリシータイプ
- ターゲットの追跡
- ポリシー名:alb-req
- ECS サービスメトリクス:ALBRequestCountPerTarget
- ターゲット値:50
- スケールアウトクールダウン期間:10
- スケールインクールダウン期間:10
- スケールインをオフにする:無効
なお、「ECS サービスメトリクス」は事前定義済みメトリクスの中から選択できます
- ECSServiceAverageCPUUtilization:サービスの平均 CPU 使用率
- ECSServiceAverageMemoryUtilization:サービスのメモリ平均使用率
- ALBRequestCountPerTarget:Application Load Balancer ターゲットグループ内の ターゲットごと に完了したリクエストの数
今回は ALBRequestCountPerTarget をメトリクスに設定します
設定ポリシーを確認する
サービスの設定とネットワークタブから、設定したポリシーを確認できます
アラームの列にフォーカスすると、CloudWatchのアラーム設定内容を確認できるURLリンクが表示されます
...AlermHigh...
が、スケールアウト(タスクの増加)を動作させるためのアラームで、...AlermLow...
が、スケールイン(タスクの減少)を動作させるためのアラームです。
動作確認
実際に負荷をかけてスケールアウト/スケールインする様子を動作確認しました
リクエストの負荷をかける方法はcurlコマンドとwatchコマンドを組み合わせて実行しました
詳細は以下ブログで紹介しています
【Auto Scaling】ターゲットトラッキングスケーリングポリシーを設定してみた 〜その② 動作確認〜 - サーバーワークスエンジニアブログ
ネットワーク設定 タブで確認したDNS名を指定し、コマンドを実行します
watch -n 0.1 curl -s http://[DNS名で確認したURL]/
アラーム画面のグラフからアラームステータスを確認
負荷をかけ始めてから約5分後にアラーム状態の判定となったことを確認しました
負荷をかけてからタスク数が増加するまでに発生したイベントは以下の通りです。
2024年5月02日 14:17 (UTC+9:00) service ContainerPatternAioStack-MyFargateServiceF490C034-jRbO6iNAXMpP has reached a steady state. 65f57d40-d120-4c1e-84ce-cd5ebdc6c5ff 2024年5月02日 14:16 (UTC+9:00) service ContainerPatternAioStack-MyFargateServiceF490C034-jRbO6iNAXMpP registered 1 targets in target-group Contai-MyFar-B5ADXCZXKWQF 1762c93e-2dbf-479b-a3f5-cf323bc2808e 2024年5月02日 14:16 (UTC+9:00) service ContainerPatternAioStack-MyFargateServiceF490C034-jRbO6iNAXMpP has started 1 tasks: task 32c00521245349e7a2005623074f6448. 04ffbb90-239e-4179-b0e2-741db86cbe12 2024年5月02日 14:16 (UTC+9:00) メッセージ: Successfully set desired count to 2. Change successfully fulfilled by ecs. 原因: monitor alarm TargetTracking-service/ContainerPatternAioStack-MyCluster4C1BA579-9fGNAp6dK6Oe/ContainerPatternAioStack-MyFargateServiceF490C034-jRbO6iNAXMpP-AlarmHigh-7c5969aa-4a80-4222-8355-7c1968a2b453 in state ALARM triggered policy alb-req 7dd15a78-9f99-498a-aff4-c1e9eb2303e1
タスクが増えたことでリクエストは半分に分散されたため、メトリクスも半分に下がっていますが、引き続き閾値を超えているリクエスト数が発生しており、アラーム状態は続いている状況です
しかし、最大タスクが2となっていることで、アラーム状態が続いてもこれ以上タスクが増えることはありません
ちなみに、この時は何もイベントは発生しません
最大タスクを3へ変更する
負荷をかけ続けたまま、タスクの最大数を3へ変更します
必要なタスクは2のままで最大数を変更するのがポイントですイベントを確認
イベントメッセージ
2024年5月02日 14:28 (UTC+9:00) メッセージ: Successfully set desired count to 3. Waiting for change to be fulfilled by ecs. 原因: monitor alarm TargetTracking-service/ContainerPatternAioStack-MyCluster4C1BA579-9fGNAp6dK6Oe/ContainerPatternAioStack-MyFargateServiceF490C034-jRbO6iNAXMpP-AlarmHigh-7c5969aa-4a80-4222-8355-7c1968a2b453 in state ALARM triggered policy alb-req 83e1bdc0-c112-4e9f-9984-794914031baa
RequestCountPerTargetの遷移をアラーム画面のグラフで確認
タスク数が1から2、2から3へと増えるごとにターゲットが捌ける数が減って、閾値に近づいていく様子がわかります
その他
動作確認で気づいた点をまとめます
必要なタスク数は自動的に変化する
最大タスク数を元に戻そうとしたところ、「必要なタスク」の数を変更していないにも関わらず3に変わっていることがわかりました
必要なタスクの設定値はスケーリングポリシーの挙動に応じて変化する様です
Amazon ECS サービスを自動的にスケールする - Amazon Elastic Container Service
サービススケジューラは常に必要数を優先しますが、サービスにアクティブなスケーリングポリシーとアラームがある限り、サービスの自動スケーリングはユーザーが手動で設定した必要数を変更できます。
また、最大タスク数を変更する際は必要なタスク数以下に設定する必要があり、自動的に変更された必要なタスク数も合わせて更新しないといけない場合もあります
アラームが新しいものに変わる
スケーリングポリシーのターゲット値を50から300へ変更したところ、既存のアラームが削除されて新しい名前で作成されました
既存の設定値が変更されると思っていましたが、更新するとアラームの設定自体が置き換わる挙動の様です
最後に
ECS on Fargateのコンテナアーキテクチャのスケーリングポリシーを実際に動かして理解しました AWSのコンテナサービスは初学者にとってはパラメーターが複数あり、ドキュメントなどの資料を読んで学ぶには理解し難い側面があります 実際に手を動かすことで体系的に学ぶことができ、より理解が深まると思います