Gemcook Tech Blog

Amazon ECSのアベイラビリティゾーンリバランシングをCDKで設定する方法

に公開

こんにちは、村中(@wage790)です。

2024年11月20日のアップデート[1]にて、AWS ECSにて、アベイラビリティーゾーン(AZ)のリバランシング機能がリリースされました。

この機能を設定することで、ECSでコンテナ化されたワークロードが一部のアベイラビリティーゾーンに偏っている場合、各アベイラビリティーゾーンに自動的にタスクが分散されるようになります。つまり、可用性の向上につながる新機能がリリースされたよということです。

今回、公式ドキュメント[2]に沿ってCDKで設定したので、備忘録としてまとめます。

CDKで設定する方法

設定方法は簡単で、ECSサービスのavailabilityZoneRebalancingecs.AvailabilityZoneRebalancing.ENABLEDを指定するだけです。

基本的な設定例

import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';

export class MyEcsStack extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const service = new ecs.FargateService(this, 'MyService', {
      cluster: cluster,
      taskDefinition: taskDefinition,
      desiredCount: 3,
      // アベイラビリティーゾーンリバランシングを有効にする設定を追加
      availabilityZoneRebalancing: ecs.AvailabilityZoneRebalancing.ENABLED,
    });
  }
}

availabilityZoneRebalancingのアクションは既に稼働中のタスクにも適用可能です。定常状態に達した後に不均衡が検出されると、自動的にリバランシングが実行されます。

複数のECSサービスがある場合

複数のサービスがある場合は、それぞれに設定することも可能です。

export class MyEcsStack extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // APIサービス
    const apiService = new ecs.FargateService(this, 'ApiService', {
      cluster: cluster,
      taskDefinition: apiTaskDefinition,
      desiredCount: 3,
      minHealthyPercent: 100,
      availabilityZoneRebalancing: ecs.AvailabilityZoneRebalancing.ENABLED,
    });

    // Workerサービス
    const workerService = new ecs.FargateService(this, 'WorkerService', {
      cluster: cluster,
      taskDefinition: workerTaskDefinition,
      desiredCount: 2,
      minHealthyPercent: 100,
      availabilityZoneRebalancing: ecs.AvailabilityZoneRebalancing.ENABLED,
    });
  }
}

タスク配置戦略を指定した設定

EC2起動タイプでは、配置戦略[3]と組み合わせることもできます。

const ec2Service = new ecs.Ec2Service(this, 'Ec2Service', {
  cluster: cluster,
  taskDefinition: taskDefinition,
  desiredCount: 4,
  placementStrategies: [
    ecs.PlacementStrategy.spreadAcrossAvailabilityZones(), // ① アベイラビリティーゾーン間でタスクを分散
    ecs.PlacementStrategy.spreadAcrossInstances(),         // ② インスタンス間でも分散
    ecs.PlacementStrategy.packedByCpu(),                   // ③ 同一インスタンス内ではCPU効率優先
  ],
  availabilityZoneRebalancing: ecs.AvailabilityZoneRebalancing.ENABLED,
});

デプロイと確認

CDKでのデプロイ

# 差分確認
cdk diff MyStack

# デプロイ
cdk deploy MyStack

設定確認

デプロイ後、AWS CLIで設定が正しく反映されているか確認します[4]

# 設定確認
aws ecs describe-services \
  --cluster my-cluster \
  --services my-service \
  --query 'services[0].availabilityZoneRebalancing'

"ENABLED"が出力されれば問題なく設定できています。

以上で設定完了です!

FargateのAZ分散とAZリバランシングの違い

ECSのAWS公式ドキュメント[5]を見ると、Fargate起動タイプでは、タスクは利用可能なアベイラビリティーゾーンに可能な限り分散してくれるとの記載があります。

タスク配置戦略および制約事項は、Fargate 起動タイプを使用しているタスクをサポートしていません。Fargate は、アクセス可能なアベイラビリティーゾーンにタスクを分散するよう最善を尽くします。キャパシティープロバイダーに Fargate と Fargate Spot の両方が含まれている場合、スプレッドの動作はキャパシティープロバイダーごとに異なります。

「あれ、今回やってるAZのリバランシングと同じじゃね?」と気になりました。

違いを調べて自分なりにまとめたものが以下です。

項目 Fargateの自動分散 アベイラビリティーゾーンリバランシング機能
対象 新規タスク配置時 稼働中サービス全体
自動で再配置 ×(偏っても放置) 〇(偏りを検知して調整)
初期分散 〇(できるだけ均等に配置)
偏りへの対処 なし 自動で再分散

Fargateは一度タスクを配置した後、その分散状態を自動で見直すことはありません。長期運用やスケーリングを繰り返すと、結果的にタスクが特定のアベイラビリティーゾーンに偏ってしまう可能性があります。

一方、リバランシング機能は、アベイラビリティーゾーン間のタスクの偏りを継続的に監視・検知し、必要に応じて再配置(再スケジュール)してくれます。

最後に

最近ECSサービスの可用性に不安を感じる場合は、各アベイラビリティーゾーンでのタスク分散状況がどのようになっているかを確認し、リバランシング設定を見直してみてはいかがでしょうか。

どなたかの参考になれば幸いです!

脚注
  1. Amazon ECS がインフラストラクチャイベント後の平均復旧時間を短縮するアベイラビリティーゾーンリバランシングを発表 - AWS ↩︎

  2. アベイラビリティーゾーン間での Amazon ECS サービスの調整 - Amazon Elastic Container Service ↩︎

  3. ECSの配置戦略とは、タスクをどのコンテナインスタンスに配置するかを決定するルールで、リソースの効率化や可用性の向上を目的に、binpack(リソース集中)、spread(分散)、random(ランダム)などの方式があります。
    戦略を使用して Amazon ECS タスク配置を定義する - Amazon Elastic Container Service↩︎

  4. Amazon ECS アベイラビリティーゾーンの再調整を追跡する - Amazon Elastic Container Service ↩︎

  5. Amazon ECS がタスクをコンテナインスタンスに配置する方法 - Amazon Elastic Container Service ↩︎

Gemcook Tech Blog
Gemcook Tech Blog

Discussion