はじめに
GMOコネクトの永田です。
とある案件で、非常に厳しいスパイクへの性能要求があり、試行錯誤してなんとか達成できたため、技術的な要点をまとめました。
性能要求事項
- 数分で数十倍までリクエストが増加
- 最終的に数万rps(requests per sec)まで増加
- 最大負荷はほとんど発生しないため、できる限りECS Fargateのタスク数はAutoScalingでScale-Out/Inさせたい
まとめ
- (前提条件)ECSのImageはgolang+distrolessで最小サイズ化
- fast scalerを自作し、Scale-Out速度を向上
- Scale-Inは、ECS Fargateのターゲット追跡ポリシーにおまかせ
ECS Fargate Scale Out速度の課題
最初は、ECSのScaling Policyである程度いけるだろう、と楽観視していたのですが、実際に環境を構築して試してみると、ELB targetに追加されてServiceInになるまで、数分では辿り着けませんでした😇
ターゲット追跡ポリシーでのScale Outの内訳をざっと見てみると、おおよそ次のような配分となっていました。
No | 実施内容 | おおよその時間 | 備考 |
---|---|---|---|
1 | CloudWatch Metrics収集 | 2分〜3分? | 1分単位のMetricsでデータ参照できるようになるまで、までまあまあかかる |
2 | Metricsに対してのAlarm Trigger(desiredCount Up) | 3分 | ターゲット追跡の場合は固定で3分(Alarmの設定を自分でいじれない)、ステップスケーリングだと最小1分 |
3 | Alarm Trigger後、ELBのtarget INITになるまで | 20秒〜30秒 | ECS Task runになってからELB INITになるまでに時間がかかる |
4 | ELB target INITからServiceInまで | 30秒〜60秒 | ELB health checkを最小(5秒x2回)にしても時間がかかる |
No3, No4はAWSサービス内でBlack Boxであり、コンテナImageサイズの縮小・Health checkなど思いつくパラメータを最小にしてもこれ以上縮まなかったです。
そのため、No1, No2の5分程度かかっているTrigger発火(desiredCount Up)までを自作して、速度向上させよう(=fast scalerを独自実装する)、というのが今回の内容です。
fast scalerの実装内容
「fast scaler」のコンセプト自体は独自のものではなくAWS sampleにあり、今回の実装も基本的な考え方は同じです。
独自に変更したのは以下となります。
- stateの管理をLambdaで実装
- samplesではStep Functionとなっていたが、コスト面とノーコードでの条件調整は不要だったため、EventBridge+Lambdaに置き換え
- Metrics収集は同じくLambda(VPC Lambda)で実装
- ECS ContainerへのMetrics取得は、ECS内のCPU使用率を返す独自Endpointを用意
- 今回のシステムでは、rpsとCPU使用率がほぼ正比例していたため
- ここは案件の内容によって調整が必要なところ
- 備考: golangの場合数分おきにGCが走るため、CPU使用率が瞬間的(1秒〜2秒)に上がるため、数回習得したCPU使用率のうち一番高い値を除いてAVGを取得するようにしている
シーケンス図で表すと以下のようになります。(要点のみ記載)
fast scaler導入後のScale Out速度
上記のfast scaler導入後、おおよそ次の速度でScale Outを実現できました。No1, No2が大幅に改善し、結果的に1分半ほどでELB target Service Inを実現することができました!
No | 実施内容 | おおよその時間 | 備考 |
---|---|---|---|
1 | Metrics収集 | 1秒 | 1秒単位でECSの独自Endpoint呼び出し |
2 | Metricsに対してのAlarm Trigger(desiredCount Up) | 5秒 | MetricsのAVGを取るdatapoint数次第 |
3 | Alarm Trigger後、ELBのtarget INITになるまで | 20秒〜30秒 | ECS Task runになってからELB INITになるまでに時間がかかる |
4 | ELB target INITからServiceInまで | 30秒〜60秒 | ELB health checkを最小(5秒x2回)にしても時間がかかる |
ただ、No3, No4のところはどうしようも無いので、Service Inになるまでの1分半はスパイクに耐え切れるようにECS Taskを余裕を持ったSpec、台数にすることで対応しました。
Scale Inの対応
ここまではScale Outの話をしてきましたが、Scale Inは「ゆっくり」で良かったので、ターゲット追跡PolicyでCPU使用率を対象に設定しました。
(再掲)まとめ
- (前提条件)ECSのImageはgolang+distrolessで最小サイズ化
- fast scalerを自作し、Scale-Out速度を向上
- Scale-Inは、ECS Fargateのターゲット追跡ポリシーにおまかせ
弊社では、AWSを使ったサービスの開発や技術支援をはじめ、幅広い支援を行っておりますので、何かありましたらお気軽にお問合せください。