📝

Application Auto Scaling のスケールアウトを EventBridge で検知するための条件

2025/03/28に公開

Monitor Application Auto Scaling events using Amazon EventBridge - Application Auto Scaling

Only events that are specific to scaled to max and API calls via CloudTrail are currently available for Application Auto Scaling.

スケールアウトを検知する方法は以下の 2 つです。

  1. 最大までスケールアウトしたことを検知する方法
  2. CloudTrail のイベントを検知する方法

1. 最大までスケールアウトしたことを検知する方法

「最大まで」という条件があるため、以下のような挙動となります。

  • Auto Scaling の最小容量 1, 希望容量 1, 最大容量 3 の場合
    • 容量が 3 にスケールアウトした場合は検知可能
    • 容量が 2 にスケールアウトした場合は検知不可

試してみた

ECS サービスを作成し、以下のスケーリングポリシーを設定しました。

  • ターゲット追跡スケーリング
  • メトリクスタイプ: ECSServiceAverageCPUUtilization
  • 実行タスク数: 1 ~ 3

EventBridge ルールは以下のように定義しました。

{
  "source": [
    "aws.application-autoscaling"
  ],
  "detail-type": [
    "Application Auto Scaling Scaling Activity State Change"
  ],
  "detail": {
    "direction": ["scale-out"]
  }
}

EventBridge ルールのターゲットは CloudWatch Logs です。

この状態で Auto Scaling のしきい値を 0.5 % などの極端に低い値に設定し、意図的に Auto Scaling を発動させます。
数分後に CloudWatch アラームがアラーム状態になり、CloudWatch Logs に以下のログが出力されました。

{
    "version": "0",
    "id": "0b079227-5ae7-1708-f3c3-e884cc8af443",
    "detail-type": "Application Auto Scaling Scaling Activity State Change",
    "source": "aws.application-autoscaling",
    "account": "012345678901",
    "time": "2025-03-21T10:32:10Z",
    "region": "ap-northeast-1",
    "resources": [],
    "detail": {
        "resourceId": "service/test/test",
        "scaledToMax": true,
        "scalableDimension": "ecs:service:DesiredCount",
        "maxCapacity": 3,
        "minCapacity": 1,
        "startTime": "2025-03-21T10:31:01.336Z",
        "serviceNamespace": "ecs",
        "newDesiredCapacity": 3,
        "endTime": "2025-03-21T10:32:04.787Z",
        "oldDesiredCapacity": 1,
        "statusCode": "Successful",
        "direction": "scale-out"
    }
}

scaledToMaxtrue なので最大容量までスケールアウトされたことでイベントが発火されたことがわかります。

2. CloudTrail のイベントを検知する方法

AWS service events delivered via AWS CloudTrail - Amazon EventBridge

最大容量までスケールアウトしない場合、上記のイベントパターンでは検知できません。
そのため、最大容量以外のスケールアウトも検知する必要がある場合、CloudTrail に記録される UpdateService などの API を検知にする必要があります。

ECS サービスの場合、タスク容量の調整は UpdateService によって実施されるため、以下のようなイベントパターンで検知できます。
UpdateService - Amazon Elastic Container Service

{
  "source": ["aws.ecs"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["ecs.amazonaws.com"],
    "eventName": ["UpdateService"],
    "userAgent": ["ecs.application-autoscaling.amazonaws.com"],
    "requestParameters": {
      "cluster": ["<ECS クラスター名>"],
      "service": ["<ECS サービス名>"]
    }
  }
}

UpdateService API はコンソールからユーザーがタスク数を変更した場合にも記録されるため、Application Auto Scaling によるスケールアウトを検知するために userAgent を指定しています。

上記イベントパターンで検知したイベントには desiredCount が含まれているため、どの容量までスケールアウトしたのかを確認することができます。

