

# Amazon ECS 自動スケーリングとキャパシティ管理におけるベストプラクティス
<a name="capacity-availability"></a>

Amazon ECS では、全サイズのコンテナ化されたアプリケーションワークロードを実行できます。これには、最小限のテスト環境と、グローバル規模で運用される大規模な本番環境が含まれます。

Amazon ECS と併せて、すべての AWS サービスと同様に、使用した分だけお支払いいただきます。アプリケーションを適切に設計することで、必要なときに必要なリソースのみを消費することでコストを削減できます。

以下の推奨事項は、Amazon ECS ワークロードを実行してサービスレベルの目標を達成しつつ、費用対効果の高い運用を行う方法を示しています。

**Topics**
+ [

# Amazon ECS のタスクサイズの決定
](capacity-tasksize-best-practice.md)
+ [

# Amazon ECS サービスの自動スケーリングの最適化
](capacity-autoscaling-best-practice.md)
+ [

# Amazon ECS のキャパシティとアベイラビリティ
](capacity-availability-best-practice.md)
+ [

# Amazon ECS クラスターのキャパシティ
](capacity-cluster-best-practice.md)
+ [

# Amazon ECS の Fargate タスクサイズの選択
](fargate-task-size-best-practice.md)
+ [

# Amazon EC2 でキャパシティプロバイダーを使用して Amazon ECS クラスターのキャパシティプロビジョニングを高速化する
](capacity-cluster-speed-up-ec2-best-practice.md)

# Amazon ECS のタスクサイズの決定
<a name="capacity-tasksize-best-practice"></a>

Amazon ECS にコンテナをデプロイする際に、最も重要な選択項目の 1 つとなるのがコンテナとタスクのサイズです。コンテナサイズとタスクサイズは、スケーリングとキャパシティプランニングに不可欠な要素です。

Amazon ECS では、CPU とメモリの 2 種類のリソースメトリクスがキャパシティに使用されます。Amazon ECS では、CPU 量 は、フル vCPU の 1024 分の 1 の単位で測定されます (1024 ユニットは 1 つの全 vCPU に相当します)。Amazon ECS はメモリをメガバイト単位で測定します。

タスク定義では、リソースの予約と制限を宣言できます。

予約を宣言する際は、タスクに最低限必要な量のリソースを宣言します。タスクはリクエストに必要となる最低限の量のリソースを受け取ります。アプリケーションは、宣言された予約量よりも多くの CPU またはメモリを使用できる可能性があります。ただし、これには宣言した制限も適用されます。

予約量を超えるリソースを使用することをバーストと呼びます。バーストとは、アプリケーションが予約したよりも多くのリソースを使用するが、宣言された制限内にとどまることを意味します。Amazon ECS は、予約量を保証します。たとえば、Amazon EC2 インスタンスを使用してキャパシティを提供する場合、Amazon ECS は予約量を満たせないインスタンスにはタスクを課しません。

制限は、コンテナまたはタスクが使用できる CPU ユニットまたはメモリの最大量です。コンテナがこの制限よりも多くの CPU を使用しようとすると、Amazon ECS によってスロットリングされます。コンテナがこの制限よりも多くのメモリを使用しようとすると、Amazon ECS はコンテナを停止します。

これらの値の決定は簡単ではありません。アプリケーションに最も適した値は、そのアプリケーションのリソース要件に大きく依存します。

アプリケーションの負荷テストは、リソース要件をうまく計画する上で重要です。負荷テストは、アプリケーションの要件をよりよく理解するのに役立ちます。

## ステートレスアプリケーション
<a name="capacity-tasksize-stateless"></a>

ロードバランサーの背後にあるアプリケーションなど、水平にスケーリングするタイプのステートレスアプリケーションでは、まずそのアプリケーションがリクエストを処理するときに消費するメモリの量がどの程度になるかを確認することをお勧めします。

そのためには、`ps` や `top` などの従来のツールを使用できます。CloudWatch Container Insights などのモニタリングソリューションを使用することもできます。

CPU 予約を決定する際には、ビジネス要件を満たすためにアプリケーションをどのようにスケーリングすべきかを考慮します。

256 CPU ユニット (つまりフル vCPU の 4 分の 1) などの小さめの CPU 予約を行うことで、コストを最小限に抑えながらきめ細かくスケールアウトできます。ただし、需要が急増した時にスケーリング速度が追い付かない可能性があります。

より大きな CPU 予約量を使用すると、より迅速にスケールインおよびスケールアウトできます。これにより、需要の急増に迅速に対応できます。ただし、CPU の予約量が多いほどコストが高くなります。

## その他のアプリケーション
<a name="capacity-tasksize-other"></a>

シングルトンワーカーやデータベースサーバーなど、水平にスケーリングしないタイプのアプリケーションでは、利用可能な容量とコストが最も重要な考慮事項となります。

トラフィックを処理し、サービスレベル目標を達成するためには、負荷テストの結果を確認したうえで必要なメモリと CPU の量を決定します。Amazon ECS は、アプリケーションが十分な容量のあるホストに確実に配置されるようにします。

# Amazon ECS サービスの自動スケーリングの最適化
<a name="capacity-autoscaling-best-practice"></a>

Amazon ECS サービスは管理されたタスクのコレクションです。各サービスには、関連するタスク定義、必要なタスク数、オプションの配置戦略があります。

