【问题标题】:CDK split API Gateway stack into 2 small stacksCDK 将 API Gateway 堆栈拆分为 2 个小堆栈
【发布时间】:2020-10-24 06:21:11
【问题描述】:

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

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

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

代码sn-p:


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 网关。

10.24.2020 更新:

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

更多信息可以在here找到。

【问题讨论】:

    标签: amazon-web-services aws-api-gateway aws-cdk


    【解决方案1】:

    这就是我们现在的做法。我们基本上有多个堆栈共享同一个 API 网关类 (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.....
      }
    }
    

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

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

    通用模块将创建 API Gateway 对象:

    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 Gateway 和多个 Lambda,这些 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

    【讨论】:

    • 这行得通,但我仍然面临 200 个限制。据我所知,目前无法解决此问题。
    • 是的。正如@kylevoyto 回答中提到的那样,您仍然只能在 API 网关堆栈中执行大约 48 个端点...
    【解决方案2】:

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

    这是一个示例(在 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
      • 2AWS::IAM::Role

    【讨论】:

      【解决方案3】:

      只需使用属性传递数据。

      这需要在提供输出变量的堆栈上定义公共属性,并创建一个接口来扩展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,
      });
      

      【讨论】:

      • 你有扩展样本吗?我真的不明白
      • 您是尝试将堆栈拆分为两个堆栈,还是尝试保留一个堆栈并使用网络堆栈解决限制?
      • 我尝试保留一个堆栈并使用嵌套堆栈解决限制,经过长时间的研究,我尝试将大堆栈分成 2 个小堆栈。我愿意尝试任何可以解决我的问题的方法。你有什么推荐?
      • 哦,好吧,我误解了这一点,如果在您的用例中可能的话,我建议您实际上将堆栈拆分为多个堆栈。如果没有 - 很抱歉给您带来不便。您可以通过使用普通 typescript 属性将所需参数或组件传递给其他堆栈来组合堆栈,部署可以使用通配符完成 -> cdk deploy 'api*'
      • 我已经尝试这样做并分成小堆栈,但我仍然遇到资源限制。我的猜测是 apigateway.RestApi 资源是问题所在。
      猜你喜欢
      • 2021-02-18
      • 2020-11-22
      • 2022-11-04
      • 2012-02-15
      • 2015-07-02
      • 1970-01-01
      • 2020-05-21
      • 2013-12-26
      • 1970-01-01
      相关资源
      最近更新 更多