AWS CDK で Lambda@Edge がクロスリージョン対応しそう
AWS, TypeScriptはじめに
AWS の Lambda@Edge は us-east1
リージョンで作成する必要がある。
ところが、クロスリージョンの怒られにより、CDK で Lambda の Stack やコードを、 ap-northeast-1
リージョンを設定した CloudFront に噛ませてデプロイしようとしてもコケてしまうのだった。
今までは、SSM に Lambda の ARN を渡して、さらにその値を読むカスタムリソースを噛ませないといけなかった。
lambda-stack.ts
import { Stack, Construct, CfnOutput, Fn, StackProps } from '@aws-cdk/core'
import {
AssetCode,
Runtime,
Function as LambdaFunction,
} from '@aws-cdk/aws-lambda'
import {
Role,
CompositePrincipal,
ServicePrincipal,
ManagedPolicy,
} from '@aws-cdk/aws-iam'
import { LAMBDA_OUTPUT_NAME } from '../config'
import { StringParameter } from '@aws-cdk/aws-ssm'
type Props = {
code: AssetCode
lambdaFunctionArnParameterName: string
} & StackProps
export class LambdaStack extends Stack {
public readonly cfnOutput: CfnOutput
constructor(scope: Construct, id: string, props: Props) {
super(scope, id, props)
const { code, lambdaFunctionArnParameterName, env } = props
if (env?.region !== 'us-east-1') {
throw new Error('region must be us-east-1')
}
/**
* Lambda
*/
const myLambda = new LambdaFunction(this, 'myLambda', {
handler: 'index.handler',
code,
role: new Role(this, 'AllowLambdaServiceToAssumeRole', {
assumedBy: new CompositePrincipal(
new ServicePrincipal('lambda.amazonaws.com'),
new ServicePrincipal('edgelambda.amazonaws.com'),
),
managedPolicies: [
ManagedPolicy.fromAwsManagedPolicyName(
'service-role/AWSLambdaBasicExecutionRole',
),
],
}),
runtime: Runtime.NODEJS_12_X,
})
new StringParameter(this, 'LambdaFunctionArnParameter', {
parameterName: lambdaFunctionArnParameterName,
stringValue: myLambda.currentVersion.functionArn,
})
this.cfnOutput = new CfnOutput(this, LAMBDA_OUTPUT_NAME, {
value: Fn.join(':', [
myLambda.functionArn,
myLambda.currentVersion.version,
]),
})
}
}
そんな中、Lambda のクロスリージョンな construct を作成する PR がマージされて、先週リリースされてたので、試してみた。
[cloudfront][lambda]Cross-region Lambda construct for Lambda@Edge
環境
- AWS CDK 1.78.0
リリースノートによれば、 1.77.0 から対応している。 Release v1.77.0 · aws/aws-cdk
使い方
下記のように @aws-cdk/aws-lambda
の Function
を使うコードがあるとして…。
cloudfront-stack.ts
import * as CloudFront from '@aws-cdk/aws-cloudfront'
import * as Lambda from '@aws-cdk/aws-lambda'
const lambdaFunction = new Lambda.Function(this, 'myLambda', {
handler: 'index.lambdaFunctions',
code: new Lambda.AssetCode(`${resolve(__dirname)}/../lambda/dist`),
runtime: Lambda.Runtime.NODEJS_12_X,
}).currentVersion
new Lambda.Function
を @aws-cdk/aws-cloudfront/lib/experimental
の experimental.EdgeFunction
に置き換えるだけ。
(CloudFront から export されてなかった)
cloudfront-stack.ts
import * as CloudFront from '@aws-cdk/aws-cloudfront'
// @aws-cdk/aws-cloudfront/lib/experimental を import
import * as CloudFrontExperimental from '@aws-cdk/aws-cloudfront/lib/experimental'
import * as Lambda from '@aws-cdk/aws-lambda'
const lambdaFunction = new CloudFrontExperimental.EdgeFunction(
this,
'myLambda',
{
handler: 'index.lambdaFunctions',
code: new Lambda.AssetCode(`${resolve(__dirname)}/../lambda/dist`),
runtime: Lambda.Runtime.NODEJS_12_X,
},
).currentVersion
これで、Lambda@Edge を us-east-1
に置きつつ、他の Stack を ap-northeast-1
に置いたままデプロイできた。
内部的には冒頭のそれとほぼ同じようなことをやっているけど、CDK 側で対応してくれるのは嬉しい。
ただ、こちらのコメントにもあるように、ロググループが見当たらない…。