Amazon ECS サービスの自動スケーリングは、アプリケーション自動スケーリングサービスを通して行われます。Application Auto Scaling は CloudWatch メトリクスをスケーリングメトリクスのソースとして使用します。また、CloudWatch アラームを使用して、サービスをスケールインまたはスケールアウトするタイミングのしきい値を設定します。

スケーリングのしきい値を指定します。メトリクスターゲットを設定できます。これは*ターゲット追跡スケーリング*と呼ばれています。しきい値を指定することもできます。これは*ステップスケーリング*と呼ばれています。

アプリケーション自動スケーリングを設定した後、サービスに必要となる適切なタスク数が継続的に計算されます。また、必要なタスク数を変更する必要がある場合、スケールアウトまたはスケールインによって Amazon ECS に通知します。

サービスの自動スケーリングを効果的に使用するには、適切なスケーリングメトリクスを選択する必要があります。メトリクスの選択方法については、以下のセクションで説明します。

## アプリケーションの特徴付け
<a name="capacity-autoscaling-app"></a>

アプリケーションを適切にスケーリングするには、アプリケーションをスケールインする条件とスケールアウトするタイミングを知る必要があります。

基本的に、需要がキャパシティを上回ると予測される場合は、アプリケーションをスケールアウトする必要があります。逆に、リソースが需要を上回る場合は、アプリケーションをスケールインすることでコストを節約できます。

### 使用率メトリクスの特定
<a name="capacity-autoscaling-app-utilizationmetric"></a>

効果的にスケーリングするには、使用率または飽和度を示すメトリクスを特定する必要があります。このメトリクスがスケーリングに役立つためには、以下の特性を備えている必要があります。
+ メトリクスは需要と相関している必要があります。リソースを一定に保っていても需要が変化する場合は、メトリクスの値も変化させる必要があります。需要が増減すると、メトリクスも増減します。
+ メトリクスの値はキャパシティに比例してスケールインする必要があります。需要が一定であれば、リソースを追加すると、メトリクスの値も比例して変化する必要があります。そのため、タスクの数を 2 倍にすると、指標は 50% 減少するはずです。

使用率メトリクスを特定する最良の方法は、ステージング環境などの実稼働前の環境で負荷テストを行うことです。商用およびオープンソースの負荷テストソリューションは広く利用可能です。これらのソリューションは通常、合成負荷を生成することも、実際のユーザートラフィックをシミュレートすることもできます。

負荷テストのプロセスを開始するには、アプリケーションの使用率メトリクスを表示するダッシュボードを最初に構築する必要があります。これらのメトリクスには、CPU 使用率、メモリ使用率、I/O 操作、I/O キューの深さ、ネットワークスループットが含まれます。これらのメトリクスは CloudWatch Container Insights などのサービスを使用して収集できます。また、Amazon Managed Grafana と一緒に Amazon Managed Service for Prometheus を使用して収集することもできます。このプロセスでは、アプリケーションの応答時間や作業完了率に関するメトリクスを必ず収集してプロットしてください。

負荷テストを実施する際は、まず小さなリクエストまたはジョブ挿入率から開始します。アプリケーションがウォームアップできるように、このレートを数分間一定に保ってください。その後、速度をゆっくりと上げて、数分間一定に保ちます。アプリケーションの応答時間または完了時間が遅すぎてサービスレベル目標 (SLO) を達成できなくなるまで、このサイクルを繰り返し、その都度レートを上げていきます。

負荷テストを行う際には、各使用率メトリクスを調べます。負荷とともに増加するメトリクスは、最適な使用率メトリクスとして役立つ最有力候補です。

次に、飽和状態に達しているリソースを特定します。同時に、使用率メトリクスを調べて、最初に高いレベルで横ばいになったものを調べます。または、ピークに達して最初にアプリケーションをクラッシュさせるものを調べます。たとえば、負荷を追加するにつれて CPU 使用率が 0% から 70 ～ 80% に増加し、さらに多くの負荷を追加してもそのレベルにとどまる場合は、CPU が飽和状態であると言えます。CPU アーキテクチャによっては、100% に達しない可能性があります。たとえば、負荷を追加するとメモリ使用率が増加し、タスクまたは Amazon EC2 インスタンスのメモリ制限に達するとアプリケーションが突然クラッシュしたとします。このような状況では、メモリが完全に消費された可能性があります。アプリケーションが複数のリソースを消費する可能性があります。そのため、最初に枯渇したリソースを表すメトリクスを選択します。

最後に、タスクまたは Amazon EC2 インスタンスの数を 2 倍にしてから、負荷テストを再試行します。キーメトリクスが以前の半分の速度で、増加または減少すると仮定します。この場合、メトリクスはキャパシティに比例します。これは自動スケーリングに適した使用率メトリクスです。

次に、この架空のシナリオを考えてみましょう。アプリケーションの負荷テストを行い、1 秒あたり 100 リクエストで CPU 使用率が最終的に 80% に達したとします。負荷を追加しても、CPU 使用率は上昇しなくなります。ただし、アプリケーションの応答は遅くなります。次に、負荷テストを再度実行して、タスクの数を 2 倍にしますが、速度は以前のピーク値に保たれます。CPU の平均使用率が約 40% に低下した場合、CPU 平均使用率がスケーリングメトリクスの候補として適しています。一方、タスク数を増やしても CPU 使用率が 80% のままであれば、平均 CPU 使用率は適切なスケーリング指標ではありません。その場合は、適切なメトリクスを見つけるためにさらに調査する必要があります。

