AWSTemplateFormatVersion: '2010-09-09' Description: Add autoscaling rules that scale an ECS service based on CPU utilization Parameters: ClusterName: Type: String Default: default Description: The cluster that is running the service you want to scale ServiceName: Type: String Default: nginx Description: The name of the service to scale Resources: # Role that Application Auto Scaling will use to interact with # CloudWatch and Amazon ECS AutoscalingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: [application-autoscaling.amazonaws.com] Action: ['sts:AssumeRole'] Path: / Policies: - PolicyName: service-autoscaling PolicyDocument: Statement: - Effect: Allow Action: - 'application-autoscaling:*' - 'cloudwatch:DescribeAlarms' - 'cloudwatch:PutMetricAlarm' - 'ecs:DescribeServices' - 'ecs:UpdateService' Resource: '*' # Enable autoscaling for the service ScalableTarget: Type: AWS::ApplicationAutoScaling::ScalableTarget Properties: ServiceNamespace: 'ecs' ScalableDimension: 'ecs:service:DesiredCount' ResourceId: !Sub 'service/${ClusterName}/${ServiceName}' MinCapacity: 2 MaxCapacity: 10 RoleARN: !GetAtt AutoscalingRole.Arn # Create scaling policies that describe how to scale the service up and down. ScaleDownPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy DependsOn: ScalableTarget Properties: PolicyName: !Sub scale-${ClusterName}-${ServiceName}-down PolicyType: StepScaling ResourceId: !Sub 'service/${ClusterName}/${ServiceName}' ScalableDimension: 'ecs:service:DesiredCount' ServiceNamespace: 'ecs' StepScalingPolicyConfiguration: AdjustmentType: 'ChangeInCapacity' StepAdjustments: - MetricIntervalUpperBound: 0 ScalingAdjustment: -1 MetricAggregationType: 'Average' Cooldown: 60 ScaleUpPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy DependsOn: ScalableTarget Properties: PolicyName: !Sub scale-${ClusterName}-${ServiceName}-up PolicyType: StepScaling ResourceId: !Sub 'service/${ClusterName}/${ServiceName}' ScalableDimension: 'ecs:service:DesiredCount' ServiceNamespace: 'ecs' StepScalingPolicyConfiguration: AdjustmentType: 'ChangeInCapacity' StepAdjustments: - MetricIntervalLowerBound: 0 MetricIntervalUpperBound: 15 ScalingAdjustment: 1 - MetricIntervalLowerBound: 15 MetricIntervalUpperBound: 25 ScalingAdjustment: 2 - MetricIntervalLowerBound: 25 ScalingAdjustment: 3 MetricAggregationType: 'Average' Cooldown: 60 # Create alarms to trigger the scaling policies LowCpuUsageAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub low-cpu-${ClusterName}-${ServiceName} AlarmDescription: !Sub "Low CPU utilization for service ${ServiceName} in cluster ${ClusterName}" MetricName: CPUUtilization Namespace: AWS/ECS Dimensions: - Name: ServiceName Value: !Ref 'ServiceName' - Name: ClusterName Value: !Ref 'ClusterName' Statistic: Average Period: 60 EvaluationPeriods: 1 Threshold: 20 ComparisonOperator: LessThanOrEqualToThreshold AlarmActions: - !Ref ScaleDownPolicy HighCpuUsageAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub high-cpu-${ClusterName}-${ServiceName} AlarmDescription: !Sub "High CPU utilization for service ${ServiceName} in cluster ${ClusterName}" MetricName: CPUUtilization Namespace: AWS/ECS Dimensions: - Name: ServiceName Value: !Ref 'ServiceName' - Name: ClusterName Value: !Ref 'ClusterName' Statistic: Average Period: 60 EvaluationPeriods: 1 Threshold: 70 ComparisonOperator: GreaterThanOrEqualToThreshold AlarmActions: - !Ref ScaleUpPolicy