やること
タイトル通り、FastAPIをLambdaで使用してAPIを設計し、APIGatewayでデプロイするのをCDKで行う。
前提
-
OpenAPI を使ってAPIを設計
- CDKではRestApiではなく、OpenAPI定義からAPIGatewayを作ることができるSpecRestApiを使う
-
LanbdaをCDKでデプロイするところまでは既に記事があるのでそちらを参照してCDKを立ち上げる
https://qiita.com/stake15/items/2616a568593d48e5bd16
上の記事ではLambdaの設定部分が省略されているので、そこは公式ドキュメント参照。
現時点では英語ばかりだしドキュメント複雑だし、わからなければ「Lambda CDK」とかで検索。https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html
開発環境
- Python 3.8
- AWS CLI
FastAPIとMungum用のLambdaレイヤーを作成する準備
FastAPIとMungumをLambdaで使うためにはこれらの依存関係を直接Lambda環境にインストールさせる処理をしなければならない。
その手段としてLambdaレイヤーがあるので、レイヤーの材料となるdependencies.zipを作成する。
requirements.txtを作成
fastapi
mangum
依存関係をzipにまとめる
mkdir python
pip install -r requirements.txt -t python/python/lib/python3.10/site-packages/
cd python
zip -r ../dependencies.zip .
cd ..
rm -rf python
この辺りの詳細や、上記コマンドを自動化させる方法は別の記事に記載
Fast APIを使う
Lambda関数のファイルを以下のように変更
from fastapi import FastAPI
from mangum import Mangum
app = FastAPI()
@app.get("/sample", status_code=200)
async def root():
return {"message": "Successfully API"}
handler = Mangum(app)
続いてlibディレクトリのCDKファイル
Lambdaレイヤーを追加している点にも注目
import * as cdk from "aws-cdk-lib";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
import * as iam from "aws-cdk-lib/aws-iam";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as signer from "aws-cdk-lib/aws-signer";
import { Construct } from "constructs";
import * as fs from "fs";
import * as path from "path";
import * as yaml from "yaml";
export class SrcStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// deploy時の引数 or envファイル参照で行う
const env_name = this.node.tryGetContext("env") ?? process.env.ENV_NAME;
const signingProfile = new signer.SigningProfile(this, "SigningProfile", {
platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA,
});
const codeSigningConfig = new lambda.CodeSigningConfig(
this,
"CodeSigningConfig",
{
signingProfiles: [signingProfile],
}
);
// レイヤー作成
const layer = new lambda.LayerVersion(this, "CustomLayer", {
code: lambda.Code.fromAsset("dependencies.zip"),
compatibleRuntimes: [lambda.Runtime.PYTHON_3_10],
description: "A layer to hold the FastAPI and Mangum dependencies",
});
// Lambda関数の作成
const fn = new lambda.Function(this, "handler", {
codeSigningConfig,
runtime: lambda.Runtime.PYTHON_3_10,
handler: "app.handler",
code: lambda.Code.fromAsset(path.join(__dirname, "../lambda")),
layers: [layer], // レイヤーを設定
});
// SpecRestApiを使ったAPIGatewayの作成
const swaggerYaml = yaml.parse(
fs.readFileSync("./api/docs/openapi.yaml").toString()
);
for (const path in swaggerYaml.paths) {
for (const method in swaggerYaml.paths[path]) {
swaggerYaml.paths[path][method]["x-amazon-apigateway-integration"] = {
uri: `arn:${cdk.Aws.PARTITION}:apigateway:${cdk.Aws.REGION}:lambda:path/2015-03-31/functions/${fn.functionArn}/invocations`,
passthroughBehavior: "when_no_match",
httpMethod: "POST",
type: "aws_proxy",
};
}
}
const apigw = new apigateway.SpecRestApi(this, "RestApi", {
apiDefinition: apigateway.ApiDefinition.fromInline(swaggerYaml),
});
fn.addPermission("LambdaPermisson", {
principal: new iam.ServicePrincipal("apigateway.amazonaws.com"),
action: "lambda:InvokeFunction",
sourceArn: apigw.arnForExecuteApi(),
});
}
}
デプロイして終わり
まとめ
FastAPIをLambdaで使用してAPIを設計し、APIGatewayでデプロイするのをCDKで行いました。
FastAPIを使えば簡単にAPIを設定できました。
また、Lambdaに必要な外部ライブラリはローカルにインストールしていても動作しないので、直接ライブラリファイルを含めてデプロイするか、本記事のようにレイヤーを作成するかなどの処理が必要です。
レイヤーの方がスマートな気がしたので今回はこの方法で実装しました。