### 一般的なアプリケーションモデルおよびスケーリングプロパティ
<a name="capacity-autoscaling-app-common"></a>

あらゆる種類のソフトウェアを AWS で実行できます。多くのワークロードは自社開発ですが、他のワークロードは一般的なオープンソースソフトウェアをベースにしています。その出所に関係なく、サービスの一般的なデザインパターンがいくつか確認されています。どの方法で効果的にスケーリングできるかは、そのパターンに大きく依存します。

#### 効率的な CPU バウンドサーバー
<a name="capacity-autoscaling-app-common-cpu"></a>

効率的な CPU バウンドサーバーは、CPU とネットワークスループット以外のリソースをほとんど使用しません。各リクエストはアプリケーションだけで処理できます。リクエストはデータベースなど他のサービスには依存しません。アプリケーションは何十万もの同時リクエストを処理でき、そのために複数の CPU を効率的に活用できます。各リクエストは、メモリーオーバーヘッドの少ない専用スレッドによって処理されるか、リクエストを処理する各 CPU で実行される非同期イベントループによって処理されます。アプリケーションの各レプリカは、同じようにリクエストを処理できます。CPU が枯渇する前に枯渇する可能性のあるリソースは、ネットワーク帯域幅のみです。CPU バウンドサービスでは、ピークスループットでもメモリ使用率は、利用可能なリソースのほんの一部です。

このタイプのアプリケーションには、CPU ベースの自動スケーリングを使用できます。このアプリケーションはスケーリングに関して最大限の柔軟性を備えています。より大きな Amazon EC2 インスタンスまたは Fargate vCPU を提供することで、垂直方向にスケーリングできます。また、レプリカをさらに追加することで、水平方向にスケールすることもできます。レプリカを追加したり、インスタンスサイズを 2 倍にしたりすると、容量に対する平均 CPU 使用率が半分に削減されます。

このアプリケーションに Amazon EC2 の容量を使用している場合は、`c5` または `c6g` ファミリーなどのコンピューティング最適化インスタンスに配置することを検討してください。

#### 効率的なメモリバウンドサーバー
<a name="capacity-autoscaling-app-common-memory"></a>

効率的なメモリバウンドサーバーは、リクエストごとに大量のメモリを割り当てます。同時実行性が最大になると、必ずしもスループットが高くなるわけではありませんが、CPU リソースが使い果たされる前にメモリが使い果たされます。リクエストに関連するメモリは、リクエストが終了すると解放されます。メモリに余裕がある限り、追加のリクエストを受け付けることができます。

このタイプのアプリケーションには、メモリベースの自動スケーリングを使用できます。このアプリケーションはスケーリングに関して最大限の柔軟性を備えています。より大きな Amazon EC2 または Fargate メモリリソースを提供することで、両方を垂直方向にスケーリングできます。また、レプリカをさらに追加することで、水平方向にスケールすることもできます。レプリカを追加したり、インスタンスサイズを 2 倍にしたりすると、容量に対する平均メモリ使用率を半分に減らすことができます。

このアプリケーションに Amazon EC2 キャパシティを使用している場合は、`r5` または `r6g` ファミリーなどのメモリ最適化インスタンスにキャパシティを割り当てることを検討してください。

メモリに制約のあるアプリケーションの中には、同時実行数を減らしても使用されるメモリが減らないように、リクエストの終了時にそのリクエストに関連するメモリを解放しないものがあります。このため、メモリベースのスケーリングを使用することはお勧めしません。

#### ワーカーベースのサーバー
<a name="capacity-autoscaling-app-common-worker"></a>

ワーカーベースのサーバーは、個々のワーカースレッドごとに 1 つのリクエストを次々に処理します。ワーカースレッドは POSIX スレッドなどの軽量スレッドでもかまいません。UNIX プロセスなど、より負荷の大きいスレッドの場合もあります。どのスレッドであっても、アプリケーションがサポートできる同時実行数は常に最大です。通常、同時実行数の制限は、使用可能なメモリリソースに比例して設定されます。同時実行数の上限に達すると、アプリケーションにより、追加のリクエストはバックログキューに入れられます。バックログキューがオーバーフローすると、アプリケーションはそれ以降の受信リクエストを直ちに拒否します。このパターンに当てはまる一般的なアプリケーションには、Apache Web サーバーや Gunicorn などがあります。

このアプリケーションを拡張するには、通常、リクエストの同時実行性が最適なメトリクスです。各レプリカには同時実行数の制限があるため、平均制限に達する前にスケールアウトすることが重要です。

リクエストの同時実行メトリクスを取得する最良の方法は、アプリケーションに CloudWatch にレポートさせることです。アプリケーションの各レプリカは、同時リクエストの数をカスタムメトリクスとして高い頻度で公開できます。この頻度は少なくとも 1 分に 1 回に設定することをおすすめします。複数のレポートを収集したら、平均同時実行数をスケーリングメトリクスとして使用できます。このメトリクスは、同時実行数の合計をレプリカ数で割って算出します。たとえば、同時実行数の合計が 1000 で、レプリカの数が 10 の場合、平均同時実行数は 100 です。

