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

CDK部署ECS ApplicationLoadBalancedFargateService加载Secrets时卡住

问题现象

向ApplicationLoadBalancedFargateService的taskImageOptions下Secrets对象注入密钥时,无论通过sm.Secret.fromSecretCompleteArn(传入包含6位自动生成连字符后缀的完整ARN)还是sm.Secret.fromSecretNameV2方式导入密钥,CDK部署流程都会卡住无法完成,注释掉批量注入的自定义密钥配置后部署可正常完成。

预期行为

ECS服务可正常加载自定义密钥,完成部署流程。

当前行为

CDK部署流程在ECS apiService部署阶段冻结,无进展。

复现步骤
  1. 批量导入Secrets Manager密钥:
const importedSecrets = SECRET_NAMES.reduce((acc, key) => {
    const secret = sm.Secret.fromSecretCompleteArn(
      scope,
      `${config.ENVIRONMENT}/${key}`,
      secretFullArns[key], // 与AWS控制台完全一致的密钥完整ARN
    );
    return {...acc, [key]: secret};
  }, {} as {[key: string]: sm.ISecret});

其中SECRET_NAMES为存储密钥名称的数组。
2. 生成ECS密钥映射配置:

const secretsJson = SECRET_NAMES.reduce(
  (acc, key) => ({
    ...acc,
    [key]: ecs.Secret.fromSecretsManager(importedSecrets[key]),
  }),
  {},
);
  1. 创建Fargate服务时传入上述配置:
// Fargate服务定义
this.backendService = new ecsPatterns.ApplicationLoadBalancedFargateService(
  scope,
  'apiService',
  {
    serviceName: 'apiService',
    cluster: this.ecsCluster,
    taskSubnets: {
      subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,
    },
    memoryLimitMiB: 2048,
    cpu: 1024,
    desiredCount: 1,
    taskImageOptions: {
      containerName: 'apiContainer',
      image: ecs.ContainerImage.fromAsset('../api-backend/', {
        followSymlinks: SymlinkFollowMode.ALWAYS,
      }),
      containerPort: config.PORT,
      environment: {
        NODE_ENV: 'development',
        AWS_DEFAULT_REGION: config.AWS_DEFAULT_REGION,
      },
      logDriver: ecs.LogDrivers.awsLogs({
        streamPrefix: `${config.PROJECT_NAME}-logStream`,
        logGroup: fargateLog,
      }),
      secrets: {
        DB_BUSINESS_PASSWORD: ecs.Secret.fromSecretsManager(
          dbBusinessPasswordSecret,
          'password',
        ),
        DB_BUSINESS_HOST: ecs.Secret.fromSecretsManager(
          dbBusinessPasswordSecret,
          'host',
        ),

        ...secretsJson 
        // ===========>> 注释掉该行时部署可成功,但无法加载所需自定义密钥

      },
    },
  },
);
排查过程

查看合成的CDK CloudFormation模板,生成的密钥名称正确,但ARN缺失了Secrets Manager创建密钥时自动生成的6位连字符后缀,示例配置如下:

....
{
  "Name": "X_API_KEY",
  "ValueFrom": {
    "Fn::Join": [
      "",
      [
        "arn:",
        {
          "Ref": "AWS::Partition"
        },
        "secret-arn-as-it-is-in-aws-console/co****/staging/X_API_KEY"
// 生成的ARN与AWS控制台中密钥ARN的唯一差异为缺失6位自动生成的连字符后缀
      ]
    ]
  }
},
...

密钥参数名为/co****/staging/X_API_KEY,ARN缺失后缀是导致部署卡住的根本原因——ECS任务启动时无法匹配到对应密钥,会持续重试卡住。已确认任务执行角色的IAM权限配置正确,包含对应密钥的访问权限(密钥完整格式为/co***/staging/CIPHER_SECRET-??????,?代表6位自动生成的随机后缀)。
可通过CDK合成输出的模板直接验证上述ARN后缀缺失问题。
后续按照AWS官方文档指引尝试使用fromSecretAttributes方法导入密钥,代码如下:

const importedSecrets = SECRET_NAMES.reduce((acc, key) => {
  const secret = sm.Secret.fromSecretAttributes(
    scope,
    `/cobuy/${config.ENVIRONMENT}/${key}`,
    {secretCompleteArn: secretFullArns[key]}, // 传入包含6位连字符后缀的完整ARN
  );
  return {...acc, [key]: secret};
}, {} as {[key: string]: sm.ISecret});

const secretsJson = SECRET_NAMES.reduce(
  (acc, key) => ({
    ...acc,
    [key]: ecs.Secret.fromSecretsManager(importedSecrets[key]),
  }),
  {} as {[key: string]: ecs.Secret},
);

该方式仍无法解决问题,CDK合成阶段直接抛出错误:must use only one of secretCompleteArn or secretPartialArn

环境信息
  • aws-cdk-lib版本:^2.27.0
  • Node.js版本:14.19
  • TypeScript版本:^4.7.2
其他配置

cdk.json配置如下:

{
  "app": "npx ts-node --prefer-ts-exts bin/CdkStarter.ts",
  "context": {
    "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
    "@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
    "@aws-cdk/aws-efs:defaultEncryptionAtRest": true,
    "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false,
    "@aws-cdk/core:stackRelativeExports": false
  }
}
根因

这是aws-cdk-lib 2.27.0版本的内置bug:通过fromSecretCompleteArn/fromSecretNameV2导入的Secrets Manager密钥实例,其secretArn属性会被CDK内部逻辑错误截断,丢失密钥自动生成的6位随机后缀,导致ECS任务定义中引用的密钥ARN无效。使用fromSecretAttributes时报错同样是该版本的参数校验逻辑bug,传入完整ARN时会被内部逻辑误判为同时传入了完整ARN和部分ARN,触发校验失败。

修复方案

两种方案选择其一即可:

  • 升级aws-cdk-lib到2.38.0及以上稳定版本,该类密钥ARN截断问题已在官方迭代中修复,升级后原有代码无需修改即可正常生成带完整后缀的密钥引用,部署流程恢复正常。
  • 若暂时无法升级CDK版本,绕过CDK的密钥ARN自动解析逻辑,手动指定密钥版本引用,示例代码如下:
const secretsJson = SECRET_NAMES.reduce(
  (acc, key) => {
    const secret = sm.Secret.fromSecretCompleteArn(
      scope,
      `${config.ENVIRONMENT}/${key}-ecs`,
      secretFullArns[key]
    );
    return {
      ...acc,
      [key]: ecs.Secret.fromSecretsManagerVersion(secret, { versionId: 'AWSCURRENT' })
    }
  },
  {} as Record<string, ecs.Secret>
);

该方式会直接使用传入的完整ARN生成任务定义,不会触发CDK的ARN截断逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:31:04