如何使用CDK在AWS多账户环境中实现中央API账户?
CDK跨账户API网关与Lambda集成死锁解决方案
核心思路
双向硬依赖的本质是两个栈都需要对方的资源输出作为入参,我们只需要通过预定义资源命名约定或者分阶段部署拆分依赖即可破解死锁,无需修改架构逻辑。
方案一:预定义命名约定(推荐,一次部署完成)
通过提前统一资源命名规则,可直接拼接生成跨账户引用的ARN,无需等待对方资源实际创建,可并行/按任意顺序部署两个栈:
- 第一步:提前固定所有跨账户资源的命名规则
- 服务账户Lambda命名格式统一为
svc-{服务标识}-{环境}-lambda - API账户API Gateway固定预设ID或统一命名,可提前拼接出API执行ARN格式
- 服务账户Lambda命名格式统一为
- 第二步:服务账户栈部署配置
直接给预拼接的API执行ARN授予Lambda调用权限,示例代码如下:from aws_cdk import Stack, aws_lambda as lambda_, aws_iam as iam from constructs import Construct # 提前约定的常量 API_ACCOUNT_ID = "123456789012" PRE_DEFINED_API_ID = "abc123def4" REGION = "cn-northwest-1" class ServiceAccountStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # 按约定命名创建Lambda order_lambda = lambda_.Function( self, "OrderLambda", function_name="svc-order-prod-lambda", runtime=lambda_.Runtime.PYTHON_3_12, handler="index.handler", code=lambda_.Code.from_asset("lambda_src") ) # 预构造API的执行ARN,直接授权 api_exec_arn = f"arn:aws:execute-api:{REGION}:{API_ACCOUNT_ID}:{PRE_DEFINED_API_ID}/*/POST/order/*" order_lambda.add_permission( "AllowAPIGWInvoke", principal=iam.ServicePrincipal("apigateway.amazonaws.com"), action="lambda:InvokeFunction", source_arn=api_exec_arn ) - 第三步:API账户栈部署配置
直接用预拼接的服务Lambda ARN作为集成目标,示例代码如下:from aws_cdk import Stack, aws_apigateway as apigw, aws_lambda as lambda_ from constructs import Construct # 提前约定的常量 SERVICE_ACCOUNT_ID = "987654321098" PRE_DEFINED_API_ID = "abc123def4" REGION = "cn-northwest-1" class APIAccountStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # 按约定ID创建API,保证ARN与服务侧预拼接的一致 central_api = apigw.RestApi( self, "CentralAPI", rest_api_name="central-prod-api", deploy_options=apigw.StageOptions(stage_name="prod") ) # 强制设置API ID为提前约定的值,需要确保该ID未被占用 CfnRestApi = central_api.node.default_child CfnRestApi.add_property_override("Id", PRE_DEFINED_API_ID) # 预构造服务Lambda ARN,导入为CDK资源 service_lambda = lambda_.Function.from_function_arn( self, "ImportedOrderLambda", function_arn=f"arn:aws:lambda:{REGION}:{SERVICE_ACCOUNT_ID}:function:svc-order-prod-lambda" ) # 添加集成方法 order_resource = central_api.root.add_resource("order") order_resource.add_method("POST", apigw.LambdaIntegration(service_lambda))
方案二:分阶段部署(无需预定义命名)
如果不想固定资源命名,可以拆为三次部署拆分依赖:
- 第一次部署API账户栈,只创建API Gateway基础资源,不添加任何Lambda集成,输出API的执行ARN前缀
- 部署服务账户栈,传入第一步输出的API ARN前缀配置Lambda调用权限,输出Lambda ARN
- 第二次部署API账户栈,传入第二步输出的Lambda ARN添加集成方法即可
注意:部署前需完成两个账户的CDK跨账户bootstrap配置,确保双方的CDK部署角色拥有对方账户对应资源的操作权限。
内容的提问来源于stack exchange,提问作者atoledo
相关产品推荐
相关产品推荐