アプリケーションが Application Load Balancer の背後にある場合は、ロードバランサーの `ActiveConnectionCount` メトリクスをスケーリングメトリクスの要素として使用することもできます。平均値を求めるには、`ActiveConnectionCount` メトリクスをレプリカの数で割る必要があります。スケーリングには未加工のカウント値ではなく、平均値を使用する必要があります。

この設計を最適に機能させるには、リクエストレートが低い場合でも応答レイテンシの標準偏差を小さくする必要があります。需要が少ない時期には、ほとんどのリクエストに短時間で回答し、平均応答時間よりも大幅に時間がかかるリクエストは多くないことをお勧めします。平均応答時間は 95 パーセンタイル応答時間に近くなります。そうしないと、結果としてキューオーバーフローが発生する可能性があります。これはエラーにつながります。オーバーフローのリスクを軽減するために、必要に応じて追加のレプリカを提供することをお勧めします。

#### 待機中のサーバー
<a name="capacity-autoscaling-app-common-waiting"></a>

待機中のサーバーはリクエストごとに何らかの処理を行いますが、機能するには 1 つ以上のダウンストリームサービスに大きく依存しています。コンテナアプリケーションは多くの場合、データベースやその他の API サービスなどのダウンストリームサービスを多用します。特に大容量または同時実行の多いシナリオでは、これらのサービスが応答するまでに時間がかかることがあります。これは、これらのアプリケーションが CPU リソースをほとんど使用せず、使用可能なメモリの観点から最大限の同時実行性を利用する傾向があるためです。

待機サービスは、アプリケーションの設計方法に応じて、メモリーバウンドのサーバーパターンとワーカーベースのサーバーパターンのどちらにも適しています。アプリケーションの同時実行がメモリによってのみ制限される場合は、平均メモリ使用率をスケーリングメトリクスとして使用する必要があります。アプリケーションの同時実行がワーカーの制限に基づいている場合は、平均同時実行数をスケーリングメトリクスとして使用する必要があります。

#### Java ベースのサーバー
<a name="capacity-autoscaling-app-common-java"></a>

Java ベースのサーバーが CPU に依存し、CPU リソースに比例してスケーリングする場合は、効率的な CPU バウンドのサーバーパターンに適している場合があります。その場合は、平均 CPU 使用率がスケーリングメトリクスとして適切である場合があります。ただし、多くの Java アプリケーションは CPU に依存していないため、スケーリングが困難です。

最高のパフォーマンスを得るには、Java 仮想マシン (JVM) ヒープにできるだけ多くのメモリーを割り当てることをお勧めします。Java 8 update 191 以降を含む最近のバージョンの JVM では、コンテナに収まるようにヒープサイズをできるだけ大きく自動的に設定しています。つまり、Java では、メモリー使用率がアプリケーション使用率に比例することはほとんどありません。要求率と同時実行数が増加しても、メモリ使用率は一定に保たれます。このため、メモリー使用率に基づいて Java ベースのサーバーをスケーリングすることはお勧めしません。代わりに、通常は CPU 使用率に基づいてスケーリングすることをおすすめします。

Java ベースのサーバーでは、CPU を使い果たす前にヒープが枯渇することがあります。同時実行数が多いとアプリケーションがヒープを使い果たしやすい場合は、平均接続数が最適なスケーリングメトリクスです。アプリケーションが高スループットでヒープを使い果たしやすい場合は、平均リクエストレートが最適なスケーリングメトリクスです。

#### ガベージコレクションされた他のランタイムを使用するサーバー
<a name="capacity-autoscaling-app-common-garbage"></a>

多くのサーバーアプリケーションは、.NET や Ruby などのガベージコレクションを実行するランタイムをベースにしています。これらのサーバーアプリケーションは、前述のパターンのいずれかに当てはまります。ただし、Java の場合と同様に、これらのアプリケーションの平均メモリ使用率はスループットや同時実行性と相関関係がないことが多いため、メモリに基づいてアプリケーションをスケーリングすることはお勧めしません。

このようなアプリケーションでは、アプリケーションが CPU に制約されている場合は CPU 使用率に基づいてスケールすることをおすすめします。それ以外の場合は、負荷テストの結果に基づいて、平均スループットまたは平均同時実行性を基準にスケーリングすることをお勧めします。

#### ジョブプロセッサ
<a name="capacity-autoscaling-app-common-job"></a>

多くのワークロードには非同期のジョブ処理が含まれます。その中には、リクエストをリアルタイムで受信せず、代わりにワークキューにサブスクライブしてジョブを受け取るアプリケーションが含まれます。この種のアプリケーションでは、ほとんどの場合、適切なスケーリング指標はキューの深さです。キューの増加は、保留中の作業が処理能力を上回っていることを示しているのに対し、キューが空の場合は、実行すべき作業よりも容量が多いことを示します。

Amazon SQS や Amazon Kinesis Data Streams などの AWS メッセージングサービスは、スケーリングに使用できる CloudWatch メトリクスを提供します。Amazon SQS では、`ApproximateNumberOfMessagesVisible` が最適なメトリクスです。Kinesis Data Streams では、Kinesis Client Library (KCL) が公開している `MillisBehindLatest` メトリクスの使用を検討してください。このメトリクスは、スケーリングに使用する前に、すべてのコンシューマで平均化する必要があります。

# Amazon ECS のキャパシティとアベイラビリティ
<a name="capacity-availability-best-practice"></a>

