CFNを使ってREST APIタイプのAPI Gatewayを構築

目次

CloudFormationを使ってREST APIタイプのAPI Gatewayを構築

以下のページで、HTTP APIタイプのAPI Gatewayについて取り上げました。

あわせて読みたい
LambdaとAPI Gatewayを使用したサーバーレスアプリ – HTTP API 【API GatewayとLambdaでサーバーレスアプリケーションを作成する】 2つのリソースを組み合わせて、シンプルなサーバーレスWebアプリケーションを作成します。 1つ目はL...

今回はREST APIタイプのAPI Gatewayを構築する方法を確認します。

構築する環境

Diagram of create REST API type API Gateway.

API Gatewayを作成し、バックエンドにLambdaを配置します。
ユーザからHTTPリクエストを受けた場合、API Gatewayがエンドポイントとなって、代わりにLambda関数を呼び出し、同関数の実行結果をユーザに返すというシンプルな構成です。
API GatewayはREST APIタイプで作成します。

Lambda関数のランタイム環境はPython3.8とします。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-fa/tree/main/052

テンプレートファイルのポイント解説

LambdaをバックエンドとするAPI Gatewayを構築する場合、以下の6つのリソースを用意します。

  1. API Gateway本体
  2. リソース
  3. メソッド
  4. 統合
  5. デプロイメント
  6. ステージ

次に確認すべき点は、API Gatewayのバージョンです。
大別すると、API Gatewayは2つのバージョンが存在します。
一方はREST APIのバージョンで、もう一方はHTTP APIやWebsocket APIのバージョンです。

CloudFormationにおいても、両バージョンはリソースとして分かれています。
例えばREST APIタイプのAPI Gateway本体を定義する場合、Typeプロパティは「AWS::ApiGateway::RestApi」となります。
次にREST APIタイプのAPI Gateway本体を定義する場合は、Typeプロパティは「AWS::ApiGatewayV2::Api」となります。

API Gateway本体

Resources:
  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      EndpointConfiguration:
        Types:
          - EDGE
      Name: !Ref Prefix
Code language: YAML (yaml)

ポイントはREST APIにおけるAPIエンドポイントタイプの指定です。
REST APIには3種類のAPIエンドポイントタイプがあります。

API エンドポイントタイプは、API トラフィックの大部分の発信元となっている場所に応じて、エッジ最適化、リージョン別、またはプライベートとすることができます。

API Gateway API に対してセットアップするエンドポイントタイプを選択する

デフォルトではエッジ最適化APIエンドポイントが選ばれますので、今回もこちらを指定します。
ちなみにこのAPIエンドポイントタイプの特徴は、CloudFrontを経由した配信にあります。

エッジ最適化された API エンドポイントは、地理的に分散されたクライアントに最適です。API リクエストは、最寄りの CloudFront POP (Point Of Presence) にルーティングされます。これは、API Gateway REST API のデフォルトのエンドポイントタイプです。

API Gateway API に対してセットアップするエンドポイントタイプを選択する

つまりこのAPIエンドポイントを選択すれば、ユーザーが自らAPI Gatewayの前面にCloudFrontを配置せずとも、デフォルトでCloudFront経由で配信されるということです。

リソース

AWS公式では、リソースについて以下のように説明されています。

各 API リソースは、API Gateway でサポートされている一意の HTTP 動詞を持つ 1 つ以上の API メソッドを公開できます。

Amazon API Gateway の概念

つまりAPI Gatewayリソースは、作成するAPIエンドポイントURLにおけるPATHの一部に相当します。

Resources:
  Resource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: !Sub "${Prefix}-resource"
      RestApiId: !Ref RestApi
Code language: YAML (yaml)

ポイントは2点です。

1点目はPathPartプロパティです。
先述の通り、API GatewayリソースはAPIエンドポイントのURLを構成する文字列に相当します。
今回ですと、組み込み関数Fn::Subを使用して、このプロパティに「fa-052-resource」を指定することになりますが、この値はURLの以下の部分です。

