API Gateway × LambdaでサーバーレスAPI構築!CloudFormationで自動化する手順ガイド

AWS

はじめに

近年、サーバーレスアーキテクチャは、スケーラビリティやコスト効率の高さから多くのシステムに採用されています。特に API GatewayAWS Lambda を組み合わせることで、インフラ管理の手間を最小限に抑えつつ、柔軟で高性能なWeb APIを構築することが可能です。

本記事では、これらのサービスを AWS CloudFormation を用いてコードとして定義し、自動的に構築する方法を解説します。CloudFormationを活用することで、以下のようなメリットが得られます

  • インフラ構成の再現性:環境ごとの構築漏れや設定ミスを防止
  • 構成管理の一元化:コードベースでインフラを管理・バージョン管理可能
  • 自動化による効率化:手動作業を減らし、デプロイ作業をスムーズに

コンソールから作成する手順

コンソールから今回のリソースを作成する手順は下記記事で紹介しています。

API Gateway×LambdaでREST API構築入門
API GatewayとAWS Lambdaを使ってサーバーレスなREST APIを構築する方法を初心者向けに丁寧に解説。デプロイと動作確認までカバー

構成図と全体イメージ

本記事では、クライアントからのリクエストを API Gateway が受け取り、Lambda関数 に処理を委ね、最終的にその結果をクライアントに返すというシンプルなサーバーレス構成を構築します。

以下は、今回構築するアーキテクチャの概要図です。

アーキテクチャ構成図

今回作成する簡単なアーキテクチャー図です。

今回構築する構成のポイント

  • API Gateway
    • REST APIとして動作
    • /hello のようなシンプルなエンドポイントを公開
    • Lambda関数との統合には「Lambdaプロキシ統合」を使用
  • AWS Lambda
    • リクエスト内容を処理し、JSON形式のレスポンスを返す
    • 言語は Python または Node.js を使用(後で選択可能)
  • IAMロール
    • Lambda実行用に最低限のIAMロールを作成
    • CloudWatch Logsへの書き込み権限を付与

CloudFormationテンプレートの作成

この章では、Lambda関数・IAMロール・API Gateway を含むサーバーレスAPIをCloudFormationテンプレートで定義します。テンプレートはYAML形式を使用し、手軽に再利用できるように構成しています。

Lambda関数定義

まずは、APIのリクエスト処理を担う Lambda関数 を作成します。ここでは Node.js 18.x を例にしていますが、Pythonなどに置き換えることも可能です。

  HelloFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: HelloFunction
      Runtime: nodejs18.x
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            return {
              statusCode: 200,
              body: JSON.stringify({ message: "Hello from Lambda!" }),
            };
          };

IAMロール定義

Lambda関数がログを出力できるように、最小限のポリシーを持つIAMロールを作成します。

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

API Gateway リソース定義

API Gatewayを作成し、/hello エンドポイントでLambdaを呼び出せるように設定します。

RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: HelloApi

  RootResourceId:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: hello
      RestApiId: !Ref RestApi

  ApiMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      RestApiId: !Ref RestApi
      ResourceId: !Ref RootResourceId
      HttpMethod: GET
      AuthorizationType: NONE
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: 
          Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloFunction.Arn}/invocations

API GatewayとLambdaの連携

API Gateway が Lambda 関数を呼び出すために必要な「実行権限」を明示的に付与するためにAWS::Lambda::Permissionを定義します。
CloudFormationで Lambda と API Gateway を連携させる場合、Lambda 側にこの権限がないとリクエストが拒否されてしまいます。

LambdaApiPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref HelloFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: 
        Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/hello

API Gatewayのデプロイ

API Gatewayでエンドポイントを公開するには、作成したAPIに対して 「デプロイ」 を行い、ステージ(例:prod を指定する必要があります。

CloudFormationを使えば、ステージの作成とAPIのデプロイも自動化できます。

デプロイの定義

以下は、ステージ名を prod としてLambda統合済みのAPI Gatewayを公開するためのCloudFormation構成です。

デプロイメント(Deployment)の定義
ApiDeployment:
  Type: AWS::ApiGateway::Deployment
  DependsOn: ApiMethod  # メソッド定義が完了していることが必要
  Properties:
    RestApiId: !Ref RestApi
    StageName: prod

DependsOn をつけることで、メソッドなどのリソース定義が完了した後にデプロイされるようになります。

必要な出力(エンドポイントURLなど)

スタック出力に、API GatewayのURLを表示させることで、デプロイ完了後すぐに確認できるようにします。

Outputs:
  ApiUrl:
    Description: "Invoke URL"
    Value: 
      Fn::Sub: https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/hello

デプロイと動作確認

CloudFormationテンプレートを使って、API GatewayとLambdaの構成をデプロイした後は、実際にAPIを呼び出して動作を確認してみましょう。

デプロイ手順

CloudFormationテンプレート(例:template.yml)を以下のコマンドでデプロイします。

aws cloudformation deploy \
  --template-file template.yml \
  --stack-name hello-api-stack \
  --capabilities CAPABILITY_NAMED_IAM

--capabilities CAPABILITY_NAMED_IAM はIAMロール作成を許可するために必要です。

デプロイが完了すると、以下のような出力が表示されます。

CloudFormationの出力タブのところで、Outputの値を確認できます。

URLに対してcurlコマンドを投げることで正常に動作しているか確認できます。

サンプルコード(テンプレート)

AWSTemplateFormatVersion: '2010-09-09'
Description: Lambda + API Gateway のシンプルな構成

Resources:
  HelloFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: HelloFunction
      Runtime: nodejs18.x
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            return {
              statusCode: 200,
              body: JSON.stringify({ message: "Hello from Lambda!" }),
            };
          };

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

  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: HelloApi

  RootResourceId:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: hello
      RestApiId: !Ref RestApi

  ApiMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      RestApiId: !Ref RestApi
      ResourceId: !Ref RootResourceId
      HttpMethod: GET
      AuthorizationType: NONE
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: 
          Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloFunction.Arn}/invocations

  LambdaApiPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref HelloFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: 
        Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/hello

  ApiDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: ApiMethod
    Properties:
      RestApiId: !Ref RestApi
      StageName: prod

Outputs:
  ApiUrl:
    Description: "Invoke URL"
    Value: 
      Fn::Sub: https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/hello

まとめ

本記事では、AWS CloudFormation を使って API GatewayとLambdaを組み合わせたサーバーレスAPI を自動構築する方法を解説しました。

以下に、構築の流れを改めて整理します

CloudFormationによる構築ステップ

  1. Lambda関数の定義
     リクエストを処理する関数を作成。コードはインラインまたはS3に配置可能。
  2. IAMロールの設定
     LambdaがCloudWatch Logsなどにアクセスできるよう最小限の権限を付与。
  3. API Gatewayの設定
     REST APIを作成し、/hello などのエンドポイントをLambda関数に統合。
  4. API Gateway デプロイ
    API Gatewayでエンドポイントを公開するためにデプロイを実施。
  5. 出力設定とデプロイ
     テンプレートにエンドポイントURLを出力。aws cloudformation deploy で一発構築。

参考リンク

コメント

タイトルとURLをコピーしました