アプリケーションの可用性は、エラーのないエクスペリエンスを提供し、アプリケーションのレイテンシーを最小限に抑えるために不可欠です。可用性を確保するには、アクセス可能で需要を満たすのに十分なキャパシティーを持つリソースが必要です。AWS では、可用性を管理するためのいくつかのメカニズムが用意されています。Amazon ECS でホストされるアプリケーションの場合、自動スケーリングやアベイラビリティーゾーン (AZ) などがあります。自動スケーリングは、定義したメトリクスに基づいてタスクやインスタンスの数を管理します。一方、アベイラビリティーゾーンを使用すると、分離されているが地理的に近い場所でアプリケーションをホストできます。

タスクサイズと同様に、キャパシティーと可用性には考慮する必要がある特定のトレードオフが存在します。理想は、キャパシティーと需要が完全に一致することです。低レイテンシーやエラー率などのサービスレベル目標 (SLO) を満たすために、リクエストを処理し、ジョブを処理するのに十分なキャパシティーが常に確保されます。キャパシティーが大きすぎて過度のコストがかかったり、キャパシティーが小さすぎてレイテンシーやエラー率が高くなったりすることはありません。

自動スケーリングは潜在的なプロセスです。まず、CloudWatch はリアルタイムメトリクスを受信する必要があります。次に、CloudWatch は、メトリクスを分析するためにこれらを集計する必要があります。メトリクスの詳細度によっては数分かかる場合があります。CloudWatch は、メトリクスをアラームのしきい値と比較して、リソースの不足や超過を特定します。不安定な状態を回避するために、設定されたしきい値を超えた状態が数分間続いたらアラームが作動するようにアラームを設定する必要があります。また、新しいタスクをプロビジョニングしたり、不要になったタスクを終了したりするのにも時間がかかります。

システムでこのような遅延が発生する可能性があるため、オーバープロビジョニングしてある程度の余裕を維持する必要があります。オーバープロビジョニングは、短期的な需要の急増に対応するのに役立ちます。また、アプリケーションを飽和状態に達させずに追加のリクエストを処理するのにも役立ちます。スケーリングのターゲットは、使用率の 60～80 % に設定することをお勧めします。これにより、追加のキャパシティーがプロビジョニングされている間も、アプリケーションは追加需要の急増をより適切に処理できるようになります。

オーバープロビジョニングが推奨されるもう 1 つの理由は、アベイラビリティーゾーンの障害に迅速に対応できるようになることです。AWS では、本番ワークロードを複数のアベイラビリティーゾーンから提供することをお勧めします。これは、1 つのアベイラビリティーゾーンに障害が発生した場合でも、残りのアベイラビリティーゾーンで実行されているタスクが引き続き需要を処理できるためです。アプリケーションが 2 つのアベイラビリティーゾーンで実行されている場合は、通常のタスク数を 2 倍にする必要があります。これは、潜在的な障害の発生時に即時にキャパシティーを提供できるようにするためです。アプリケーションが 3 つのアベイラビリティーゾーンで実行されている場合は、通常のタスク数の 1.5 倍を実行することをお勧めします。つまり、通常のサービス提供に必要な 2 つのタスクごとに 3 つのタスクを実行します。

## スケーリング速度の最大化
<a name="capacity-availability-speed"></a>

自動スケーリングは事後対応型プロセスであるため、効果が現れるまでに時間がかかります。ただし、スケールアウトに必要な時間を最小限に抑えるための方法がいくつかあります。

**イメージサイズを最小限に抑えます。**イメージが大きいほど、イメージリポジトリからのダウンロードと解凍にかかる時間が長くなります。したがって、イメージサイズを小さくすることで、コンテナの起動に必要な時間が短縮されます。イメージサイズを小さくするには、以下の特定の推奨事項に従ってください。
+ 静的バイナリを構築できるか、Golang を使用する場合は、イメージを`FROM`ゼロから構築し、作成されたイメージにバイナリアプリケーションのみを含めます。
+ Amazon Linux や Ubuntu など、アップストリームのディストリビューションベンダーが提供する最小限のベースイメージを使用します。
+ 最終イメージにはビルドアーティファクトを含めないでください。マルチステージビルドを使用することで、これを実現できます。
+ 可能な限り、`RUN` ステージをコンパクトにします。各 `RUN` ステージで新しいイメージレイヤーが作成され、そのレイヤーをダウンロードするための追加のラウンドトリップが発生します。`&&` によって複数のコマンドが結合された単一の `RUN` ステージでは、複数の `RUN` ステージの場合よりレイヤーが少なくなります。
+ 最終イメージに ML 推論データなどのデータを含める場合は、起動とトラフィック処理の開始に必要なデータのみを含めます。サービスに影響を与えずに Amazon S3 または他のストレージからオンデマンドでデータを取得する場合は、代わりにそれらの場所にデータを保存します。

**イメージを近くに保持します。**ネットワークレイテンシーが高いほど、イメージのダウンロードにかかる時間が長くなります。ワークロードと同じ AWS リージョンのリポジトリでイメージをホストします。Amazon ECR は、Amazon ECS を使用可能なすべてのリージョンで使用できる高性能のイメージリポジトリです。インターネットや VPN リンクを経由してコンテナイメージをダウンロードすることは避けてください。同じリージョンでイメージをホストすることで、全体的な信頼性が向上します。これにより、別のリージョンでネットワーク接続の問題や可用性の問題が発生するリスクを軽減できます。または、Amazon ECR クロスリージョンレプリケーションを実装して、これを実現することもできます。

