AWS CodeBuild中CDK读取SSM参数时捕获异常失败问题
解决CDK中SSM参数Lookup失败导致CodeBuild终止的问题
问题场景
我在CodeBuild项目中使用CDK代码读取SSM参数,首次运行时该参数不存在,我写了try/catch逻辑想让程序继续执行,但还是报错终止了CodeBuild:
SSM parameter not available in account 1234, region us-east-1: /api-endpoint error stops the codebuild project error
我的代码:
let apiEndpoint: string; try { apiEndpoint = ssm.StringParameter.valueFromLookup(this, `api-endpoint`) } catch (error: any) { if (error.message.includes('ParameterNotFound')) { // Handle the case where the parameter doesn't exist yet console.warn('SSM parameter "api-endpoint" not found. Using default value.'); apiEndpoint = 'default-value'; } else { // Handle other errors throw error; } }
核心原因
你遇到的问题本质是**ssm.StringParameter.valueFromLookup是CDK合成阶段(synth)执行的操作,而非运行时逻辑**。CDK在生成CloudFormation模板的过程中会同步调用AWS API查询SSM参数,如果参数不存在,这个查询会直接抛出异常并终止synth流程——你的try/catch块是TypeScript代码逻辑,只会在代码运行时生效,根本到不了触发catch的阶段。
解决方案
方案1:在CodeBuild运行时读取SSM参数(推荐)
放弃在CDK中提前查询参数,改为在CodeBuild的构建脚本里用AWS CLI读取,这样可以在运行时捕获参数不存在的情况:
修改buildspec.yml:
version: 0.2 phases: build: commands: - | # 尝试读取SSM参数,捕获错误输出 API_ENDPOINT=$(aws ssm get-parameter --name "/api-endpoint" --query "Parameter.Value" --output text 2>/dev/null) if [ -z "$API_ENDPOINT" ]; then echo "SSM参数/api-endpoint不存在,使用默认值" API_ENDPOINT="default-value" fi # 将参数设为环境变量供后续步骤使用 export API_ENDPOINT=$API_ENDPOINT # 执行你的构建命令,比如 npm run build
方案2:在CDK中使用自定义资源处理
如果必须在CDK层面获取参数值,可以用AWS自定义资源(Custom Resource)来异步读取SSM参数,这样即使参数不存在,也可以在部署阶段处理并返回默认值:
import * as cdk from 'aws-cdk-lib'; import * as customresources from 'aws-cdk-lib/custom-resources'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as codebuild from 'aws-cdk-lib/aws-codebuild'; export class YourStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // 创建自定义资源读取SSM参数 const ssmLookupResource = new customresources.AwsCustomResource(this, 'ApiEndpointLookup', { onCreate: { service: 'SSM', action: 'getParameter', parameters: { Name: 'api-endpoint' }, physicalResourceId: customresources.PhysicalResourceId.of('ApiEndpointLookup'), }, // 给自定义资源添加读取SSM参数的权限 policy: customresources.AwsCustomResourcePolicy.fromStatements([ new iam.PolicyStatement({ actions: ['ssm:GetParameter'], resources: [`arn:aws:ssm:${this.region}:${this.account}:parameter/api-endpoint`], }), ]), timeout: cdk.Duration.minutes(5), }); // 获取参数值,处理不存在的情况 const apiEndpoint = ssmLookupResource.getResponseField('Parameter.Value').toString() || 'default-value'; // 将参数传递给CodeBuild项目 new codebuild.Project(this, 'YourBuildProject', { // ...其他配置 environmentVariables: { API_ENDPOINT: { value: apiEndpoint }, }, }); } }
内容的提问来源于stack exchange,提问作者Jack Rogers
相关产品推荐
相关产品推荐

