CDK 将 API 网关堆栈拆分为 2 个小堆栈

CDK split API Gateway stack into 2 small stacks

我正在尝试创建 CDK 堆栈以创建 API 网关。如果我以“小块”(资源的评论部分)创建堆栈,一切都正常工作,但是当我尝试创建完整的堆栈时,我遇到了这个异常:

 Number of resources, 224, is greater than maximum allowed, 200

因此,我尝试将我的大堆栈拆分为 2 个较小的堆栈,一个堆栈创建资源并创建一半资源,另一个堆栈填充相关数据。

代码片段:


const api = new apigateway.RestApi(this, 'ApiGWEndPoint', {
  restApiName: 'API_NAME,
  deployOptions: {
    stageName: 'STAGE_NAME',
  },
  description: "MyDescription",
  endpointTypes: [apigateway.EndpointType.REGIONAL]
});

我尝试创建 cross-stacknested-stack 并将 API 数据传递给它,但到目前为止运气不好。

我的目标是创建一个包含 2 个小堆栈的堆栈 - 它们都指向相同的 API。 或者,如果可能的话,为资源限制创建一个解决方法。

任何帮助将不胜感激。


更新 1.10.2020:

目前,没有解决此问题的方法,最终将 API 网关拆分为多个 API 网关。

2020 年 10 月 24 日更新:

AWS CloudFormation 现在支持增加对五个服务配额的限制 - 模板大小、资源、参数、映射和输出。可在 S3 对象中传递的模板的最大大小现在为 1MB(之前为 450KB)。 新的每个模板资源最大数量限制为 500(之前为 200)

可以找到更多信息 here

只需使用属性传递数据。

这需要在提供输出变量的堆栈上定义 public 属性,并创建一个扩展 StackProperties 并具有传入所需属性的接口。

结果可能如下所示:

const domain = new DomainStack(app, 'domain', {
  env: env,
  domainName: domainName,
  hostedZoneId: hostedZoneId
});

new WebsiteStack(app, 'website', {
  env: env,
  domainName: domainName,
  certificate: domain.certificate,
  hostedZone: domain.hostedZone,
});

我认为您可以通过将资源分成更小的堆栈来实现您的目标。您似乎不需要交叉堆栈引用或嵌套堆栈。

这是一个示例(在 Python 中),其中 295 个资源在两个堆栈之间分配。

#!/usr/bin/env python3

from aws_cdk import core

from lambda_api.lambda_api_stack import APIStack
from lambda_api.lambda_api_stack import LambdasStack


app = core.App()
lambdas_stack = LambdasStack(app, 'lambdasstack')
APIStack(app, 'apistack', lambdas=lambdas_stack.lambdas)


app.synth()
from aws_cdk import (
    aws_apigateway as apigateway,
    aws_lambda as _lambda,
    aws_s3 as s3,
    core
)


class LambdasStack(core.Stack):

    @property
    def lambdas(self):
        return self._lambdas

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        self._lambdas = list()
        for i in range(48):
            handler = _lambda.Function(
                self, f'Handler_{i}',
                function_name=f'Handler_{i}',
                runtime=_lambda.Runtime.PYTHON_3_8,
                code=_lambda.Code.from_asset('resources'),
                handler='handler.main'
            )
            self._lambdas.append(handler)


class APIStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, lambdas: list,
            **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        api = apigateway.RestApi(
            self, 'lambdas-api',
            rest_api_name='Lambdas Service',
            description='This service serves lambdas.'
        )

        for i in range(len(lambdas)):
            get_lambda_integration = apigateway.LambdaIntegration(
                lambdas[i],
                request_templates={
                    'application/json':
                    '{ "statusCode": "200" }'
                }
            )
            model = api.root.add_resource(f'Resource_{i}')
            model.add_method('GET', get_lambda_integration)

对于此示例,API 资源 + Lambda 集成生成的资源最多。这是所创建资源的概要。

lambdasstack 中创建了 97 个资源。

  • 1 AWS::CDK::Metadata
  • 48 x 2 资源
    • 1 AWS::Lambda::Function
    • 1 AWS::IAM::Role

apistack 中创建了 198 个资源。

  • 1 AWS::CDK::Metadata
  • 1 AWS::ApiGateway::Account
  • 1 AWS::IAM::Role
  • 1 AWS::ApiGateway::RestApi
  • 1 AWS::ApiGateway::Deployment
  • 1 AWS::ApiGateway::Stage
  • 48 x 4 资源
    • 1 AWS::ApiGateway::Resource
    • 1 AWS::ApiGateway::Method
    • 2 AWS::IAM::Role

这就是我们现在的做法。我们基本上有多个堆栈共享相同的 API 网关 class (RestApi)

class MultipleStackConstruct extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // Main stack with shared components
    const commonStack = new CommonStack(
      scope,
      `common-stack`
    );

    // Module 1
    const moduleOneStack = new ModulOneStack(
      scope,
      `module-one`,
      {
        apiGatewayRestApi: commonStack.apiGatewayRestApi
      }
    );

    // Module 2, 3, etc.....
  }
}

此接口用于将道具传递给模块堆栈:

export interface CommonProps extends cdk.StackProps {
  apiGatewayRestApi: apigw.RestApi;
}

公共模块将创建 API 网关对象:

export class CommonStack extends cdk.Stack {
  public readonly apiGatewayRestApi: apigw.RestApi;

  constructor(scope: cdk.Construct, id: string, props?: CommonProps) {
    super(scope, id, props);

    /******** SETUP API ********/
    this.apiGatewayRestApi = new apigw.RestApi(this, "MyAPI", {
      // Options here
    });
}

所以模块堆栈本身将是这样的:

export class ModuleOneStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: CommonProps) {
    super(scope, id, props);

    if (props && props.apiGatewayRestApi) {
      const apiGatewayRestApi = props.apiGatewayRestApi;

      // associate lambda with api gateway
    }
  }
}

在这种情况下,我们只使用一个 API 网关,多个 Lambda 被分成多个堆栈,因为我们也遇到了限制问题。

AWS 的文档使用 VPC 做同样的事情: https://docs.aws.amazon.com/cdk/api/latest/docs/aws-ec2-readme.html#sharing-vpcs-between-stacks

从我的评论中复制粘贴到这里:https://github.com/aws/aws-cdk/issues/1477#issuecomment-568652807