**ロードバランサーのヘルスチェックのしきい値を下げます。**ロードバランサーは、アプリケーションにトラフィックを送信する前にヘルスチェックを実行します。ターゲットグループのデフォルトのヘルスチェック設定には、90 秒以上かかる場合があります。この間に、ロードバランサーはヘルスステータスをチェックし、リクエストを受信します。ヘルスチェックの間隔としきい値のカウントを下げることで、アプリケーションがトラフィックをより迅速に受け入れ、他のタスクの負荷を減らすことができます。

**コールドスタートのパフォーマンスを考慮します。**一部のアプリケーションでは、Java などのランタイムを使用してジャストインタイム (JIT) コンパイルを実行します。コンパイルプロセスは、少なくとも開始時に、アプリケーションのパフォーマンスを示すことができます。回避策は、レイテンシーが重要となるワークロードの部分を、コールドスタート時にパフォーマンスの低下を引き起こさない言語で書き換えることです。

**ターゲット追跡スケーリングポリシーではなく、ステップスケーリングポリシーを使用します。**Amazon ECS タスクには、いくつかの Application Auto Scaling オプションがあります。ターゲットトラッキングは最も使いやすいモードです。これにより、CPU 平均使用率などのメトリクスの目標値を設定するだけです。次に、オートスケーラーは、その値を達成するために必要なタスクの数を自動的に管理します。ステップスケーリングを使用すると、スケーリングメトリクスの特定のしきい値と、しきい値を超えたときに追加または削除するタスクの数を定義できるため、需要の変化に迅速に対応できます。さらに重要なことは、しきい値アラームが超過する時間を最小限に抑えることで、需要の変化に非常に迅速に対応できることです。詳細については、*Amazon Elastic Container Service デベロッパーガイド*の「[サービスのオートスケーリング](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-auto-scaling.html)」を参照してください。

Amazon EC2 インスタンスを使用してクラスターキャパシティーを提供する場合は、以下の推奨事項を考慮してください。

**より大きい Amazon EC2 インスタンスと、より高速な Amazon EBS ボリュームを使用します。**より大きい Amazon EC2 インスタンスとより高速な Amazon EBS ボリュームを使用することで、イメージのダウンロードと準備の速度を向上させることができます。特定の Amazon EC2 インスタンスファミリー内では、インスタンスサイズが大きくなると、ネットワークと Amazon EBS の最大スループットが増加します (例えば、`m5.xlarge` から `m5.2xlarge`)。さらに、Amazon EBS ボリュームをカスタマイズして、そのスループットと IOPS を向上させることもできます。例えば、`gp2` ボリュームを使用する場合は、より大きいボリュームを使用すると、ベースラインスループットが高くなります。`gp3` ボリュームを使用する場合は、ボリュームの作成時にスループットと IOPS を指定します。

**Amazon EC2 インスタンスで実行されるタスクには、ブリッジネットワークモードを使用します。**Amazon EC2 で `bridge` ネットワークモードを使用するタスクは、`awsvpc` ネットワークモードを使用するタスクよりも速く開始されます。`awsvpc` ネットワークモードを使用すると、Amazon ECS はタスクを起動する前に Elastic Network Interface (ENI) をインスタンスにアタッチします。これにより、レイテンシーが大きくなります。ただし、ブリッジネットワークの使用には、いくつかのトレードオフがあります。これらのタスクは独自のセキュリティグループを取得しないため、ロードバランシングにいくつかの影響を及ぼします。詳細については、「*Elastic Load Balancing ユーザーガイド*」の「[Load balancer target groups](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html)」を参照してください。

## 需要ショックへの対処
<a name="capacity-availability-shocks"></a>

一部のアプリケーションでは、需要が急激に増大することがあります。これは、ニュースイベント、大セール、メディアイベント、急速に拡散されるその他のイベント (トラフィックが非常に短期間で急速かつ大幅に増加する原因となる) など、さまざまな理由で発生します。計画外の場合、これによって使用可能なリソースを需要が急速に上回る可能性があります。

需要ショックに対処する最善の方法は、それらを予測して適切に計画することです。自動スケーリングには時間がかかる場合があるため、需要ショックが始まる前にアプリケーションをスケールアウトすることをお勧めします。最良の結果を得るために、共有カレンダーを使用するチーム間の緊密なコラボレーションを含むビジネス計画を立てることをお勧めします。イベントを計画しているチームは、事前にアプリケーションを担当するチームと緊密に連携する必要があります。これにより、そのチームは明確なスケジューリング計画を立てるのに十分な時間を確保できます。イベント前にスケールアウトし、イベント後にスケールインするキャパシティーをスケジュールできます。詳細については、「*Application Auto Scaling ユーザーガイド*」の「[スケジュールされたスケーリング](https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-scheduled-scaling.html)」を参照してください。

エンタープライズサポートプランをご利用の場合は、テクニカルアカウントマネージャー (TAM) とも連携してください。TAM はサービスクォータを検証し、イベントの開始前に必要なクォータが引き上げられるようにします。これにより、誤ってサービスクォータに達することがなくなります。また、ロードバランサーなどのサービスを事前準備して、イベントがスムーズに進行するように支援することもできます。

