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-stack
或 nested-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
我正在尝试创建 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-stack
或 nested-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
- 1
在 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
- 1
这就是我们现在的做法。我们基本上有多个堆栈共享相同的 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