如何使用Lambda ARN订阅SNS主题 解决CDK Token未解析报错
问题根因
报错本质是CDK执行时序和你的代码调用时机不匹配,同时混用基础设施定义和SDK调用违反了CDK的基本运行逻辑:
- CDK代码运行分两个阶段:第一阶段是本地合成阶段,执行你写的Python构造代码,生成CloudFormation模板,这个阶段所有未创建的资源属性(比如
function_arn)都是CDK生成的${Token[TOKEN.xxx]}占位符,要等CloudFormation实际部署资源时才会替换成真实值;第二阶段是云端部署阶段,CloudFormation按照模板顺序创建资源,此时才能拿到资源的真实ARN、ID等属性。 - 你把boto3的SNS创建、订阅逻辑直接写在CDK构造代码里,这些调用会在本地合成阶段就直接用你本地的AWS凭证发起请求,此时Lambda还没开始创建,拿到的只有无法被AWS API识别的Token占位符,自然会报Endpoint ARN非法的错误。
- 额外问题:这种写法创建的SNS主题不在CDK栈的管理范围内,后续执行栈删除、更新操作时,这个SNS主题不会被同步处理,会产生云资源残留。
推荐解决方案:全量使用CDK原生资源构造,移除boto3调用
CDK本身已经封装了SNS主题、SNS订阅Lambda的相关资源,完全不需要自行编写boto3调用,CDK会自动处理资源依赖、ARN传参、权限配置的问题,部署时会自动等待资源创建完成再注入正确的属性值。
修改后的代码逻辑如下:
# 引入CDK自带的SNS、SNS订阅相关依赖,无需使用boto3 from aws_cdk import aws_sns as sns from aws_cdk import aws_sns_subscriptions as subscriptions from aws_cdk import Tags # 原有Lambda定义,注意同scope下构造ID不能重复,这里将角色ID调整为不与Lambda重名 dynamodb_lambda = lambda_.Function( self, "foobar", runtime = lambda_.Runtime.PYTHON_3_7, handler = "lambda_handlers.dynamodb_lambda_handler", code = lambda_.Code.from_asset(path), role = iam_.Role( self, "DynamoDBLambdaRole", assumed_by = iam_.ServicePrincipal('lambda.amazonaws.com'), managed_policies = [ iam_.ManagedPolicy.from_aws_managed_policy_name('DynamoDBFullAccess') ] ) ) # 用CDK原生构造创建SNS主题,替代boto3的create_topic调用 sns_topic = sns.Topic( self, "AppSnsTopic", topic_name = c.SNS_TOPIC_NAME ) # 给SNS主题添加指定标签 Tags.of(sns_topic).add("CohortStudent", "anon") # 给SNS主题添加Lambda订阅,CDK会自动完成ARN传参、触发权限配置 sns_topic.add_subscription(subscriptions.LambdaSubscription(dynamodb_lambda))
该写法的优势:
- 不需要手动处理ARN传参,CDK会自动在CloudFormation模板中配置正确的资源引用,部署时自动解析为真实ARN值
- 自动给Lambda添加SNS触发所需的资源策略,不需要手动调用权限添加接口
- 自动处理资源创建顺序:CDK会识别到SNS订阅依赖Lambda和SNS主题资源,会等两个资源都创建完成后再创建订阅关系,不会出现时序错误
- 所有资源都纳入CDK栈管理,后续更新、删除栈时会同步处理对应资源,不会产生残留
特殊场景方案:必须使用boto3时通过自定义资源在部署阶段执行
如果有特殊业务逻辑无法通过CDK原生构造实现,必须使用boto3编写自定义逻辑,不能将boto3调用直接写在构造代码中,需要将boto3逻辑封装为CDK自定义资源,让这段逻辑在CloudFormation部署阶段、Lambda创建完成之后再执行:
- 自定义资源会在部署时由CloudFormation触发临时Lambda执行你的boto3代码
- 可以将CDK创建的Lambda ARN作为参数传给自定义资源,此时传入的Token会在部署阶段被解析为真实的ARN值,可正常被boto3接口识别
- 自定义资源需要正确处理创建、更新、删除三类事件回调,避免资源残留
内容的提问来源于stack exchange,提问作者yamero
相关产品推荐
相关产品推荐