予定外の需要ショックに対処することは、より難しい問題です。予定外のショックが発生し、その振幅が非常に大きい場合、需要がすぐにキャパシティーを超える可能性があります。また、自動スケーリングが反応する能力を上回る可能性もあります。予定外のショックに備える最善の方法は、リソースをオーバープロビジョニングすることです。予想される最大トラフィック需要をいつでも処理できる十分なリソースを確保しておく必要があります。

予定外の需要ショックに備えて最大キャパシティーを維持すると、コストがかかる可能性があります。コストへの影響を軽減するには、大きな需要ショックが差し迫っていることを予測する先行指標となるメトリクスやイベントを見つけます。メトリクスやイベントによって十分な事前通知が確実に提供される場合、イベントが発生したとき、またはメトリクスが設定した特定のしきい値を超えたときには、すぐにスケールアウトプロセスを開始してください。

アプリケーションが突然の予定外の需要ショックを受けやすい場合は、高性能モードをアプリケーションに追加することを検討してください。このモードでは、重要ではない機能を犠牲にして、顧客にとって重要な機能を保持します。例えば、ご使用のアプリケーションでは、コストがかかる高価なカスタマイズされたレスポンスの生成から静的レスポンスページの提供に切り替えることができるとします。このシナリオでは、アプリケーションをまったくスケーリングせずに、スループットを大幅に向上させることができます。

最後に、需要ショックにより適切に対処するために、モノリシックサービスを分割することを検討できます。ご使用のアプリケーションが、実行にコストがかかり、スケーリングに時間がかかるモノリシックサービスである場合、パフォーマンスが重要となる部分を抽出または書き換えて、別のサービスとして実行できる可能性があります。これらの新しいサービスは、重要度の低いコンポーネントから独立してスケーリングできます。パフォーマンスが重要となる機能をアプリケーションの他の部分とは別にスケールアウトする柔軟性を持つことで、キャパシティーの追加にかかる時間の短縮とコストの削減の両方を実現できます。

# Amazon ECS クラスターのキャパシティ
<a name="capacity-cluster-best-practice"></a>

Amazon ECS クラスターに容量を提供するには、いくつかの方法があります。例えば、Amazon EC2 インスタンスを起動し、Amazon ECS コンテナエージェントを使用して起動時にクラスターに登録できます。ただし、スケーリングを自分で管理する必要があるため、この方法は難しい場合があります。そのため、Amazon ECS キャパシティプロバイダーを使用することをお勧めします。キャパシティプロバイダーがリソースのスケーリングを管理します。Amazon EC2、Fargate、Fargate Spot の 3 種類のキャパシティプロバイダーがあります。Fargate キャパシティプロバイダーの詳細については、「[Amazon ECS clusters for Fargate workloads](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-capacity-providers.html)」を参照し、EC2 ワークロードについては、「[Amazon ECS clusters for EC2 workloads](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/asg-capacity-providers.html)」を参照してください。

Fargate および Fargate Spot のキャパシティプロバイダーは、Fargate タスクのライフサイクルをユーザーに代わって処理します。Fargate はオンデマンド容量を提供し、Fargate Spot はスポット容量を提供します。タスクを起動すると、Amazon ECS はユーザーに代わって Fargate リソースをプロビジョニングします。この Fargate リソースには、タスク定義で宣言したタスクレベルの制限に直接対応するメモリと CPU ユニットが付属しています。各タスクは独自の Fargate リソースを受け取り、タスクとコンピューティングリソースの間に 1:1 の関係が作成されます。

Fargate Spot で実行されるタスクは中断される可能性があります。中断は 2 分間の警告の後に発生します。これらは、需要が高い時間帯に発生します。Fargate Spot は、バッチジョブ、開発環境、ステージング環境などの中断に対して耐性のあるワークロードに最適です。また、高いアベイラビリティと低い待機時間が要件ではない他のすべてのシナリオにも適しています。

Fargate Spot タスクは、Fargate オンデマンドタスクと一緒に実行できます。これらを一緒に使用することで、プロビジョンの「バースト」キャパシティを低コストで受け取ることができます。

Amazon ECS では、タスクの Amazon EC2 インスタンス容量を管理することもできます。各 Amazon EC2 キャパシティプロバイダーは、指定した Amazon EC2 Auto Scaling グループに関連付けられます。Amazon EC2 キャパシティプロバイダーを使用する場合、クラスターの自動スケーリングは Amazon EC2 Auto Scaling グループのサイズを維持して、スケジュールされたすべてのタスクを配置できるようにします。

# Amazon ECS の Fargate タスクサイズの選択
<a name="fargate-task-size-best-practice"></a>

