Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws-applicationautoscaling: metricAggregationType Maximum produces alarms on the average #31792

Open
1 task
diegotomba opened this issue Oct 17, 2024 · 1 comment
Assignees
Labels
@aws-cdk/aws-applicationautoscaling Related to AWS Application Auto Scaling bug This issue is a bug. p2 response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days.

Comments

@diegotomba
Copy link

Describe the bug

When I define a StepScalingPolicy with a metricAggregationType value of autoscaling.MetricAggregationType.MAXIMUM what is produced are Amazon CloudWatch alarms that are based on average and not maximum CPU usage

Regression Issue

  • Select this option if this issue appears to be a regression.

Last Known Working CDK Version

No response

Expected Behavior

Get CloudWatch alarms that have statistic equal to max and not average in their details

Current Behavior

what is produced are Amazon CloudWatch alarms that are based on average and not maximum CPU usage

Reproduction Steps

const webserverService = new ecs.FargateService(this, "example-webserver-service", {
            cluster: webServerCluster,
            desiredCount: 3,
            taskDefinition: webserverTaskDefinition,
            securityGroups: [exampleSG],
            serviceName: 'example-webserver-service',
            circuitBreaker: {
                rollback: true
            },
            vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }
        });
        
        const scalableTarget = new autoscaling.ScalableTarget(this, 'example-scalableTarget', {
            serviceNamespace: autoscaling.ServiceNamespace.ECS,
            resourceId: `service/${webServerCluster.clusterName}/${webserverService.serviceName}`,
            scalableDimension: 'ecs:service:DesiredCount',
            minCapacity: 3,
            maxCapacity: 15,
          });

        const scalingPolicy = new autoscaling.StepScalingPolicy(this, 'example-scalingPolicy', {
            scalingTarget: scalableTarget,
            metricAggregationType: autoscaling.MetricAggregationType.MAXIMUM,
            evaluationPeriods: 2,
            adjustmentType: autoscaling.AdjustmentType.CHANGE_IN_CAPACITY,
            scalingSteps: [
              { lower: 0, upper: 45, change: -1 },
              { lower: 80, upper: Infinity, change: 3 },
            ],
            cooldown: cdk.Duration.minutes(5),
            metric: new cloudwatch.Metric({
              namespace: 'AWS/ECS',
              metricName: 'CPUUtilization',
              dimensionsMap: {
                ClusterName: webServerCluster.clusterName,
                ServiceName: webserverService.serviceName,
              },
              period: cdk.Duration.seconds(30),
            }),
          });

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.161.1

Framework Version

No response

Node.js Version

20.9.0

OS

Ubuntu 22.04.5 LTS

Language

TypeScript

Language Version

TypeScript 5.6.3

Other information

No response

@diegotomba diegotomba added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 17, 2024
@github-actions github-actions bot added the @aws-cdk/aws-applicationautoscaling Related to AWS Application Auto Scaling label Oct 17, 2024
@ashishdhingra ashishdhingra self-assigned this Oct 17, 2024
@ashishdhingra ashishdhingra added p2 needs-reproduction This issue needs reproduction. and removed needs-triage This issue or PR still needs to be triaged. labels Oct 17, 2024
@ashishdhingra
Copy link
Contributor

@diegotomba Good afternoon. Thanks for opening the issue. I was able to synthesize sample ECS stack using your code as reference and some other examples.

import * as cdk from 'aws-cdk-lib';
import * as autoscaling from 'aws-cdk-lib/aws-applicationautoscaling';
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';

export class CdktestStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new ec2.Vpc(this, 'MyDefaultVpc');

    const webServerCluster = new ecs.Cluster(this, "MyCluster", {
      vpc: vpc
    });
    
    const fargateTaskDefinition = new ecs.FargateTaskDefinition(this, 'ApiTaskDefinition', {
      memoryLimitMiB: 512,
      cpu: 256,
    });

    const container = fargateTaskDefinition.addContainer("backend", {
      // Use an image from Amazon ECR
      image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
    });
    
    container.addPortMappings({
      containerPort: 3000
    });


    const exampleSG = new ec2.SecurityGroup(this, 'MySGService', { vpc: vpc });
    exampleSG.addIngressRule(ec2.Peer.ipv4('0.0.0.0/0'), ec2.Port.tcp(3000));

    const webserverService = new ecs.FargateService(this, "example-webserver-service", {
      cluster: webServerCluster,
      desiredCount: 3,
      taskDefinition: fargateTaskDefinition,
      securityGroups: [exampleSG],
      serviceName: 'example-webserver-service',
      circuitBreaker: {
          rollback: true
      },
      vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }
  });

  const scalableTarget = new autoscaling.ScalableTarget(this, 'example-scalableTarget', {
      serviceNamespace: autoscaling.ServiceNamespace.ECS,
      resourceId: `service/${webServerCluster.clusterName}/${webserverService.serviceName}`,
      scalableDimension: 'ecs:service:DesiredCount',
      minCapacity: 3,
      maxCapacity: 15,
    });

  const scalingPolicy = new autoscaling.StepScalingPolicy(this, 'example-scalingPolicy', {
      scalingTarget: scalableTarget,
      metricAggregationType: autoscaling.MetricAggregationType.MAXIMUM,
      evaluationPeriods: 2,
      adjustmentType: autoscaling.AdjustmentType.CHANGE_IN_CAPACITY,
      scalingSteps: [
        { lower: 0, upper: 45, change: -1 },
        { lower: 80, upper: Infinity, change: 3 },
      ],
      cooldown: cdk.Duration.minutes(5),
      metric: new cloudwatch.Metric({
        namespace: 'AWS/ECS',
        metricName: 'CPUUtilization',
        dimensionsMap: {
          ClusterName: webServerCluster.clusterName,
          ServiceName: webserverService.serviceName,
        },
        period: cdk.Duration.seconds(30),
      }),
    });
  }
}