UpdateService の記録
{
  "version": "0",
  "id": "bf64fc86-bb0f-e2af-f720-14c62cbd2192",
  "detail-type": "AWS API Call via CloudTrail",
  "source": "aws.ecs",
  "account": "012345678901",
  "time": "2025-03-21T10:57:53Z",
  "region": "ap-northeast-1",
  "resources": [],
  "detail": {
    "eventVersion": "1.11",
    "userIdentity": {
      "type": "AssumedRole",
      "principalId": "xxx:AutoScaling-UpdateDesiredCapacity",
      "arn": "arn:aws:sts::012345678901:assumed-role/AWSServiceRoleForApplicationAutoScaling_ECSService/AutoScaling-UpdateDesiredCapacity",
      "accountId": "012345678901",
      "accessKeyId": "xxx",
      "sessionContext": {
        "sessionIssuer": {
          "type": "Role",
          "principalId": "xxx",
          "arn": "arn:aws:iam::012345678901:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService",
          "accountId": "012345678901",
          "userName": "AWSServiceRoleForApplicationAutoScaling_ECSService"
        },
        "attributes": {
          "creationDate": "2025-03-21T10:57:53Z",
          "mfaAuthenticated": "false"
        }
      },
      "invokedBy": "ecs.application-autoscaling.amazonaws.com"
    },
    "eventTime": "2025-03-21T10:57:53Z",
    "eventSource": "ecs.amazonaws.com",
    "eventName": "UpdateService",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "ecs.application-autoscaling.amazonaws.com",
    "userAgent": "ecs.application-autoscaling.amazonaws.com",
    "requestParameters": {
      "cluster": "test",
      "desiredCount": 3,
      "forceNewDeployment": false,
      "service": "test"
    },
    "responseElements": {
      "service": {
        "serviceArn": "arn:aws:ecs:ap-northeast-1:012345678901:service/test/test",
        "serviceName": "test",
        "clusterArn": "arn:aws:ecs:ap-northeast-1:012345678901:cluster/test",
        "loadBalancers": [],
        "serviceRegistries": [],
        "status": "ACTIVE",
        "desiredCount": 3,
        "runningCount": 2,
        "pendingCount": 0,
        "launchType": "FARGATE",
        "platformVersion": "LATEST",
        "platformFamily": "Linux",
        "taskDefinition": "arn:aws:ecs:ap-northeast-1:012345678901:task-definition/test:61",
        "deploymentConfiguration": {
          "deploymentCircuitBreaker": {
            "enable": true,
            "rollback": true
          },
          "maximumPercent": 200,
          "minimumHealthyPercent": 100,
          "alarms": {
            "alarmNames": [],
            "rollback": false,
            "enable": false
          }
        },
        "deployments": [
          {
            "id": "ecs-svc/0324308393307114801",
            "status": "PRIMARY",
            "taskDefinition": "arn:aws:ecs:ap-northeast-1:012345678901:task-definition/test:61",
            "desiredCount": 2,
            "pendingCount": 0,
            "runningCount": 2,
            "failedTasks": 0,
            "createdAt": "Mar 21, 2025, 10:20:09 AM",
            "updatedAt": "Mar 21, 2025, 10:55:36 AM",
            "launchType": "FARGATE",
            "platformVersion": "1.4.0",
            "platformFamily": "Linux",
            "networkConfiguration": {
              "awsvpcConfiguration": {
                "assignPublicIp": "ENABLED",
                "securityGroups": ["sg-0849e791c058df084"],
                "subnets": [
                  "subnet-06ec2ff6a93ea5ba8",
                  "subnet-0f2690c6ffd8fd0b5",
                  "subnet-0f1c943a631285f62"
                ]
              }
            },
            "rolloutState": "COMPLETED",
            "rolloutStateReason": "ECS deployment ecs-svc/0324308393307114801 completed.",
            "failedLaunchTaskCount": 0,
            "replacedTaskCount": 0,
            "scale": {
              "value": 100,
              "unit": "PERCENT"
            },
            "stabilityStatus": "STABILIZING"
          }
        ],
        "roleArn": "arn:aws:iam::012345678901:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS",
        "version": 0,
        "events": [
          {
            "id": "dac88e68-f6d2-4615-9948-b4b192ba323d",
            "createdAt": "Mar 21, 2025, 10:55:36 AM",
            "message": "(service test) has reached a steady state."
          },
          {
            "id": "65111595-040f-4a70-b428-622e07d553e4",
            "createdAt": "Mar 21, 2025, 10:54:58 AM",
            "message": "(service test) has started 1 tasks: (task 3b2c41a4c9014b4aaaf4a91e10f7360f)."
          },
          {
            "id": "738ceb54-9cc4-43f0-a52e-463eec81d0e7",
            "createdAt": "Mar 21, 2025, 10:44:50 AM",
            "message": "(service test) has reached a steady state."
          },
          {
            "id": "5a46956b-f87b-4f65-9e37-1898427dffba",
            "createdAt": "Mar 21, 2025, 10:44:41 AM",
            "message": "(service test) has stopped 1 running tasks: (task 2d0e9b9cdd3a4c84bc83432edc63538a)."
          },
          {
            "id": "7ab7cd0b-6e38-4f6d-a36e-d70afd4ee08e",
            "createdAt": "Mar 21, 2025, 10:42:47 AM",
            "message": "(service test) has reached a steady state."
          },
          {
            "id": "eb07a2af-947b-44be-93ce-d29a944eff44",
            "createdAt": "Mar 21, 2025, 10:42:38 AM",
            "message": "(service test) has stopped 1 running tasks: (task 999efbc2fb6c4f348f5805e0c03ef960)."
          },
          {
            "id": "fc461efb-6bbc-4a36-9398-1a9a51781b3a",
            "createdAt": "Mar 21, 2025, 10:41:54 AM",
            "message": "(service test) has reached a steady state."
          },
          {
            "id": "3703b8f0-4f1c-413f-b1b6-24ad58a72a30",
            "createdAt": "Mar 21, 2025, 10:41:46 AM",
            "message": "(service test) has stopped 7 running tasks: (task e6acf1214dff401199917319d00b5901) (task 25006224e34a4a15baa1352f527f02ce) (task 7b68fec44cdc4fff9914ce97916c9aff) (task 3c86554e52fb4c98a9bea27c50626b82) (task 59d67050d5164815951a1bd80f7307ef) (task d749a5b9ed4d49dbb3090668ce8da691) (task bdc6f45fe2ba484196428e5f5ac58c46)."
          },
          {
            "id": "3204dca2-37a6-4e19-ab5a-6972585120de",
            "createdAt": "Mar 21, 2025, 10:38:40 AM",
            "message": "(service test) has reached a steady state."
          },
          {
            "id": "fee7510a-d767-4ecf-9f4c-8708e63470ac",
            "createdAt": "Mar 21, 2025, 10:38:12 AM",
            "message": "(service test) has started 9 tasks: (task 25006224e34a4a15baa1352f527f02ce) (task 2d0e9b9cdd3a4c84bc83432edc63538a) (task 3c86554e52fb4c98a9bea27c50626b82) (task 59d67050d5164815951a1bd80f7307ef) (task 7b68fec44cdc4fff9914ce97916c9aff) (task 999efbc2fb6c4f348f5805e0c03ef960) (task bdc6f45fe2ba484196428e5f5ac58c46) (task d749a5b9ed4d49dbb3090668ce8da691) (task e6acf1214dff401199917319d00b5901)."
          },
          {
            "id": "ca2a6619-4acb-4d1d-bdfc-2eebf93cbc40",
            "createdAt": "Mar 21, 2025, 10:31:39 AM",
            "message": "(service test) has reached a steady state."
          },
          {
            "id": "d03f29f1-1850-4003-8157-245d3d77a7f1",
            "createdAt": "Mar 21, 2025, 10:31:11 AM",
            "message": "(service test) has started 2 tasks: (task 28377ac6ec0a496da8d6b610a7fa6672) (task 3d0cbd5f0cf148d681f80f0fff80284d)."
          },
          {
            "id": "1a66f172-20dc-42f4-91af-859571f5dfde",
            "createdAt": "Mar 21, 2025, 10:23:04 AM",
            "message": "(service test) has reached a steady state."
          },
          {
            "id": "f6b0cf91-db85-444c-9201-e86d9d7e8a60",
            "createdAt": "Mar 21, 2025, 10:23:04 AM",
            "message": "(service test) (deployment ecs-svc/0324308393307114801) deployment completed."
          },
          {
            "id": "a32f6f47-9c06-4f2a-9a9f-921f7dbe6c73",
            "createdAt": "Mar 21, 2025, 10:20:23 AM",
            "message": "(service test) has started 1 tasks: (task 930417a1fea144fbbbb0c52d07ae30a2)."
          }
        ],
        "createdAt": "Mar 21, 2025, 10:20:09 AM",
        "placementConstraints": [],
        "placementStrategy": [],
        "networkConfiguration": {
          "awsvpcConfiguration": {
            "assignPublicIp": "ENABLED",
            "securityGroups": ["sg-0849e791c058df084"],
            "subnets": [
              "subnet-06ec2ff6a93ea5ba8",
              "subnet-0f2690c6ffd8fd0b5",
              "subnet-0f1c943a631285f62"
            ]
          }
        },
        "healthCheckGracePeriodSeconds": 0,
        "schedulingStrategy": "REPLICA",
        "deploymentController": {
          "type": "ECS"
        },
        "createdBy": "xxx",
        "enableECSManagedTags": true,
        "propagateTags": "NONE",
        "enableExecuteCommand": false,
        "availabilityZoneRebalancing": "ENABLED",
        "runStatus": "SteadyState",
        "extendDeploymentTimePeriod": 0
      }
    },
    "requestID": "c5a7edf3-ca00-4599-b05e-e78a81a4b72d",
    "eventID": "aa3eefc6-88aa-4dd2-8597-9f2d45598bce",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "012345678901",
    "eventCategory": "Management"
  }
}

情報量が多いので、メールや Slack に通知する場合には EventBridge の入力トランスフォーマーや Lambda で整形すると可視性が向上すると思います。

まとめ

Application Auto Scaling のスケールアウトを EventBridge で検知するための条件を紹介しました。
どなたかの参考になれば幸いです。

参考資料

Discussion