Amazon Auroraに2種類のオートスケーリングポリシーを組み合わせてコストを削減しました

こんにちはSREチームの宮後(@miya10kei)です。最近、DisplayLink対応の変換アダプターをGETし、トリプルディスプレイ化していろいろ捗っています!

前回から少し時間が空いてしまいましたが、今回はAmazon Auroraに対して2種類のオートスケーリングポリシーを組み合わせた事例を紹介します。

背景

Park DirectではデータベースにAmazon Aurora(Provisioned)を利用し、Writerインスタンス1台、Readerインスタンス2台の構成で運用しています。

ReaderインスタンスのCPU利用率には次の傾向がありました。

ReaderインスタンスのCPU利用率の推移

CPU利用率の傾向
平日 08:00~18:00までCPU利用率が(相対的に)高い状態が続き、18:00を境に低い状態になる。
休日 平日と同じ傾向だが全体的にCPU利用率が低い状態にある

Readerインスタンスを常時2台運用するのは過剰であると判断し、オートスケーリングを導入することでコスト削減を図ることにしました。

※ Aurora Serverless v2への移行も検討しましたが、過去の検証でコスト増となった実績があったことと、リザーブドインスタンスを購入済みであったため今回は見送ることにしました。

Application Auto Scaling

Auroraでオートスケーリングを実現する場合、Application Auto Scalingを利用できます。Application Auto ScalingはAuroraだけでなく、ECSやDynamoDB、ElastiCacheなどのオートスケーリングにも対応しています。

Application Auto Scalingでは次の3つのスケーリングポリシーを利用することができます。

ポリシー 説明
スケジュールされたスケーリングポリシー 予めスケジュールした設定に従ってリードレプリカをスケールイン・アウトするポリシー
ターゲット追跡スケーリングポリシー リードレプリカの平均CPU使用率 or 接続数が指定した値におさまるようにスケールイン・アウトするポリシー
ステップスケーリングポリシー CloudWatchアラームに基づいて指定の増減分リードレプリカをスケールイン・アウトするポリシー

今回はスケジュールされたスケーリングポリシーとターゲット追跡スケーリングポリシーの2つを組み合わせることにしました。

スケーリングの方針

スケジュールされたスケーリングポリシーで前述のCPU利用率の傾向に合わせたスケーリングをおこないます。そして、ターゲット追跡スケーリングポリシーで縮退時の予期しないCPU利用率の増加に対応します。

スケーリング方針
平日 ■ スケジュールされたスケーリングポリシー
・07:00:Readerインスタンスを2台にスケールアウト
・23:00:Readerインスタンスを1台にスケールイン
※ 日によって多少のブレがあるため余裕をもたせた設定にしています
■ ターゲット追跡スケーリングポリシー
・23:00~07:00:CPU利用率に応じてReaderインスタンスを1~2台の間でスケーリング
休日 ■ ターゲット追跡スケーリングポリシー
・CPU利用率に応じてReaderインスタンスを1~2台の間でスケーリング

実現方法

スケジュールされたスケーリングポリシーは執筆時点ではマネジメントコンソールから設定することができません(AWS CLIであれば設定可能です)。Park DirectではインフラをTerraformでIaC化しているので、今回はTerraformでの設定例を紹介します。

スケーラブルターゲットの登録

まずは、AuroraをApplication Auto Scalingの対象に設定するためにスケーラブルターゲットを登録します。スケジュールされたスケーリングポリシーでmin_capacityとmax_capacityの値が時間によって変化するため、ignore_changesに設定しています。

resource "aws_appautoscaling_target" "aurora_replica" {
  service_namespace  = "rds"
  scalable_dimension = "rds:cluster:ReadReplicaCount"
  resource_id        = "cluster:my-cluster"
  min_capacity       = 2
  max_capacity       = 2

  lifecycle {
    ignore_changes = [min_capacity, max_capacity]
  }
}  

ターゲット追跡スケーリングポリシー

続いて、ターゲット追跡スケーリングポリシーを設定していきます。今回はCPU利用率
の変化で制御するため、predefined_metric_type=RDSReaderAverageCPUUtilization"を設定しています。接続数で制御したい場合はRDSReaderAverageDatabaseConnectionsを設定してください。

resource "aws_appautoscaling_policy" "target_tracking" {
  name               = "as-policy-target-tracking-my-cluster"
  service_namespace  = aws_appautoscaling_target.aurora_replica.service_namespace
  scalable_dimension = aws_appautoscaling_target.aurora_replica.scalable_dimension
  resource_id        = aws_appautoscaling_target.aurora_replica.resource_id
  policy_type        = "TargetTrackingScaling"

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "RDSReaderAverageCPUUtilization"
    }

    target_value       = 60
    scale_in_cooldown  = 300
    scale_out_cooldown = 300
    disable_scale_in   = false
  }
}

スケジュールされたスケーリングポリシー

最後に、スケジュールされたスケーリングポリシーの設定です。
平日07:00のタイミングでmin_capacity=max_capacity=2とすることで、Readerインスタンスを2台にスケールアウトさせます。
そして、毎日23:00のタイミングでmin_capacity=1とすることで、以降のスケーリング制御をターゲット追跡スケーリングポリシーに委譲しています。

# スケールアウト設定  
resource "aws_appautoscaling_scheduled_action" "scheduled_scale_out" {
  name               = "as-policy-scheduled-scaleup-my-cluster"
  service_namespace  = aws_appautoscaling_target.aurora_replica.service_namespace
  resource_id        = aws_appautoscaling_target.aurora_replica.resource_id
  scalable_dimension = aws_appautoscaling_target.aurora_replica.scalable_dimension
  schedule           = “cron(0 7 ? * MON-FRI *)”
  timezone           = “Asia/Tokyo”

  scalable_target_action {
    min_capacity = 2
    max_capacity = 2
  }
}

# スケールイン設定
resource "aws_appautoscaling_scheduled_action" "scheduled_scale_in" {
  name               = "as-policy-scheduled-scaledown-my-cluster"
  service_namespace  = aws_appautoscaling_target.aurora_replica.service_namespace
  resource_id        = aws_appautoscaling_target.aurora_replica.resource_id
  scalable_dimension = aws_appautoscaling_target.aurora_replica.scalable_dimension
  schedule           = “cron(0 23 * * ? *)”
  timezone           = “Asia/Tokyo”

  scalable_target_action {
    min_capacity = 1
    max_capacity = 2
  }
}

注意点

Application Auto Scalingによってスケールアウトされたインスタンスはベースのインスタンスの設定によらず以下の状態となります。

  • Amazon RDS Performance Insightsが無効
  • タグが未設定

Park DirectではAmazon EventBridgeでスケールアウトを検知し、AWS Step FunctionsでPerformance Insightsとタグを設定することでこの問題を回避しています。

さいごに

今回はAuroraに対して2つのスケーリングポリシーを適用した事例を紹介しました。

スケジュールされたスケーリングポリシーを適用することで、スケール対象のインスタンスの稼働時間を50%ほど削減することができました。また、縮退時の予期しないCPU利用率の増加にも対応でき、上手くコストと信頼性を両立できたのではないかと思います。

同じような悩みがある方は是非参考にしてみてください!