目次

API GatewayとLambdaをCloudFormationテンプレートで作成する方法を説明します。

前提

このテンプレートは、API GatewayがLambda関数にリクエストをルーティングする基本的な構成を示しています。

以下は基本的なテンプレートの例です。

CloudFormationテンプレート例

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  MyLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.handler
      Role: 
        Fn::GetAtt:
          - LambdaExecutionRole
          - Arn
      Code:
        ZipFile: |
          exports.handler = async (event) => {
  const response = {
              statusCode: 200,
              body: JSON.stringify('Hello from Lambda!'),
            };
            return response;
          };
      Runtime: 'nodejs20.x'

  LambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: 'Allow'
            Principal:
              Service: 'lambda.amazonaws.com'
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: 'lambda-execution-policy'
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: 'Allow'
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: '*'

  ApiGatewayRestApi:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: 'MyApiGateway'
      Description: 'API Gateway for Lambda'

  ApiGatewayResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      ParentId:
        Fn::GetAtt:
          - ApiGatewayRestApi
          - RootResourceId
      PathPart: 'mylambda'
      RestApiId:
        Ref: 'ApiGatewayRestApi'

  ApiGatewayMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: 'NONE'
      HttpMethod: 'GET'
      ResourceId:
        Ref: 'ApiGatewayResource'
      RestApiId:
        Ref: 'ApiGatewayRestApi'
      Integration:
        IntegrationHttpMethod: 'POST'
        Type: 'AWS_PROXY'
        Uri:
          Fn::Sub:
            - 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaArn}/invocations'
            - LambdaArn:
                Fn::GetAtt:
                  - MyLambdaFunction
                  - Arn

  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    Properties:
      RestApiId:
        Ref: 'ApiGatewayRestApi'
      StageName: 'prod'
    DependsOn:
      - ApiGatewayMethod

  LambdaPermission:
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName:
        Ref: 'MyLambdaFunction'
      Principal: 'apigateway.amazonaws.com'
      SourceArn:
        Fn::Sub:
          - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiId}/*/*'
          - ApiId:
              Ref: 'ApiGatewayRestApi'

説明

  • MyLambdaFunction: Lambda関数を定義しています。Node.js 14.xランタイムを使用し、簡単なハンドラー関数を記述しています。
  • LambdaExecutionRole: Lambda関数の実行に必要なIAMロールを作成しています。このロールはログの作成と書き込みを許可します。
  • ApiGatewayRestApi: API Gatewayのリソースを作成しています。
  • ApiGatewayResource: API Gatewayにリソース(エンドポイントの一部)を追加しています。
  • ApiGatewayMethod: HTTPメソッド(GET)を定義し、Lambda関数との統合を設定しています。
  • ApiGatewayDeployment: API Gatewayのデプロイメントを作成し、prodステージを作成しています。このリソースはApiGatewayMethodに依存します。
  • LambdaPermission: API GatewayがLambda関数を呼び出すための権限を設定しています。

デプロイ手順

このテンプレートを使用して、API GatewayとLambda関数をCloudFormationでデプロイできます。デプロイするには、このテンプレートを.yamlファイルとして保存し、以下のAWS CLIコマンドを実行します。

aws cloudformation create-stack --stack-name MyStack --template-body file://path_to_your_template.yaml --capabilities CAPABILITY_NAMED_IAM

このコマンドはCloudFormationスタックを作成し、テンプレートに基づいてリソースをプロビジョニングします。


CloudFormationテンプレートを更新する場合

aws cloudformation update-stack --stack-name MyStack --template-body file://path_to_your_template.yaml

動作確認

URLはAWSコンソールで、API Gateway > ステージから確認できます。

以下のcurlコマンドで、「Hello from Lambda!”」が返ってくればOK

curl https://xxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/mylambda

終わりに

爆速で、ApiGatewayとLambdaの統合を作ってみました。CloudFormation便利ですね。

流石に適当に作りすぎているので、以下の部分は修正の余地ありかと思います。


Lambda関数のコード管理

ZipFileプロパティを使用してインラインでコードを記述していますが、実際のプロジェクトではバージョン管理された外部ファイルを参照するほうが管理しやすくなります。S3バケットにコードを配置し、そこから参照する方法が推奨されます。

Code:
S3Bucket: !Ref CodeS3Bucket
S3Key: !Ref CodeS3Key

API Gatewayのステージ名の管理

StageNameをハードコーディングしている(prod)ため、複数の環境(開発、テスト、本番)を管理する場合に柔軟性が欠けることがあります。ステージ名をパラメータとして扱い、異なるデプロイ環境に対応できるようにすることが推奨されます。

Parameters:
  StageName:
    Type: String
    Default: prod

Resources:
  ApiGatewayDeployment:
    Properties: