【AWS】 CDK V2でAPI Gawate + Lamabda + EIPを構築する
やりたいこと
以下の図のようなAPI Gatew + Lambdaで外部APIから値を取得し、加工してクライアントに返すAPIをAWS CDK V2を使って作ります。利用する外部APIはアクセス元IPアドレスによりアクセス制限を行うため、LambdaをVPC内に配置しEIPを付与したNat Gateway経由で外部APIを呼び出します。
AWS CDKのインストール
AWS CDKをインストールします。
# インストール
$ npm install -g aws-cdk
# インストール後にバージョン確認
$ cdk --version
プロジェクト作成
AWS CDKを利用する準備としてブートストラップを行います。ブートストラップによりAWS CDKによるデプロイに必要なファイルをアップロードするために必要なS3などが作成されます。
ブートストラップ後にプロジェクトディレクトリを作成し、プロジェクトの初期化を行います。この例では言語はTypeScriptを選択しています。
$ aws-vault exec {プロファイル名} -- cdk bootstrap aws://{アカウントID}/{リージョン名}
$ mkdir test-project
$ cd test-project
$ cdk init --language typescript
AWSリソースの作成
CDKのスタック部分のコードは以下のようになります。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {aws_apigateway, aws_ec2, aws_lambda, Duration} from "aws-cdk-lib";
import { PythonFunction } from "@aws-cdk/aws-lambda-python-alpha";
import * as path from "path";
export class TestStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPC
const vpc = new aws_ec2.Vpc( this , 'test-vpc', {
cidr: '10.1.0.0/16',
defaultInstanceTenancy: aws_ec2.DefaultInstanceTenancy.DEFAULT,
enableDnsSupport: true,
enableDnsHostnames: true,
subnetConfiguration: [
{
cidrMask: 24,
name: 'test-public-subnet',
subnetType: aws_ec2.SubnetType.PUBLIC
},
{
cidrMask: 24,
name: 'test-private-subnet',
subnetType: aws_ec2.SubnetType.PRIVATE_WITH_EGRESS
}
],
natGateways: 1
});
// Lambda
const testFunction = new PythonFunction(this, 'TestFunction', {
functionName: 'TestFunction',
handler: 'handler',
runtime: aws_lambda.Runtime.PYTHON_3_8,
entry: path.resolve('lambda/function/src/main'),
memorySize: 128,
timeout: Duration.seconds(60),
vpc: vpc,
vpcSubnets: {
subnetType: aws_ec2.SubnetType.PRIVATE_WITH_EGRESS
}
});
// API Gateway
const testApiGateway = new aws_apigateway.RestApi(this, 'TestApi', {
restApiName: 'test-api',
deployOptions: {
stageName: 'dev'
},
defaultCorsPreflightOptions: {
allowOrigins: aws_apigateway.Cors.ALL_ORIGINS,
allowMethods: aws_apigateway.Cors.ALL_METHODS,
allowHeaders: aws_apigateway.Cors.DEFAULT_HEADERS
}
});
// Lambda統合
testApiGateway.root.addProxy({
defaultIntegration: new aws_apigateway.LambdaIntegration(testFunction),
anyMethod: true
});
}
}
VPC
Lambdaを配置するためのプライベートサブネットとNat Gatewayを配置するためのパブリックサブネットを作成します。Nat Gateway経由で内部からのみインターネットへアクセス可能なサブネットを作成するためにsubnetTypeにPRIVATE_WITH_EGRESSを指定します。
Nat Gatewayはパブリックサブネットに配置されるため、パブリックサブネットを作成する必要があります。特に指定しなくてもNat Gatewayに対してはEIPが付与されます。
Lambda
@aws-cdk/aws-lambda-python-alpha パッケージのPythonFunctionを使用すると、外部パッケージを使用したLambdaの作成が簡単になります。Lambda関数のソースコードを格納したディレクトリ内でpoetryプロジェクトを作成し、使いたいパッケージを追加しておけばCDKのデプロイ時に外部パッケージを含めたLambda関数が作成されます。
@aws-cdk/aws-lambda-python-alphaはAWS CDK 2.49.0時点でEXPERIMENTALですのでご注意ください。
# CDKプロジェクト内でのLambda関数のソースコードディレクトリへ移動
$ cd lambda/function/src/main
# Poetryプロジェクト作成
$ poetry init
# requestsパッケージを追加
$ poetry add requests
Lambdaの配置先サブネットをプライベートサブネットとします。
API Gateway
今回はAPI Gatewayのリソースはプロキシリソースとして作成しています。また、API Gatewayで受け取ったリクエストをLambdaで処理するためのプロキシ統合を作成します。