AWS CDKを使ってLambda 関数URL(Function URLs)を設定してみた。(L1 Constractで)
先日登場したLambda 関数URL(Functions URLs)を、遅ればせながら作ってみました。
先日、AWS CDK Conference Japanもあったことですし、AWS CDKを使って作ってみました。
が、現段階では、Function URLsはL2 Construct対応はされていないので、L1 Construct、つまりCloudFormationのリソースを定義して、作ることになります。(日本語正しいか若干不安)
なお、AWS CDKのGitHubにはL2 Construct対応と思われるプルリクがあるので、リリースされたら作り直してみたいですね。(2022/04/12 AM11時現在、マージはされたみたいですが、まだリリースされてません)
なお、すでに試されている方がSampleをあげていたので、そちらをサンプルに作ってみました。
stackファイルはこんな感じ。とりあえずなので。
ちなみに、VPC Lambdaでも発行できるんだよね?ってことで、VPC作って、Lambdaをアタッチしてます。
あと、比較用にAPI Gatewayを作ってます。
IDとかもっといい付け方あると思うんですが、すみません。
スタック定義
import { Stack, StackProps, Duration, CfnResource } from 'aws-cdk-lib';
import { Runtime } from 'aws-cdk-lib/aws-lambda';
import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs'
import * as ec2 from 'aws-cdk-lib/aws-ec2'
import * as apigw from 'aws-cdk-lib/aws-apigateway'
import { Construct } from 'constructs';
export class LambdaUrlStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// VPC
const lambdaUrlVpc = new ec2.Vpc(this, 'lambdaUrlVpc', {
cidr : '10.0.0.0/16',
});
// Lambda
const lambdaUrlFunction = new lambda.NodejsFunction(this, 'lambda-url', {
runtime: Runtime.NODEJS_14_X,
entry: 'lambda/index.ts',
handler: 'endpointHandler',
timeout: Duration.seconds(30),
});
const lambdaUrlFunctionVpc = new lambda.NodejsFunction(this, 'lambda-url-vpc', {
runtime: Runtime.NODEJS_14_X,
entry: 'lambda/index.ts',
handler: 'endpointHandler',
timeout: Duration.seconds(30),
vpc: lambdaUrlVpc
});
const lambdaApiGwFunction = new lambda.NodejsFunction(this, 'lambda-url-apigw', {
runtime: Runtime.NODEJS_14_X,
entry: 'lambda/index.ts',
handler: 'endpointHandler',
timeout: Duration.seconds(30),
});
const lambdaApiGwFunctionVpc = new lambda.NodejsFunction(this, 'lambda-url-apigw-vpc', {
runtime: Runtime.NODEJS_14_X,
entry: 'lambda/index.ts',
handler: 'endpointHandler',
timeout: Duration.seconds(30),
vpc: lambdaUrlVpc
});
// API GW
const api = new apigw.LambdaRestApi(this, 'apigw',{
handler: lambdaApiGwFunction,
proxy: false
});
const test = api.root.addResource('test', {});
test.addMethod('GET');
test.addMethod('POST');
const testId = test.addResource('{id}');
testId.addMethod('GET');
const apiVpc = new apigw.LambdaRestApi(this, 'apigw-for-vpc', {
handler: lambdaApiGwFunctionVpc,
proxy: false
});
const testVpc = apiVpc.root.addResource('test');
testVpc.addMethod('GET');
testVpc.addMethod('POST');
const testVpcId = testVpc.addResource('{id}');
testVpcId.addMethod('GET');
/**
* Lambda Url
* Referenced https://github.com/neilkuan/cdk-lambda-url-sample
* See https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-url.html
*/
new CfnResource(this, 'lambda-url-cfn' , {
type: 'AWS::Lambda::Url',
properties: {
TargetFunctionArn: lambdaUrlFunction.functionArn,
AuthType: 'NONE'
}
});
new CfnResource(this, 'lambda-url-vpc-cfn' , {
type: 'AWS::Lambda::Url',
properties: {
TargetFunctionArn: lambdaUrlFunctionVpc.functionArn,
AuthType: 'NONE'
}
});
new CfnResource(this, 'lambda-url-Permision', {
type: 'AWS::Lambda::Permission',
properties: {
FunctionName: lambdaUrlFunction.functionName,
Principal: '*',
Action: 'lambda:InvokeFunctionUrl',
FunctionUrlAuthType: 'NONE'
}
});
new CfnResource(this, 'lambda-url-vpc-Permision', {
type: 'AWS::Lambda::Permission',
properties: {
FunctionName: lambdaUrlFunctionVpc.functionName,
Principal: '*',
Action: 'lambda:InvokeFunctionUrl',
FunctionUrlAuthType: 'NONE'
}
})
}
}
URLの設定のところは、サンプルと、CloudFormationのドキュメントを参考にしました。
FunctionUrlInvokeする権限いるんですね。この辺L2で内部で作って欲しい感ありますね。
余談ですが、CDKでVPC作る(ちなみにaws-vpcとかあると思ったら、なかった)と、CIDR以外、特に指定しないとSubnet、Internet Gateway、ルートテーブルのみならず、NAT Gatewayとそれに紐づくEIPまで取得してくれるんですね。便利なような、作りすぎのような・・・って感じでした。
※今回に関しては、NAT GatewayとEIPはなくても問題なかった。
L1 Constructの部分は、若干面倒ですが、先達の方のコード見ながらやりました。
とりあえずcURLから叩ければ良かったので、IAM認証とかCORSは設定してません。
この辺はL2 Construct対応されたらやってみます。
作ったもの
API Gatewayから実行されるLambda2つとLambda関数URL利用のLambda2つ。
中身は、一緒です。Hello from Lambda! 返すだけです。
VPCでも関数URL設定できるようですね。ふむ。
速度計測
APIのレスポンス速度レスポンス測ってみます。
計測方法はこちらを参考にさせていただきました。
タイプ | VPC有無 | 1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 最短 | 最長 | 平均 |
---|---|---|---|---|---|---|---|---|---|
API Gateway | なし | 0.508493 | 0.18015 | 0.138093 | 0.156039 | 0.502672 | 0.138093 | 0.502672 | 0.2970894 |
API Gateway | あり | 0.153878 | 0.444583 | 0.200877 | 0.153219 | 0.180667 | 0.153219 | 0.444583 | 0.2266448 |
Lambda 関数UIRL | なし | 0.417916 | 0.180331 | 0.193102 | 0.203698 | 0.18742 | 0.180331 | 0.203698 | 0.2364934 |
Lambda 関数UIRL | あり | 0.167147 | 0.176179 | 0.176841 | 0.400613 | 0.400877 | 0.167147 | 0.400877 | 0.2643314 |
レスポンスにそこまで大きな差はなさそうですね。
何もしてないLambdaなので、爆速なのはご容赦を。
使い分け
API Gatewayを置き換えるというものではなく、簡易的なAPI Endpointなのかなと思いました。
API Gatewayを立てるほどでもないAPI、ちょっとしたデモとかハンズオンとか?で使うことが多そうです。
今回は、IAM認証使ってみませんでした(なのでめっちゃパブリック)が、IAM認証使うことで、簡易的な認証付きアクセスもできそうですが。
次回予告
L2 Constructされたら改めて作ってみます。
IAM認証とかCORSも試してみます。
Discussion