AWS

LambdaとAPI Gatewayを使用したサーバーレスアプリ – HTTP API

スポンサーリンク
CloudFormationでAPI GatewayとLambdaのサーバレスアプリを作成する AWS
スポンサーリンク
スポンサーリンク

API GatewayとLambdaでサーバーレスアプリケーションを作成する

2つのリソースを組み合わせて、シンプルなサーバーレスWebアプリケーションを作成します。

1つ目はLambdaです。LambdaはAWSが提供するFaaSサービスです。

AWS Lambda はイベント発生時にお客様のコードを実行し、基盤となるコンピューティングリソースをお客様に代わって管理する、サーバーレスコンピューティングサービスです。

AWS Lambda の特徴

今回はLambdaをWebアプリのコンピューティングリソースとして使用します。

2つ目はAPI Gatewayです。
API GatewayはAWSが提供するフルマネージド型のAPI構築用サービスです。

Amazon API Gateway は、デベロッパーがあらゆる規模で API の公開、保守、モニタリング、セキュリティ保護、運用を簡単に行えるフルマネージドサービスです。

Amazon API Gateway の特徴

今回はHTTPタイプのAPI Gatewayを、Webアプリにアクセスするためのエンドポイントとして使用します。

なおREST APIタイプのAPI Gatewayを作成する方法については、以下のページをご確認ください。

構築する環境

Amazon.co.jp: AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版 : NRIネットコム株式会社, 佐々木 拓郎, 林 晋一郎, 金澤 圭: 本
Amazon.co.jp: AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版 : NRIネットコム株式会社, 佐々木 拓郎, 林 晋一郎, 金澤 圭: 本
Diagram of serverless app using Lambda & API Gateway.

API Gatewayを作成し、バックエンドにLambdaを配置します。

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

API GatewayはHTTP APIタイプで作成します。

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

環境構築用のCloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。

以下のURLにCloudFormationテンプレートを配置します。

awstut-fa/005 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

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

今回の環境を構成するための、各テンプレートファイルのポイントを取り上げます。

Lambda関数に関数を実行できる権限を付与する

fa-005-lambda.yamlでLambda関係のリソースを定義します。

まず関数本体の定義を確認します。

Resources: Function: Type: AWS::Lambda::Function Properties: Architectures: - !Ref Architecture Code: ZipFile: !Ref ZipFile FunctionName: !Sub ${Prefix}-function Handler: !Ref Handler Runtime: !Ref Runtime Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)

ArchitecturesプロパティはLambda関数を実行する基盤のプロセッサを指定するためのパラメータです。2021年9月29日より、関数をArmベースのGraviton2で実行することができるようになりました。

x86 または Arm/Graviton2 プロセッサ上で実行するように新規および既存の関数を設定できるようになりました。この選択により、2 つの方法でコストを節約できます。まず、Graviton2 アーキテクチャにより、関数がより効率的に実行されます。第二に、実行する時間に対する支払いが少なくなります。実際、Graviton2 を搭載した Lambda 関数は、20% 低いコストで最大 19% 優れたパフォーマンスを実現するように設計されています。

AWS Graviton2 プロセッサを搭載した AWS Lambda 関数 – Arm で関数を実行し、最大 34% 優れた料金パフォーマンスを実現

本プロパティはデフォルトでは「x86_64」とされていますが、今回は組み込み関数Fn::Refで変数を参照して「arm64」と指定することで、Graviton2上で関数を実行できます。

CodeプロパティでLambda関数で実行するコードに関して設定します。下記の通り、関数で実行するコードを3つの方法で用意することができます。

To deploy a function defined as a container image, you specify the location of a container image in the Amazon ECR registry. For a .zip file deployment package, you can specify the location of an object in Amazon S3. For Node.js and Python functions, you can specify the function code inline in the template.

AWS::Lambda::Function Code

今回はテンプレートファイル内にインラインでコードを記述します。

Lambda関数で実行するコードをインラインで記載する方法については、以下をご確認ください。

実行するコードは以下の通りです。

import json def lambda_handler(event, context): return { 'statusCode': 200, 'body': json.dumps('Hello form Awstut !') }
Code language: Python (python)

中身は辞書型で、Pythonでステータスコードとともに、JSON形式の文字列を返すというシンプルなものです。

Handlerプロパティは関数が呼び出された際に実行する関数を定義するパラメータです。上記の通り、今回はlambda_handler関数を定義していますので、同関数名を指定します。

Runtimeプロパティは関数のランタイム環境を指定するパラメータです。今回はPython3.8で実行するように指定します。

Roleプロパティで関数に関連付けるIAMロールを指定する必要があります。今回は以下のようにIAMロールを定義し、こちらを参照するように指定します。

Resources: FunctionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: - lambda.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Code language: YAML (yaml)

ManagedPolicyArnsプロパティで、作成するIAMロールにAWS管理ポリシーを関連付けます。今回はAWSLambdaBasicExecutionRoleを指定します。なお同ポリシーの内容は以下の通りです。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] }
Code language: JSON / JSON with Comments (json)

