ECSのApplication Auto Scalingまとめ
はじめに
本番環境にて、ECSのオートスケール設定が適切でなかったために、スパイクアクセスに耐えられずサイトがダウンするというやらかしをしました。
自戒を込めて記事にまとめます。
前提
- ECS on Fargate
- Terraform
Application Auto Scaling
ECS on Fargateで利用可能なApplication Auto Scalingでは、CloudWatchアラームで定めたメトリクスの閾値で、スケールアウトやスケールインを実行します。
1. ステップスケーリングポリシー
ステップスケーリングポリシーは、段階的にスケールアクションを設定できるポリシーです。
resource "aws_appautoscaling_target" "ecs_target" {
max_capacity = 3
min_capacity = 1
resource_id = "service/clusterName/serviceName"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
resource "aws_appautoscaling_policy" "ecs_step_policy" {
name = "cpu-step-autoscaling"
service_namespace = aws_appautoscaling_target.ecs_target.service_namespace
scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
resource_id = aws_appautoscaling_target.ecs_target.resource_id
policy_type = "StepScaling"
step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 90
metric_aggregation_type = "Average"
# CPUの平均使用率が70%-85%の場合コンテナを3増やす
step_adjustment {
metric_interval_lower_bound = 0
metric_interval_upper_bound = 15
scaling_adjustment = 3
}
# CPUの平均使用率が85%以上の場合コンテナを6増やす
step_adjustment {
metric_interval_lower_bound = 15
scaling_adjustment = 6
}
}
}
resource "aws_cloudwatch_metric_alarm" "cpu_scale_out_alarm" {
alarm_name = "${var.ecs_service_name}-cpu-scale-out"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = 60
statistic = "Average"
// Step ScalingのCPU使用率の閾値の基準を平均70%とする
threshold = 70
dimensions = {
ClusterName = var.ecs_cluster_name
ServiceName = var.ecs_service_name
}
alarm_actions = [aws_appautoscaling_policy.ecs_step_policy.arn]
}
※設定されている値は適当です。
2. ターゲット追跡スケーリングポリシー
ターゲット追跡スケーリングポリシーは、CloudWatchアラームのメトリクスのターゲット値を維持するようにスケールアウトやスケールインが制御されるポリシーです。
ステップスケーリングポリシーと異なり、増減させるタスク数の設定は不要になります。
メトリクスがターゲット値を超えている場合のみスケールアウトします。
resource "aws_appautoscaling_target" "ecs_target" {
max_capacity = 3
min_capacity = 1
resource_id = "service/clusterName/serviceName"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
resource "aws_appautoscaling_policy" "ecs_target_policy" {
name = "cpu-target-autoscaling"
service_namespace = aws_appautoscaling_target.ecs_target.service_namespace
scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
resource_id = aws_appautoscaling_target.ecs_target.resource_id
policy_type = "TargetTrackingScaling"
target_tracking_scaling_policy_configuration {
# 維持するターゲット値
# CPUの平均使用率が50%になるように維持する
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
target_value = 50
# スケールインの間隔を180秒空ける
scale_in_cooldown = 180
# スケールアウトの間隔を90秒空ける
scale_out_cooldown = 90
}
}
※設定されている値は適当です。
負荷テスト
リリース前に検証環境等で負荷テストを実施して、オートスケールが想定通り動くか確認しましょう。
私の場合は、リリース前に行っていなかったため、テストの段階で気づけたはずのバグに気づかぬままリリースしてしまいサイトをダウンさせました...
パフォーマンス要件を確認する
秒間の最大アクセス数などを確認することで、負荷テストの基準が決まり、テストを実行できるようになります。
テストの実施
負荷テストには以下二つのツールを使用しました。
手軽に使えるのはabコマンドです。
設定をいろいろカスタムしたい場合はLocustがおすすめです。
以下の記事を参考にすると、テストを何回か実行して細かな調整が必要だということが分かります。
設定して終わりではなく、テストを必ず実行しましょう。
私の場合も何度かテストを実施して、設定をチューニングしました。
また、テストを実施する際は下記の観点をチェックすることをおすすめします。
- 期待する一連のCloudWatchメトリクスが取得できているか
- Auto Scalingのスケールアウトおよびスケールインは設定されているか
- アプリケーションからエラーが出力されていないか
- ログ出力の内容は適切か(欠損等はしていないか、ログレベルは妥当か)
参考文献: AWSコンテナ設計・構築[本格]入門
最後に
この記事で伝えたかったことは下記2点です。
- リリース前に必ず負荷テストを実施しましょう。
- オートスケール設定は、設定して終わりではなくチューニングが必要です。
参考URL
ENECHANGEグループは、「エネルギー革命」を技術革新により推進し、より良い世界を創出することをミッションとするエネルギーベンチャー企業です。 enechange.co.jp/
Discussion