This synthesizes into below stack:

Resources:
...
...
  examplescalableTarget6E7DA7BB:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 15
      MinCapacity: 3
      ResourceId:
        Fn::Join:
          - ""
          - - service/
            - Ref: MyCluster4C1BA579
            - /
            - Fn::GetAtt:
                - examplewebserverserviceService7D1CBE41
                - Name
      RoleARN:
        Fn::GetAtt:
          - examplescalableTargetRole417A60B3
          - Arn
      ScalableDimension: ecs:service:DesiredCount
      ServiceNamespace: ecs
    Metadata:
      aws:cdk:path: CdktestStack/example-scalableTarget/Resource
  examplescalingPolicyLowerPolicy430C530E:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: CdktestStackexamplescalingPolicyLowerPolicy763900CE
      PolicyType: StepScaling
      ScalingTargetId:
        Ref: examplescalableTarget6E7DA7BB
      StepScalingPolicyConfiguration:
        AdjustmentType: ChangeInCapacity
        Cooldown: 300
        MetricAggregationType: Maximum
        StepAdjustments:
          - MetricIntervalUpperBound: 0
            ScalingAdjustment: -1
    Metadata:
      aws:cdk:path: CdktestStack/example-scalingPolicy/LowerPolicy/Resource
  examplescalingPolicyLowerAlarm4957AFBF:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Ref: examplescalingPolicyLowerPolicy430C530E
      AlarmDescription: Lower threshold scaling alarm
      ComparisonOperator: LessThanOrEqualToThreshold
      Dimensions:
        - Name: ClusterName
          Value:
            Ref: MyCluster4C1BA579
        - Name: ServiceName
          Value:
            Fn::GetAtt:
              - examplewebserverserviceService7D1CBE41
              - Name
      EvaluationPeriods: 2
      MetricName: CPUUtilization
      Namespace: AWS/ECS
      Period: 30
      Statistic: Average
      Threshold: 45
    Metadata:
      aws:cdk:path: CdktestStack/example-scalingPolicy/LowerAlarm/Resource
  examplescalingPolicyUpperPolicy30A191F6:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: CdktestStackexamplescalingPolicyUpperPolicyE18E8DE8
      PolicyType: StepScaling
      ScalingTargetId:
        Ref: examplescalableTarget6E7DA7BB
      StepScalingPolicyConfiguration:
        AdjustmentType: ChangeInCapacity
        Cooldown: 300
        MetricAggregationType: Maximum
        StepAdjustments:
          - MetricIntervalLowerBound: 0
            ScalingAdjustment: 3
    Metadata:
      aws:cdk:path: CdktestStack/example-scalingPolicy/UpperPolicy/Resource
  examplescalingPolicyUpperAlarmBE6B14B5:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Ref: examplescalingPolicyUpperPolicy30A191F6
      AlarmDescription: Upper threshold scaling alarm
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
        - Name: ClusterName
          Value:
            Ref: MyCluster4C1BA579
        - Name: ServiceName
          Value:
            Fn::GetAtt:
              - examplewebserverserviceService7D1CBE41
              - Name
      EvaluationPeriods: 2
      MetricName: CPUUtilization
      Namespace: AWS/ECS
      Period: 30
      Statistic: Average
      Threshold: 80
    Metadata:
      aws:cdk:path: CdktestStack/example-scalingPolicy/UpperAlarm/Resource
...

Are you referring Statistic: Average in the created alarms? I guess to control this value, which represents What function to use for aggregating, you need to explicitly set statistic to Maximum (default value is Average). metricAggregationType defined at ScalingPolicy level and metric alarms are separate concepts.

Thanks,
Ashish

@ashishdhingra ashishdhingra added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed needs-reproduction This issue needs reproduction. labels Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-applicationautoscaling Related to AWS Application Auto Scaling bug This issue is a bug. p2 response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days.
Projects
None yet
Development

No branches or pull requests

2 participants