CloudWatch Logsへの書き込みに関する権限が提供するという内容です。

API Gatewayを作成するためには5つのリソースを定義する必要がある

fa-005-apigateway.yamlでAPI Gateway関係のリソースを定義します。

API Gatewayを通じてLambdaを実行する環境構築する場合、以下の5つのリソースを用意します。

  1. API Gateway本体
  2. ステージ
  3. 統合
  4. ルート
  5. API GatewayがLambda関数を呼び出す権限

順番に確認します。

API Gateway本体

まずAPI Gateway本体を確認します。

Resources: HttpApi: Type: AWS::ApiGatewayV2::Api Properties: Name: !Sub ${Prefix}-HttpApi Description: HttpApi. ProtocolType: HTTP
Code language: YAML (yaml)

ProtocolTypeプロパティで作成するAPI Gatewayのタイプを指定します。

API GatewayでRESTful APIを作成する場合、HTTP APIとREST APIの2つのタイプを選択することができます。

API Gateway を利用すると、HTTP API または REST API を使用して RESTful API を作成できます。HTTP API の使用は、API 管理機能を必要としない API を構築するために最適な手法です。HTTP API は、サーバーレスのワークロードと HTTP に最適化されています。これにより、API Gateway から提供される REST API と比較しても、コストを最大で 71% 削減しながら、レイテンシーを 60% 低減できます。

Amazon API Gateway の特徴

今回は本プロパティに「HTTP」を指定し、HTTP APIタイプとします。

ステージ

次にステージを確認します。

Resources: Stage: Type: AWS::ApiGatewayV2::Stage Properties: ApiId: !Ref HttpApi AutoDeploy: true StageName: $default
Code language: YAML (yaml)

ステージを用意し、開発用や本番用といったステージング環境を構築することができます。

API ステージは、API のライフサイクル状態への論理的なリファレンスです (例: dev、prod、beta、v2 など)。API ステージは API ID とステージ名で識別され、API の呼び出しに使用する URL に含まれます。

HTTP API のステージの使用

今回はStageNameプロパティに「$default」と指定することで、デフォルトエンドポイントを作成することができます。

ステージには、API のベース URL から呼び出される $default のステージを作成することができます。ベース URL は、https://{api_id}.execute-api.{region}.amazonaws.com/ のような形式になります。

HTTP API のステージの使用

統合

続いて統合を確認します。

Resources: Integration: Type: AWS::ApiGatewayV2::Integration Properties: ApiId: !Ref HttpApi ConnectionType: INTERNET CredentialsArn: !GetAtt ApiGatewayRole.Arn IntegrationMethod: POST IntegrationType: AWS_PROXY IntegrationUri: !Ref FunctionArn PayloadFormatVersion: '2.0'
Code language: YAML (yaml)

統合はAPI Gateway本体とLambda等のリソースの仲立ちをします。

統合は、ルートをバックエンドリソースに接続します。HTTP API は、Lambda プロキシ、AWS のサービス、および HTTP プロキシの統合をサポートします。

HTTP API の統合の設定

今回の構成ですと、統合を介して、API GatewayからバックエンドリソースであるLambda関数にリクエストを送信し、Lambda関数からのレスポンスをAPI Gatewayに返す形になります。

ApiIdプロパティでAPI Gateway本体を指定します。先述の本体リソースをRef関数で参照して指定します。

ConnectionTypeプロパティで統合エンドポイントへの接続タイプを指定します。本プロパティには「INTERNET」か「VPC_LINK」が設定可能ですが、今回はVPC外のLambdaをバックエンドリソースとしますので、「INTERNET」を指定します。

CredentialsArnプロパティは、API Gatewayがバックエンドリソースを呼び出すために必要な権限に関するプロパティです。後述するIAMロールのARNを指定します。

IntegrationTypeプロパティは統合タイプを指定するパラメータです。今回のようにLambda関数をバックエンドリソースとする場合、Lambdaプロキシ統合を選択します。

Lambda プロキシ統合を使用すると、API ルートを Lambda 関数と統合できます。クライアントが API を呼び出すと、API Gateway はリクエストを Lambda 関数に送信し、関数のレスポンスをクライアントに返します。

HTTP API の AWS Lambda プロキシ統合の使用

Lambdaプロキシ統合を使用する場合、IntegrationTypeプロパティに「AWS_PROXY」を指定します。

Lambdaプロキシ統合の場合、IntegrationMethodプロパティに指定する値は決まっています。

Lambda 統合では、関数呼び出しの Lambda サービスアクションの仕様に従って、統合リクエストに POST の HTTP メソッドを使用する必要があります。

AWS CLI を使用して Lambda プロキシ統合をセットアップする

上記の通り、本プロパティには「POST」を指定します。

IntegrationUriプロパティで呼び出すバックエンドリソースを指定します。今回はLambda関数を呼び出す構成としますので、先述のLambda関数を指定します。

