You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何删除在用ECS容量提供商?CDK销毁栈失败求助

解决CDK销毁ECS栈时容量提供商占用的问题

以下是几种无需手动操作控制台即可自动清理资源并销毁栈的方案:

方案1:在CDK代码中添加销毁前的自动清理逻辑

通过自定义Lambda资源,在栈销毁阶段自动终止ECS任务、缩容ASG,确保容量提供商释放后再销毁集群关联资源:

  1. 创建清理用的Lambda函数,包含终止ECS任务、缩容ASG的逻辑
  2. 绑定自定义资源到栈的销毁生命周期
  3. 调整资源依赖顺序,让清理逻辑优先执行

示例TypeScript代码片段:

import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as customresources from 'aws-cdk-lib/custom-resources';

// 替换为你的ECS集群和ASG实例
const ecsCluster = /* 你的ECS集群对象 */;
const asg = /* 你的ASG对象 */;

// 创建清理Lambda函数
const cleanupFn = new lambda.Function(this, 'EcsCleanupFn', {
  runtime: lambda.Runtime.NODEJS_18_X,
  handler: 'index.handler',
  code: lambda.Code.fromInline(`
const AWS = require('aws-sdk');
const ecs = new AWS.ECS();
const autoscaling = new AWS.AutoScaling();

exports.handler = async (event) => {
  if (event.RequestType === 'Delete') {
    // 将所有ECS服务的期望任务数设为0
    const servicesResp = await ecs.listServices({ cluster: '${ecsCluster.clusterName}' }).promise();
    for (const serviceArn of servicesResp.serviceArns) {
      const serviceName = serviceArn.split('/').pop();
      await ecs.updateService({
        cluster: '${ecsCluster.clusterName}',
        service: serviceName,
        desiredCount: 0
      }).promise();
    }
    // 等待服务任务停止(可根据实际情况调整等待时间)
    await new Promise(resolve => setTimeout(resolve, 45000));
    
    // 停止所有独立运行的ECS任务
    const tasksResp = await ecs.listTasks({ cluster: '${ecsCluster.clusterName}' }).promise();
    for (const taskArn of tasksResp.taskArns) {
      await ecs.stopTask({ cluster: '${ecsCluster.clusterName}', task: taskArn }).promise();
    }
    
    // 将ASG缩容到0
    await autoscaling.updateAutoScalingGroup({
      AutoScalingGroupName: '${asg.autoScalingGroupName}',
      MinSize: 0,
      MaxSize: 0,
      DesiredCapacity: 0
    }).promise();
  }
  return { Status: 'SUCCESS', PhysicalResourceId: event.PhysicalResourceId || 'ecs-cleanup' };
};
`),
  role: new iam.Role(this, 'CleanupLambdaRole', {
    assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
    managedPolicies: [
      iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonECS_FullAccess'),
      iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2AutoScalingFullAccess')
    ],
  }),
});

// 创建自定义资源,触发清理逻辑
const cleanupResource = new customresources.AwsCustomResource(this, 'EcsCleanupCustomResource', {
  onCreate: {
    service: 'Lambda',
    action: 'invoke',
    parameters: { FunctionName: cleanupFn.functionName },
  },
  onDelete: {
    service: 'Lambda',
    action: 'invoke',
    parameters: { FunctionName: cleanupFn.functionName },
  },
  policy: customresources.AwsCustomResourcePolicy.fromSdkCalls({
    resources: customresources.AwsCustomResourcePolicy.ANY_RESOURCE,
  }),
});

// 设置依赖:集群需等待清理完成后再销毁
ecsCluster.node.addDependency(cleanupResource);

方案2:使用预销毁脚本+cdk destroy

编写Shell脚本自动清理资源,再执行销毁命令:

  1. 创建清理脚本(cleanup-ecs.sh):
#!/bin/bash
CLUSTER_NAME="sd-cluster"

# 将所有ECS服务的期望任务数设为0
aws ecs list-services --cluster $CLUSTER_NAME --query 'serviceArns[]' --output text | tr '\t' '\n' | while read SERVICE_ARN; do
  SERVICE_NAME=$(echo $SERVICE_ARN | awk -F '/' '{print $NF}')
  aws ecs update-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --desired-count 0
done

# 停止所有运行中的ECS任务
aws ecs list-tasks --cluster $CLUSTER_NAME --query 'taskArns[]' --output text | tr '\t' '\n' | while read TASK_ARN; do
  aws ecs stop-task --cluster $CLUSTER_NAME --task $TASK_ARN
done

# 获取关联的容量提供商对应的ASG名称(假设仅一个容量提供商)
CAPACITY_PROVIDER=$(aws ecs describe-clusters --clusters $CLUSTER_NAME --query 'clusters[0].capacityProviders[0]' --output text)
ASG_NAME=$(aws ecs describe-capacity-providers --capacity-providers $CAPACITY_PROVIDER --query 'capacityProviders[0].autoScalingGroupProvider.autoScalingGroupArn' --output text | awk -F '/' '{print $NF}')

# 将ASG缩容到0
aws autoscaling update-auto-scaling-group --auto-scaling-group-name $ASG_NAME --min-size 0 --max-size 0 --desired-capacity 0

# 等待资源清理完成
echo "等待资源清理完成..."
sleep 60
  1. 赋予脚本执行权限并运行:
chmod +x cleanup-ecs.sh
./cleanup-ecs.sh
  1. 执行销毁命令:
cdk destroy --force

方案3:调整CDK资源的删除顺序和移除策略

通过设置资源的移除策略和依赖关系,确保ECS服务、ASG先被销毁,再处理集群的容量提供商关联:

import * as cdk from 'aws-cdk-lib';

// 对ECS服务设置销毁策略
ecsService.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
// 对ASG设置销毁策略
asg.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);

// 设置依赖顺序:ASG需等待ECS服务销毁完成
asg.node.addDependency(ecsService);
// 集群需等待ASG销毁完成
ecsCluster.node.addDependency(asg);

内容的提问来源于stack exchange,提问作者sak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 11:25:30