AWS Lambda の blank 関数サンプルアプリケーション - AWS Lambda

AWS Lambda の blank 関数サンプルアプリケーション

blank 関数のサンプルアプリケーションは、Lambda API を呼び出す関数を使用し、Lambda の一般的なオペレーションを示すスターター アプリケションです。ロギング、環境変数、AWS X-Ray トレース、レイヤー、単体テスト、AWS SDK の使用を示します。このアプリケーションについて調べ、お使いのプログラミング言語で Lambda 関数を構築したり、自分のプロジェクトの出発点として使用したりする方法を学びます。

このサンプルアプリケーションのバリアントは、次の言語で使用できます。

Variants

このトピックの例では、Node.js バージョンのコードが強調されていますが、詳細は通常すべてのバリアントに適用できます。

サンプルは、AWS CLI および AWS CloudFormation を使用して数分でデプロイできます。README の指示に従い、ご自分のアカウントでダウンロード、設定、デプロイしてください。

アーキテクチャとハンドラーコード

サンプルアプリケーションは、関数コード、AWS CloudFormation テンプレート、およびサポートリソースで構成されています。サンプルをデプロイするときは、次の AWS サービスを使用します。

  • AWS Lambda - 関数コードの実行、CloudWatch Logs へのログの送信、X-Ray へのトレースデータの送信を行います。また、この関数は Lambda API を呼び出して、現在のリージョンでのアカウントのクォータと使用状況に関する詳細を取得します。

  • AWS X-Ray - トレースデータの収集、トレースのインデックス作成 (検索用)、サービスマップの生成を行います。

  • Amazon CloudWatch — ログとメトリックを格保存します。

  • AWS Identity and Access Management(IAM) — アクセス許可を付与します。

  • Amazon Simple Storage Service (Amazon S3) — デプロイ時に関数のデプロイパッケージを保存します。

  • AWS CloudFormation - アプリケーションリソースを作成し、関数コードをデプロイします。

各サービスには標準料金が適用されます。詳細については、AWS 料金を参照してください。

関数コードは、イベントを処理するための基本的なワークフローを示しています。ハンドラーは、入力として Amazon Simple Queue Service (Amazon SQS) イベントを受け取り、そのイベントに含まれるレコードを反復処理して、各メッセージの内容をログ記録します。これは、イベントの内容、コンテキストオブジェクト、環境変数をログ記録します。次に、AWS SDK を呼び出し、レスポンスを Lambda ランタイムに渡します。

blank-nodejs/function/index.js - ハンドラーコード

// Handler exports.handler = async function(event, context) { event.Records.forEach(record => { console.log(record.body) }) console.log('## ENVIRONMENT VARIABLES: ' + serialize(process.env)) console.log('## CONTEXT: ' + serialize(context)) console.log('## EVENT: ' + serialize(event)) return getAccountSettings() } // Use SDK client var getAccountSettings = function(){ return lambda.getAccountSettings().promise() } var serialize = function(object) { return JSON.stringify(object, null, 2) }

ハンドラーの入出力型と非同期プログラミングのサポートは、ランタイムによって異なります。この例のハンドラーメソッドは async です。Node.js では、これはランタイムに promise を返す必要があることを意味します。Lambda ランタイムは、promise が解決されるのを待ち、呼び出し元にレスポンスを返します。関数コードまたは AWS SDK クライアントがエラーを返した場合、ランタイムはエラーを JSON ドキュメントにフォーマットして返します。

サンプルアプリケーションには、イベントを送信するAmazon SQS キューは含まれていませんが、Amazon SQS (event.json) からのイベントを使用して、イベントの処理方法が示されています。アプリケーションに Amazon SQS キューを追加する方法については、Amazon SQS での Lambda の使用 を参照してください。

AWS CloudFormation および AWS CLI を使用したデプロイの自動化

サンプルアプリケーションのリソースは AWS CloudFormation テンプレートで定義され、AWS CLI を使用してデプロイされます。プロジェクトには、アプリケーションのセットアップ、デプロイ、呼び出し、および解体のプロセスを自動化する簡単なシェルスクリプトが含まれています。

アプリケーションテンプレートでは、AWS Serverless Application Model (AWS SAM) リソースタイプを使用してモデルを定義します。AWS SAM は、実行ロール、API、およびその他のリソースの定義を自動化することで、サーバーレスアプリケーションのテンプレート作成を簡素化します。

テンプレートは、アプリケーションスタック内のリソースを定義します。これには、関数およびその実行ロールのほか、関数のライブラリの依存関係を提供する Lambda レイヤーが含まれます。スタックには、AWS CLI がデプロイ中に使用するバケットまたは CloudWatch Logs グループは含まれません。

blank-nodejs/template.yml - サーバーレスリソース

AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS::Serverless-2016-10-31' Description: An AWS Lambda application that calls the Lambda API. Resources: function: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: nodejs12.x CodeUri: function/. Description: Call the AWS Lambda API Timeout: 10 # Function's execution role Policies: - AWSLambdaBasicExecutionRole - AWSLambda_ReadOnlyAccess - AWSXrayWriteOnlyAccess Tracing: Active Layers: - !Ref libs libs: Type: AWS::Serverless::LayerVersion Properties: LayerName: blank-nodejs-lib Description: Dependencies for the blank sample app. ContentUri: lib/. CompatibleRuntimes: - nodejs12.x

アプリケーションをデプロイすると、AWS CloudFormation は AWS SAM 変換をテンプレートに適用し、AWS CloudFormation や AWS::Lambda::Function などの標準タイプの AWS::IAM::Role テンプレートを生成します。