PayloadFormatVersionプロパティはAPI Gatewayとバックエンドリソースの仲立ちで使用するペイロードのバージョンを指定するパラメータです。今回は最新バージョンである「2.0」を指定します。

ルート

ルートの定義を確認します。

Resources: Route: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref HttpApi RouteKey: 'GET /' Target: !Sub "integrations/${Integration}"
Code language: YAML (yaml)

ルートはHTTPメソッドおよびURLと、バックエンドリソースの紐付けを行うためのリソースです。

ルートは、直接の受信 API リクエストをバックエンドリソースにルーティングします。ルートは、HTTP メソッドとリソースパスという 2 つの部分で構成されます (例: GET /pets)。ルートに特定の HTTP メソッドを定義できます。

HTTP API のルートの使用

RouteKeyプロパティで紐付けるHTTPメソッドおよびURLを指定します。今回は「’GET /’」と指定することで、エンドポイントに対して、GETでルートURLにリクエストされた場合のルートを定義します。

Targetプロパティでルーティング先を指定します。ルーティング先は定義済みの統合を指定することができます。今回は組み込み関数Fn::Subを使用し、先述の統合リソースのIDを埋め込んで指定します。

API GatewayがLambda関数を呼び出す権限

先述の統合リソースのCredentialsArnプロパティですが、下記の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がバックエンドリソースを呼び出すためには、以下の通り、2つの方法でAPI Gatewayに権限を付与することができます。

apigAwsProxyRole の IAM ロールは、apigateway サービスが Lambda 関数を呼び出せるようにするポリシーが必要です。 (中略) credentials の IAM ロールを指定する代わりに、add-permission コマンドを呼び出して、リソースベースのアクセス許可を追加することができます。

AWS CLI を使用して Lambda プロキシ統合をセットアップする

今回は前者のIAMロールを割り当てることで、API Gatewayに権限を付与します。

ポリシーの中身を見ますと、Actionに「lambda:InvokeFunction」を、Resourceに先述のLambda関数を指定することで、同関数を呼び出す権限を付与するものであることがわかります。

なお以下の通り、Lambdaのリソースベースのポリシーを使用することでも、API Gatewayに同関数を呼び出す権限を付与することができます。

Resources: Permission: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref FunctionName Action: lambda:InvokeFunction Principal: apigateway.amazonaws.com
Code language: YAML (yaml)

環境構築

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

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

CloudFormationスタックを作成します。

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

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

  • API Gateway本体のID:io3gltn5gi
  • 統合のID:wezv2df
  • Lambda関数名:fa-005-function

AWS Management ConsoleからもAPI Gateway関係のリソースの作成状況を確認します。

まずAPI Gateway本体およびステージを確認します。

You can see that a default stage has been created in the API Gateway.

API Gateway本体が正常に作成されています。またステージ名が「$default」のデフォルトステージが作成されていることもわかります。これでステージ名を含めない、API GatewayのルートURLを使用することができます。

次に統合を確認します。

統合を介して、API Gatewayに作成したLambda関数が関連づいていることがわかります。また同関数を呼び出すための権限を持つIAMロールが関連づいていることもわかります。

最後にルートも確認します。

Integration is assigned to the API Gateway root URL.

API GatewayのルートURLに先述の統合が関連づいていることがわかります。これでAPI GatewayのルートURLにアクセスすると、統合に関連づくLambda関数が呼び出されるという構成が成立します。

動作確認:API Gatewayエンドポイントにアクセスする

準備が整いましたので、API Gatewayにアクセスします。

API Gatewayに作成されるAPIエンドポイントは、以下の通り、APIのIDおよびリージョン情報を組み合わせて作成されます。

API エンドポイント

特定のリージョンにデプロイされる API Gateway の API のホスト名。ホスト名の形式は {api-id}.execute-api.{region}.amazonaws.comです。

Amazon API Gateway の概念

以上に従って、今回作成されたAPIエンドポイントは「https://io3gltn5gi.execute-api.ap-northeast-1.amazonaws.com」になります。

実際にアクセスします。

$ curl https://io3gltn5gi.execute-api.ap-northeast-1.amazonaws.com/ "Hello form Awstut !"
Code language: Bash (bash)

正常に文字列が返ってきました。

ちなみに未定義のルートにアクセスすると、エラーが発生した旨のメッセージが返ってきます。

$ curl https://io3gltn5gi.execute-api.ap-northeast-1.amazonaws.com/hogehoge {"message":"Not Found"}
Code language: Bash (bash)

以上より、ユーザーがAPIエンドポイントにアクセスすると、ルートで定められたURL・HTTPメソッドに対するリクエストだった場合、統合を介してLambda関数が実行されます。そして再び統合・API Gatewayを通じて、HTTPレスポンスがユーザに返ってきます。

まとめ

Lambda関数とAPI Gatewayで、シンプルなサーバーレスアプリケーションを構築する手法を確認しました。API Gatewayを作成する場合、本体を含めて5つのリソースを組み合わせる必要があることを確認しました。

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