API Gateway有阶段的概念(例如:dev
,test
,prod
),通过AWS控制台部署多个阶段非常简单。
使用AWS CDK定义和部署多个阶段是否可行?
我尝试过,但目前似乎不可能。以下是一个非常基本的堆栈的摘要示例,用于构建API Gateway RestApi
来服务于lambda函数:
export class TestStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define stage at deploy time; e.g: STAGE=prod cdk deploy
const STAGE = process.env.STAGE || 'dev'
// First, create a test lambda
const testLambda = new apilambda.Function(this, 'test_lambda', {
runtime: apilambda.Runtime.NODEJS_10_X,
code: apilambda.Code.fromAsset('lambda'),
handler: 'test.handler',
environment: { STAGE }
})
// Then, create the API construct, integrate with lambda and define a catch-all method
const api = new apigw.RestApi(this, 'test_api', { deploy: false });
const integration = new apigw.LambdaIntegration(testLambda);
api.root.addMethod('ANY', integration)
// Then create an explicit Deployment construct
const deployment = new apigw.Deployment(this, 'test_deployment', { api });
// And, a Stage construct
const stage = new apigw.Stage(this, 'test_stage', {
deployment,
stageName: STAGE
});
// There doesn't seem to be a way to add more than one stage...
api.deploymentStage = stage
}
}
我没有使用
LambdaRestApi
,因为有一个bug不允许显式定义Deployment
,而显式定义Stage
是必要的。这种方法需要额外的LambdaIntegration
步骤。这个堆栈运行得足够好——我可以部署一个新的堆栈,并通过环境变量定义API Gateway阶段;例如:
STAGE=my_stack_name cdk deploy
。我希望这样做可以让我添加阶段,具体操作如下:
STAGE=test cdk deploy
STAGE=prod cdk deploy
# etc.
然而,这种方法不起作用——在上面的例子中,“test”阶段被“prod”阶段覆盖。
在尝试上述方法之前,我认为只需要创建一个或多个“Stage”构造对象并将它们分配给同一个部署(该部署已经使用“RestApi”作为参数),就可以解决问题。
但是,必须通过“api.deploymentStage = stage”显式地将一个阶段分配给API,并且似乎只能分配一个阶段。
这意味着这是不可能的,相反,您需要为“test”、“prod”等创建不同的堆栈。这意味着同一API网关和Lambda函数的多个实例。
更新
经过进一步的摆弄,我发现似乎可以部署多个阶段,尽管我还没有完全解决问题...
首先,恢复“RestApi”的默认行为——删除属性“deploy: false”,该属性会自动创建一个“Deployment”。
const api = new apigw.RestApi(this, 'test_api');
接下来,像之前一样,创建一个明确的Deployment
结构:
const deployment = new apigw.Deployment(this, 'test_deployment', { api });
现在需要注意的是,prod
阶段已经被 预定义,如果您明确为 prod
创建一个 Stage
构造,则 cdk deploy
将失败。
相反,为您想要创建的每个其他阶段创建一个 Stage
构造; 例如:
new apigw.Stage(this, 'stage_test', { deployment, stageName: 'test' });
new apigw.Stage(this, 'stage_dev', { deployment, stageName: 'dev' });
// etc.
这个部署过程中,prod
正常工作。然而,test
和 dev
都会出现500内部服务器错误,并显示以下错误信息:
由于 Lambda 函数的权限无效,执行失败。
在 AWS 控制台中手动重新分配 Lambda 可以解决权限问题。我还没有找到如何在 CDK 中解决这个问题。
api.deploymentStage = prodStage
隐式地授权了调用权限,因此我们最终只有一个阶段的准确调用访问权限。如果RestApi
可以提供一种同时创建多个阶段的方法,那么就不需要显式地使用grantInvoke
了。api.deploymentStages = [prodStage, devStage, testStage]
这样的写法可能会更加有帮助。 - dmahapatro