例 処理済みテンプレート

{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "An AWS Lambda application that calls the Lambda API.", "Resources": { "function": { "Type": "AWS::Lambda::Function", "Properties": { "Layers": [ { "Ref": "libs32xmpl61b2" } ], "TracingConfig": { "Mode": "Active" }, "Code": { "S3Bucket": "lambda-artifacts-6b000xmpl1e9bf2a", "S3Key": "3d3axmpl473d249d039d2d7a37512db3" }, "Description": "Call the AWS Lambda API", "Tags": [ { "Value": "SAM", "Key": "lambda:createdBy" } ],

この例では、Code プロパティは Amazon S3 バケット内のオブジェクトを指定します。これは、プロジェクトテンプレートの CodeUri プロパティのローカルパスに対応します。

CodeUri: function/.

プロジェクトファイルを Amazon S3 にアップロードするため、デプロイメントスクリプトは AWS CLI にあるコマンドを使用します。cloudformation package コマンドは、テンプレートを前処理して、アーティファクトをアップロードし、ローカルパスを Amazon S3 オブジェクトの場所に置き換えます。cloudformation deploy コマンドは、AWS CloudFormation 変更セット持つ処理済みテンプレートをデプロイします。

blank-nodejs/3-deploy.sh – パッケージングとデプロイ

#!/bin/bash set -eo pipefail ARTIFACT_BUCKET=$(cat bucket-name.txt) aws cloudformation package --template-file template.yml --s3-bucket $ARTIFACT_BUCKET --output-template-file out.yml aws cloudformation deploy --template-file out.yml --stack-name blank-nodejs --capabilities CAPABILITY_NAMED_IAM

このスクリプトを初めて実行すると、AWS CloudFormation という名前の blank-nodejs スタックが作成されます。関数コードまたはテンプレートを変更した場合は、関数コードまたはテンプレートを再度実行してスタックを更新できます。

クリーンアップスクリプト (blank-nodejs/5-cleanup.sh) はスタックを削除し、必要に応じてデプロイバケットと関数ログを削除します。

AWS X-Ray での計測

サンプル関数は、AWS X-Ray でトレースするように構成されています。トレースモードをアクティブに設定すると、Lambda は呼び出しのサブセットのタイミング情報を記録し、これを X-Ray に送信します。X-Ray は、このデータを処理してサービスマップを生成し、クライアントノードと 2 つのサービスノードを示します。

最初のサービスノード (AWS::Lambda) は、呼び出しリクエストを検証して関数に送信する Lambda サービスを表します。2 番目のノード AWS::Lambda::Function は、関数自体を表します。

追加の詳細を記録するために、サンプル関数は X-Ray SDK を使用します。関数コードを最小限変更するだけで、X-Ray SDK は AWS SDK を使用した AWS のサービスへの呼び出しに関する詳細を記録します。

blank-nodejs/function/index.js – インストルメンテーション

const AWSXRay = require('aws-xray-sdk-core') const AWS = AWSXRay.captureAWS(require('aws-sdk')) // Create client outside of handler to reuse const lambda = new AWS.Lambda()

AWS SDK クライアントを計測すると、サービスマップにノードが追加され、トレースにさらに詳細が追加されます。この例では、サービスマップに Lambda API を呼び出すサンプル関数が表示され、現在のリージョンでのストレージと同時実行の使用状況に関する詳細を取得しています。

トレースは、関数の初期化、呼び出し、オーバーヘッドのサブセグメントとともに、呼び出しのタイミングの詳細を表示します。呼び出しサブセグメントには、AWS API オペレーションに対する GetAccountSettings SDK 呼び出しのサブセグメントが含まれています。

X-Ray SDK やその他のライブラリを関数のデプロイパッケージに含めることも、Lambda レイヤーに個別にデプロイすることもできます。Node.js、Ruby、Python の場合、Lambda ランタイムは実行環境に AWS SDK を含めます。

レイヤーを使用した依存関係管理

ライブラリは、ローカルにインストールして、Lambda にアップロードするデプロイパッケージに含めることができますが、これにはデメリットがあります。ファイルサイズが大きくなるほどデプロイ時間が長くなり、Lambda コンソールで関数コードの変更をテストできなくなる可能性があります。デプロイパッケージを小さく保ち、変更されていない依存関係のアップロードを避けるために、サンプルアプリは Lambda レイヤーを作成し、関数に関連付けます。

blank-nodejs/template.yml – 依存関係レイヤー

Resources: function: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: nodejs12.x CodeUri: function/. Description: Call the AWS Lambda API Timeout: 10 # Function's execution role Policies: - AWSLambdaBasicExecutionRole - AWSLambda_ReadOnlyAccess - AWSXrayWriteOnlyAccess Tracing: Active Layers: - !Ref libs libs: Type: AWS::Serverless::LayerVersion Properties: LayerName: blank-nodejs-lib Description: Dependencies for the blank sample app. ContentUri: lib/. CompatibleRuntimes: - nodejs12.x

2-build-layer.sh スクリプトは、npm を使用して関数の依存関係をインストールし、Lambda ランタイムに必要な構造を持つフォルダに配置します。

2-build-layer.sh - レイヤーの準備

#!/bin/bash set -eo pipefail mkdir -p lib/nodejs rm -rf node_modules lib/nodejs/node_modules npm install --production mv node_modules lib/nodejs/

サンプルアプリケーションを初めてデプロイすると、AWS CLI によってレイヤーが関数コードとは別にパッケージ化され、両方がデプロイされます。以降のデプロイでは、lib フォルダーの内容が変更された場合にのみレイヤーアーカイブがアップロードされます。