11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

やること

タイトル通り、FastAPIをLambdaで使用してAPIを設計し、APIGatewayでデプロイするのをCDKで行う。

前提

開発環境

  • Python 3.8
  • AWS CLI

FastAPIとMungum用のLambdaレイヤーを作成する準備

FastAPIとMungumをLambdaで使うためにはこれらの依存関係を直接Lambda環境にインストールさせる処理をしなければならない。
その手段としてLambdaレイヤーがあるので、レイヤーの材料となるdependencies.zipを作成する。

requirements.txtを作成

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関数のファイルを以下のように変更

lambda/app.py
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レイヤーを追加している点にも注目

lib/cdk-openapi-express-stack.ts
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に必要な外部ライブラリはローカルにインストールしていても動作しないので、直接ライブラリファイルを含めてデプロイするか、本記事のようにレイヤーを作成するかなどの処理が必要です。
レイヤーの方がスマートな気がしたので今回はこの方法で実装しました。

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?