https://[api-endpoint]/[stage-name]/[resource-name]/

2点目はParentIdプロパティです。
このプロパティは作成するAPI Gatewayリソースの親リソースを指定する項目です。
と言うのも、API Gatewayリソースはルートリソースをベースとしたツリー構造なのです。

API リソースはアプリケーションロジックに従ってリソースツリーで整理されます。

Amazon API Gateway の概念

今回はルートリソースの直下にリソースを紐づけます。
組み込み関数Fn::GetAttを使用して、API Gateway本体からルートリソースのIDを取得し、このプロパティに設定します。

メソッドと統合

メソッドについては先ほど引用した通りです。
つまりGETやPOSTといったHTTPメソッドに相当します。

Resources:
  Method:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        ConnectionType: INTERNET
        Credentials: !GetAtt ApiGatewayRole.Arn
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FunctionArn}/invocations"
      ResourceId: !Ref Resource
      RestApiId: !Ref RestApi
Code language: YAML (yaml)

ポイントは2点目あります。

1点目はHttpMethodプロパティです。
このプロパティでHTTPメソッドを指定できますが、今回は「GET」を指定します。
今回の構成ですと、ResourceIdプロパティと組み合わせることによって、APIエンドポイントの/fa-052-resource/にGETメソッドでアクセスした場合の挙動を定義するという意味になります。

2点目は統合です。
統合についてAWS公式では以下の通りに説明されています。

API メソッドを設定したら、バックエンドのエンドポイントに統合する必要があります。バックエンドのエンドポイントは、統合エンドポイントとも呼ばれ、Lambda 関数、HTTP ウェブページ、または AWS のサービスアクションにすることができます。

REST API 統合の設定

つまり統合は、API Gatewayとバックエンドリソースの仲立ちします。
今回の構成ですと、ユーザーがAPI Gatewayにアクセスした際に、バックエンドであるLambda関数を実行し、実行結果をAPI Gatewayに返す働きをするということです。

統合はIntegrationプロパティの内部で設定します。

ConnectionTypeプロパティは統合エンドポイントのネットワークタイプを設定するものです。
特定のVPC内からのみアクセス可能なAPI Gatewayタイプ(プライベートAPIエンドポイント)を作成する場合は「VPC_LINK」、それ以外の用途の場合は「INTERNET」を指定します。
今回は後者です。

CredentialsプロパティはAPI Gatewayに関連づけるIAMロールを指定します。
今回ですと、以下のIAMロールを指定します。

Resources:
  ApiGatewayRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - apigateway.amazonaws.com
      Policies:
        - PolicyName: !Sub "${Prefix}-InvokeFunctionPolicy"
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - lambda:InvokeFunction
                Resource:
                  - !Ref FunctionArn
Code language: YAML (yaml)

API GatewayにバックエンドであるLambda関数を実行する権限を与える内容です。

3つのプロパティ(IntegrationHttpMethod, Type, Uri)で、バックエンドにLambda関数を指定します。
Lambda関数をバックエンドとする方法について、AWS公式では、以下の通りに解説されています。

Lambda プロキシ統合または Lambda 非プロキシ (カスタム) 統合を使用して、API メソッドを Lambda 関数に統合できます。

Lambda プロキシ統合では、必要なセットアップを簡単に行えます。統合の HTTP メソッドを POST に設定し、統合エンドポイント URI を特定の Lambda 関数のアクションを呼び出す Lambda 関数の ARN に設定して、ユーザーに代わって Lambda 関数を呼び出す許可を API Gateway に付与します。

API Gateway で Lambda 統合を設定する

今回は上記の引用に従い、Lambdaプロキシ統合を使用します。
引用の通りに、3つのプロパティを設定します。
IntegrationHttpMethodプロパティに「POST」、TypeプロパティにLambdaプロキシ統合を意味する「AWS_PROXY」、Uriプロパティに実行するLambda関数を意味するURLを指定します。

