

# 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 はサービスクォータを検証し、イベントの開始前に必要なクォータが引き上げられるようにします。これにより、誤ってサービスクォータに達することがなくなります。また、ロードバランサーなどのサービスを事前準備して、イベントがスムーズに進行するように支援することもできます。

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

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

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

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