AWS Fargate タスク定義では、タスクレベルで CPU とメモリを指定する必要があり、オーバーヘッドを考慮する必要はありません。また、コンテナレベルで Fargate タスクの CPU とメモリを指定することもできます。ただし、この設定は必須ではありません。リソース制限は、宣言した予約量以上の値である必要があります。ほとんどの場合、タスク定義で宣言されている各コンテナの予約量の合計に設定できます。次に、その数値を最も近い Fargate サイズに切り上げます。使用可能なサイズの詳細については、「[タスク CPU とメモリ](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-tasks-services.html#fargate-tasks-size)」を参照してください。

# Amazon EC2 でキャパシティプロバイダーを使用して Amazon ECS クラスターのキャパシティプロビジョニングを高速化する
<a name="capacity-cluster-speed-up-ec2-best-practice"></a>

Amazon EC2 で Amazon ECS を実行するお客様は、[Amazon ECS Cluster Auto Scaling (CAS)](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-auto-scaling.html) を利用して Amazon EC2 Auto Scaling グループのスケーリングを管理できます。CAS を使用すると、ASG を自動的にスケールするように Amazon ECS を設定できるため、タスクの実行に集中できます。Amazon ECS により、追加の操作を必要とせずに、必要に応じて ASG をスケールインおよびスケールアウトできるようになります。Amazon ECS キャパシティープロバイダーは、アプリケーションの需要を満たすのに十分なコンテナインスタンスを確保することで、クラスター内のインフラストラクチャを管理するために使用されます。Amazon ECS CAS の仕組みについては、「[Amazon ECS クラスターの Auto Scaling を深く探る](https://aws.amazon.com/blogs/containers/deep-dive-on-amazon-ecs-cluster-auto-scaling/)」を参照してください。

CAS は、クラスターの容量を調節するにあたり、ASG との CloudWatch ベースの統合に依存するため、CloudWatch メトリクスの公開、メトリクス `CapacityProviderReservation` が CloudWatch アラーム (高と低の両方) に違反するまでの時間、および新しく起動された Amazon EC2 インスタンスがウォームアップするまでの時間に関連する固有のレイテンシーが存在します。以下のアクションを実行することで、CAS の応答性を高め、デプロイを高速化できます。

## キャパシティープロバイダーのステップスケーリングサイズ
<a name="cas-step-size"></a>

Amazon ECS キャパシティープロバイダーは、最終的に、アプリケーションの需要に合わせてコンテナインスタンスを拡大/縮小します。Amazon ECS が起動するインスタンスの最小数は、デフォルトでは 1 に設定されています。そのため、保留中のタスクを配置するために複数のインスタンスが必要な場合は、デプロイにさらに時間がかかることがあります。Amazon ECS API を使用して [https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ManagedScaling.html](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ManagedScaling.html) を増やすことで、Amazon ECS が一度にスケールインまたはスケールアウトするインスタンスの最小数を増やすことができます。[https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ManagedScaling.html](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ManagedScaling.html) が小さすぎると、一度にスケールインまたはスケールアウトされるコンテナインスタンスの数が制限され、デプロイが遅くなる可能性があります。

**注記**  
この設定は現在、[https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateCapacityProvider.html](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateCapacityProvider.html) または [https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateCapacityProvider.html](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateCapacityProvider.html) API を使用することでのみ利用可能です。

## インスタンスのウォームアップ期間
<a name="instance-warmup-period"></a>

インスタンスのウォームアップ期間は、新たに起動された Amazon EC2 インスタンスが Auto Scaling グループの CloudWatch メトリックスに反映されるまでの時間です。指定されたウォームアップ期間が終了すると、そのインスタンスは ASG の集計メトリクスにカウントされ、CAS は、必要なインスタンス数を推定するための次の計算ループへと進みます。

[https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ManagedScaling.html#ECS-Type-ManagedScaling-instanceWarmupPeriod](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ManagedScaling.html#ECS-Type-ManagedScaling-instanceWarmupPeriod) のデフォルト値は 300 秒です。この値は [https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateCapacityProvider.html](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateCapacityProvider.html) API または [https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateCapacityProvider.html](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateCapacityProvider.html) API を使用して小さい値に設定することで、スケーリングの応答性を向上させることができます。

## 予備のキャパシティー
<a name="spare-capacity"></a>

キャパシティープロバイダーにタスクを配置するために使用できるコンテナインスタンスがない場合は、Amazon EC2 インスタンスをその場で起動してクラスターキャパシティーを増やし (スケールアウトし)、それらのインスタンスが起動するまで待ってからコンテナを起動する必要があります。これにより、タスクの起動レートが大幅に低下する可能性があります。ここでは 2 つのオプションがあります。

 この場合、予備の Amazon EC2 キャパシティーを事前に起動してタスクを実行する準備をしておくことで、実質的なタスク起動レートを上げることができます。`Target Capacity` 設定を使用して、クラスターで予備のキャパシティーを保持するかどうかを指定できます。例えば、`Target Capacity` を 80 % に設定することで、クラスターに常に 20 % の予備のキャパシティーが必要であることを示します。この予備のキャパシティーにより、スタンドアロンタスクをすぐに起動できるようになり、タスクの起動がスロットリングされなくなります。このアプローチのトレードオフは、予備のクラスターキャパシティーを保持するコストが増加する可能性があることです。

検討できる代替アプローチは、キャパシティープロバイダーではなくサービスにヘッドルームを追加することです。つまり、予備のキャパシティーを起動するための `Target Capacity` 設定を小さくする代わりに、ターゲット追跡スケーリングメトリクス、またはサービス自動スケーリングのステップスケーリングのしきい値を変更することで、サービス内のレプリカの数を増やすことができます。このアプローチが有用なのはワークロードの急増に対してのみであり、新しいサービスをデプロイし、初めて 0 から N タスクに移行する場合には効果がないことに注意してください。関連するスケーリングポリシーの詳細については、「[Target Tracking Scaling Policies](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-autoscaling-targettracking.html)」または「[Step Scaling Policies](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-autoscaling-stepscaling.html)」を参照してください。