デプロイメント

AWS公式では、デプロイメントについて以下のように説明しています。

API Gateway では、REST API のデプロイは Deployment リソースにより表現されます。これは、RestApi リソースによって表される API の実行可能ファイルと似ています。

クライアントが API を呼び出すには、デプロイを作成してステージを関連付ける必要があります。

API Gateway で REST API をデプロイします。
Resources:
  Deployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn:
      - Method
    Properties:
      RestApiId: !Ref RestApiCode language: CSS (css)

特別な設定は不要です。
RestApiIdプロパティでAPI Gateway本体のIDを設定するだけです。

ステージ

AWS公式では、ステージについて以下のように説明しています。

API (例: ‘dev’、’prod’、’beta’、’v2’ など) のライフサイクル状態への論理的な参照。

Amazon API Gateway の概念

つまりステージは、作成するAPIエンドポイントURLにおけるPATHの一部に相当します。

Resources:
  Stage:
    Type: AWS::ApiGateway::Stage
    Properties:
      DeploymentId: !Ref Deployment
      RestApiId: !Ref RestApi
      StageName: !Sub "${Prefix}-stage"
Code language: YAML (yaml)

DeploymentIdプロパティでデプロイメントのIDを指定します。
これでデプロイメントとステージを関連付けます。

StageNameプロパティがポイントです。
先述の通り、ステージはAPIエンドポイントのURLを構成する文字列に相当します。
今回ですと、組み込み関数Fn::Subを使用して、このプロパティに「fa-052-stage」を指定することになりますが、この値はURLの以下の部分です。

https://[api-endpoint]/[stage-name]/[resource-name]/

(参考)バックエンドのLambda関数

Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Code:
        ZipFile: |
          import json

          def lambda_handler(event, context):
            return {
              'statusCode': 200,
              'body': json.dumps('Hello form Awstut !')
            }
      FunctionName: !Sub "${Prefix}-function"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)

特別な設定は不要です。
実行すると「Hello form Awstut !」を返すという単純な内容です。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • API Gatewayの名前:fa-052
  • API Gatewayのエンドポイント:https://ee9xq1xttd.execute-api.ap-northeast-1.amazonaws.com/
  • API Gatewayのステージ名:fa-052-stage
  • API Gatewayのリソース名:fa-052-resource
  • バックエンドで動作するLambda関数:fa-052-function

AWS Management ConsoleからもAPI Gatewayを確認します。

REST API type API Gateway

Edge最適化のREST APIタイプが作成されました。

リソースとメソッドの内容を確認します。

Resources, Method and Integration of REST API.

ルートリソース(「/」)の直下に、今回作成した「fa-052-resource」が位置しています。
このリソースのメソッドとしてGETが用意されています。
GETで定義されている内容を見ると、Lambdaプロキシ統合を通じて、Lambda関数「fa-052-function」が関連づいていることがわかります。

次にステージとデプロイメントを確認します。

Stage and Endpoint of REST API.

「fa-052-stage」という名前のステージが作成され、正常にデプロイされていることが確認できます。

動作確認

準備が整いましたので、API Gatewayのエンドポイントにアクセスします。
今回アクセスするURLは以下の4種類の情報を組み合わせて定まります。

  • エンドポイント:ee9xq1xttd.execute-api.ap-northeast-1.amazonaws.com
  • ステージ名:fa-052-stage
  • リソース名:fa-052-resource
  • HTTPメソッド:GET

つまり以下の通りです。

GET https://ee9xq1xttd.execute-api.ap-northeast-1.amazonaws.com/fa-052-stage/fa-052-resource

実際にアクセスします。

The result of invoking REST API.

正常に文字列が返ってきました。
ユーザーがAPIエンドポイントにアクセスすることによって、統合を通じてLambda関数が実行され、実行結果が返ってきたということです。

まとめ

REST APIタイプのAPI Gatewayを構築する方法を確認しました。

目次