如何在AWS CDK/CloudFormation中实现ECS基于表达式的指标自动扩缩容?
实现ECS服务基于指标表达式的目标扩缩容
不用依赖自定义Lambda就能搞定,AWS CDK和CloudFormation都原生支持这个配置——只是官方文档的示例大多聚焦单指标场景,容易忽略Metric Expression的配置方式。
AWS CDK 实现示例(TypeScript)
在CDK中,你可以通过ApplicationAutoScaling.TargetTrackingScalingPolicy的customizedMetricSpecification属性直接配置指标表达式。比如下面的例子是计算「SQS队列待处理消息数/ECS当前运行任务数」作为扩缩容依据:
import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as appscaling from 'aws-cdk-lib/aws-applicationautoscaling'; import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; const stack = new cdk.Stack(app, 'EcsScalingStack'); // 导入已有的ECS集群与服务 const ecsCluster = ecs.Cluster.fromClusterArn(stack, 'ExistingCluster', 'arn:aws:ecs:region:account-id:cluster/your-cluster'); const ecsService = ecs.EcsService.fromEcsServiceArn(stack, 'ExistingService', 'arn:aws:ecs:region:account-id:service/your-cluster/your-service'); // 创建扩缩容目标 const scalingTarget = ecsService.autoScaleTaskCount({ minCapacity: 2, maxCapacity: 10, }); // 基于指标表达式的目标追踪策略 scalingTarget.scaleToTrackCustomMetric('QueuePerTaskScaling', { targetValue: 5, // 目标值:每个任务对应5条待处理消息 customizedMetricSpecification: { metricName: 'QueueMessagesPerTask', namespace: 'CustomMetrics', dimensionsMap: {}, statistic: 'Average', unit: cloudwatch.Unit.NONE, // 核心配置:指标表达式 metricExpression: { expression: 'm1/m2', label: 'QueueMessagesPerTask', returnData: true, metrics: [ { id: 'm1', metricStat: { metric: cloudwatch.Metric.fromMetricName({ namespace: 'AWS/SQS', metricName: 'ApproximateNumberOfMessagesVisible', dimensionsMap: { QueueName: 'your-queue' }, }), period: cdk.Duration.minutes(1), stat: 'Average', }, returnData: false, }, { id: 'm2', metricStat: { metric: cloudwatch.Metric.fromMetricName({ namespace: 'AWS/ECS', metricName: 'RunningTasksCount', dimensionsMap: { ClusterName: ecsCluster.clusterName, ServiceName: ecsService.serviceName, }, }), period: cdk.Duration.minutes(1), stat: 'Average', }, returnData: false, }, ], }, }, });
CloudFormation 模板实现示例(YAML)
直接在AWS::ApplicationAutoScaling::ScalingPolicy的TargetTrackingScalingPolicyConfiguration中定义CustomizedMetricSpecification,并包含MetricExpression字段即可:
Resources: ECSScalingTarget: Type: AWS::ApplicationAutoScaling::ScalingTarget Properties: MaxCapacity: 10 MinCapacity: 2 ResourceId: !Join ['/', [service, !Ref ECSClusterName, !Ref ECSServiceName]] ScalableDimension: ecs:service:DesiredCount ServiceNamespace: ecs RoleARN: !GetAtt ECSScalingRole.Arn ECSScalingPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy Properties: PolicyName: QueuePerTaskScalingPolicy PolicyType: TargetTrackingScaling ScalingTargetId: !Ref ECSScalingTarget TargetTrackingScalingPolicyConfiguration: TargetValue: 5 CustomizedMetricSpecification: MetricName: QueueMessagesPerTask Namespace: CustomMetrics Statistic: Average Unit: None MetricExpression: Expression: m1/m2 Label: QueueMessagesPerTask ReturnData: true Metrics: - Id: m1 MetricStat: Metric: Dimensions: - Name: QueueName Value: your-queue MetricName: ApproximateNumberOfMessagesVisible Namespace: AWS/SQS Period: 60 Stat: Average ReturnData: false - Id: m2 MetricStat: Metric: Dimensions: - Name: ClusterName Value: !Ref ECSClusterName - Name: ServiceName Value: !Ref ECSServiceName MetricName: RunningTasksCount Namespace: AWS/ECS Period: 60 Stat: Average ReturnData: false ECSScalingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: application-autoscaling.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: ECSAutoScalingPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - cloudwatch:GetMetricStatistics - cloudwatch:ListMetrics - ecs:DescribeServices - ecs:UpdateService Resource: '*'
注意事项
- 指标表达式需符合CloudWatch语法规则,确保表达式中的指标ID与引用对应
- 需为AutoScaling角色配置读取CloudWatch指标、更新ECS服务的权限
- 根据业务场景调整
Period(统计周期)和Statistic(统计方式)参数 - 目标值的设置要贴合实际业务负载,避免过度扩缩容
内容的提问来源于stack exchange,提问作者sachi1325
相关产品推荐
相关产品推荐

