Lambda コンソールでの継続的デリバリーによるアプリケーションの作成 - AWS Lambda

Lambda コンソールでの継続的デリバリーによるアプリケーションの作成

Lambda コンソールで、統合された継続的デリバリーパイプラインを使用してアプリケーションを作成できます。継続的デリバリーでは、ソース管理リポジトリにプッシュした変更ごとに、アプリケーションを自動的にビルドおよびデプロイするパイプラインがトリガーされます。Lambda コンソールには、Node.js サンプルコード付きの一般的なアプリケーションタイプのスタータープロジェクトと、サポートリソースを作成するためのテンプレートが用意されています。

このチュートリアルでは、次のリソースを作成します。

  • アプリケーション – Node.js Lambda 関数、ビルド仕様、および AWS サーバーレスアプリケーションモデル (AWS SAM) テンプレート。

  • パイプライン – 他のリソースを接続して継続的デリバリーを有効にする AWS CodePipeline パイプライン。

  • リポジトリ – AWS CodeCommit の Git リポジトリ。変更をプッシュすると、パイプラインはソースコードを Amazon S3 バケットにコピーしてから、それをビルドプロジェクトに渡します。

  • トリガー – リポジトリのマスターブランチを監視し、パイプラインをトリガーする Amazon CloudWatch Events ルール。

  • ビルドプロジェクト – パイプラインからソースコードを取得してアプリケーションをパッケージ化する、AWS CodeBuild のビルド。ソースにはビルド仕様が含まれています。この仕様には、依存関係をインストールしてデプロイ用のアプリケーションテンプレートを準備するコマンドが含まれています。

  • デプロイ設定 – パイプラインのデプロイステージは、ビルド出力から処理済みの AWS SAM テンプレートを取得し、AWS CloudFormation で新しいバージョンをデプロイする一連のアクションを定義します。

  • バケット – デプロイアーティファクトストレージ用の Amazon Simple Storage Service (Amazon S3) バケット。

  • ロール – パイプラインのソース、ビルド、デプロイの各ステージには、AWS リソースを管理するための IAM ロールがあります。アプリケーションの関数には、ログをアップロードするための実行ロールがあります。このロールは、他のサービスにアクセスするように拡張できます。

アプリケーションおよびパイプラインリソースは、カスタマイズして拡張できる AWS CloudFormation テンプレートに定義されています。アプリケーションリポジトリに含まれているテンプレートは、カスタマイズして Amazon DynamoDB テーブル、Amazon API Gateway API、その他のアプリケーションリソースを追加できます。継続的デリバリーパイプラインは、ソース管理外の別のテンプレートに定義されており、独自のスタックがあります。

パイプラインは、リポジトリ内の 1 つのブランチを 1 つのアプリケーションスタックにマッピングします。さらにパイプラインを作成して、他のブランチの環境を同じリポジトリ内に追加することができます。また、試験遂行、ステージング、手動承認用にステージをパイプラインに追加することもできます。AWS CodePipeline の詳細については、「AWS CodePipeline とは」を参照してください。

前提条件

このチュートリアルでは、基本的な Lambda オペレーションと Lambda コンソールについてある程度の知識があることを前提としています。まだ作成していない場合は、AWS Lambda の開始方法 の指示に従って、まず Lambda 関数を作成します。

このガイドの手順に従うには、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要になります。コマンドは、該当する場合、プロンプト記号 ($) と現在のディレクトリの名前が前に付けられて、リストに示されます。

~/lambda-project$ this is a command this is output

コマンドが長い場合は、エスケープ文字 (\) を使用して、コマンドを複数の行に分割します。

Linux および macOS では、任意のシェルとパッケージマネージャーを使用します。Windows 10 では、Linux 用の Windows サブシステムをインストールして、Windows 統合バージョンの Ubuntu および Bash を入手できます。

このチュートリアルでは、ソース管理に CodeCommit を使用します。アプリケーションコードにアクセスして更新するようにローカルマシンを設定するには、AWS CodeCommit ユーザーガイドの「設定」を参照してください。

アプリケーションの作成

Lambda コンソールでアプリケーションを作成します。Lambda でのアプリケーションとは、Lambda 関数と任意の数のサポートリソースを持つ AWS CloudFormation スタックです。このチュートリアルでは、関数とその実行ロールを持つアプリケーションを作成します。

アプリケーションを作成するには

  1. Lambda コンソールアプリケーションページを開きます。

  2. [Create application] を選択します。

  3. [Author from scratch] を選択します。

  4. アプリケーション設定を構成します。

    • アプリケーション名my-app

    • アプリケーションの説明my application

    • ランタイムNode.js 10.x

    • ソース管理サービスCodeCommit.

    • リポジトリ名my-app-repo

    • アクセス許可ロールとアクセス許可の境界を作成します

  5. [Create] を選択します。

Lambda は、パイプラインおよび関連リソースを作成し、サンプルアプリケーションコードを Git リポジトリにコミットします。リソースが作成されると、概要ページに表示されます。


        デプロイ時のスターターアプリケーションリソース。

[Infrastructure (インフラストラクチャ)] スタックには、リポジトリおよびビルドプロジェクトのほか、その他のリソースが含まれます。これらを結合すると、継続的デリバリーパイプラインが形成されます。このスタックのデプロイが完了すると、関数ロールと実行ロールを含むアプリケーションスタックがデプロイされます。これらは、[Infrastructure (リソース)] の下に表示されるアプリケーションリソースです。

関数を呼び出します

デプロイメントプロセスが完了したら、Lambda コンソールから関数を呼び出します。

アプリケーションの関数を呼び出すには

  1. Lambda コンソールアプリケーションページを開きます。

  2. [my-app] を選択します。

  3. [リソース] で、[helloFromLambdaFunction] を選択します。

  4. [Test] を選択します。

  5. テストイベントを設定します。

    • イベント名event

    • 本文{}

  6. [作成] を選択します。

  7. [Test] を選択します。

Lambda コンソールによって関数が実行され、その結果が表示されます。結果の下の [詳細] セクションを展開して、出力と実行の詳細を表示します。


        テスト呼び出しからの出力。

AWS リソースの追加

前のステップでは、Lambda コンソールを使用し、関数コード、テンプレート、およびビルド仕様を含む Git リポジトリを作成しました。テンプレートを変更し、変更をリポジトリにプッシュすることで、アプリケーションにリソースを追加できます。ローカルマシンでアプリケーションコードのコピーを取得するには、リポジトリのクローンを作成します。

プロジェクトリポジトリをクローンするには

  1. Lambda コンソールアプリケーションページを開きます。

  2. [my-app] を選択します。

  3. [コード] を選択します。

  4. [リポジトリの詳細] で、「セットアップ」で設定した認証モードに応じて、HTTP または SSH リポジトリ URI をコピーします。

  5. リポジトリのクローンを作成するには、git clone コマンドを使用します。

    ~$ git clone ssh://git-codecommit.us-east-2.amazonaws.com/v1/repos/my-app-repo

アプリケーションに DynamoDB テーブルを追加するには、テンプレートに AWS::Serverless::SimpleTable リソースを定義します。

DynamoDB テーブルを追加するには

  1. テキストエディタで template.yml を開きます。

  2. テーブルリソース、テーブル名を関数に渡す環境変数、およびテーブルリソースの管理を関数に許可するアクセス許可ポリシーを追加します。

    例 template.yml - リソース

    ... Resources: ddbTable: Type: AWS::Serverless::SimpleTable Properties: PrimaryKey: Name: id Type: String ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 helloFromLambdaFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./ Handler: src/handlers/hello-from-lambda.helloFromLambdaHandler Runtime: nodejs10.x MemorySize: 128 Timeout: 60 Description: A Lambda function that returns a static string. Environment: Variables: DDB_TABLE: !Ref ddbTable Policies: - DynamoDBCrudPolicy: TableName: !Ref ddbTable - AWSLambdaBasicExecutionRole
  3. 変更をコミットしてプッシュします。

    ~/my-app-repo$ git commit -am "Add DynamoDB table" ~/my-app-repo$ git push

変更をプッシュすると、アプリケーションのパイプラインがトリガーされます。アプリケーション画面の [Deployments (デプロイ)] タブを使用して、パイプラインを通過する変更を追跡します。デプロイが完了したら、次のステップに進みます。


        Lambda コンソールでアプリケーションのデプロイを監視しています。

アクセス許可の境界の更新

サンプルアプリケーションは、その関数の実行ロールにアクセス許可の境界を適用します。アクセス許可の境界は、関数のロールに追加できるアクセス許可を制限します。境界がないと、プロジェクトリポジトリへの書き込みアクセス権を持つユーザーは、プロジェクトテンプレートを変更して、サンプルアプリケーションの範囲外のリソースやサービスにアクセスするためのアクセス許可を関数に付与できます。

前のステップで実行ロールに追加した DynamoDB アクセス許可を関数で使用するには、アクセス許可の境界を拡張して追加のアクセス許可を付与する必要があります。Lambda コンソールは、アクセス許可の境界から外れたリソースを検出すると、更新されたポリシーを提供して境界を更新できるようにします。

アプリケーションのアクセス許可の境界を更新するには

  1. Lambda コンソールアプリケーションページを開きます。

  2. アプリケーションを選択します。

  3. [リソース] で、[Edit permisssions boundary (アクセス許可の境界の編集)] を選択します。

  4. 表示される手順に従って境界を更新し、新しいテーブルへのアクセスを許可します。

アクセス許可の境界の詳細については、「AWS Lambda アプリケーションに対するアクセス許可の境界の使用」を参照してください。

関数コードの更新

次に、テーブルを使用するように関数コードを更新します。次のコードでは、DynamoDB テーブルを使用して、関数の各インスタンスで処理された呼び出しの数を追跡します。関数インスタンスの一意の識別子として、ログストリーム ID が使用されます。

関数コードを更新するには

  1. index.js という名前の新しいハンドラーを、次の内容で src/handlers フォルダに追加します。

    例 src/handlers/index.js

    const dynamodb = require('aws-sdk/clients/dynamodb'); const docClient = new dynamodb.DocumentClient(); exports.handler = async (event, context) => { const message = 'Hello from Lambda!'; const tableName = process.env.DDB_TABLE; const logStreamName = context.logStreamName; var params = { TableName : tableName, Key: { id : logStreamName }, UpdateExpression: 'set invocations = if_not_exists(invocations, :start) + :inc', ExpressionAttributeValues: { ':start': 0, ':inc': 1 }, ReturnValues: 'ALL_NEW' }; await docClient.update(params).promise(); const response = { body: JSON.stringify(message) }; console.log(`body: ${response.body}`); return response; }
  2. アプリケーションのテンプレートを開き、ハンドラー値を src/handlers/index.handler に変更します。

    例 template.yml

    ... helloFromLambdaFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./ Handler: src/handlers/index.handler Runtime: nodejs10.x
  3. 変更をコミットしてプッシュします。

    ~/my-app-repo$ git add . && git commit -m "Use DynamoDB table" ~/my-app-repo$ git push

コードの変更がデプロイされたら、関数を数回呼び出して DynamoDB テーブルを更新します。

DynamoDB テーブルを表示するには

  1. DynamoDB コンソールのテーブルページを開きます。

  2. my-appで始まるテーブルを選択します。

  3. [Items (項目)] を選択します。

  4. [Start search (検索の開始)] を選択します。


        関数のインスタンスがイベントを処理した回数を示す DynamoDB テーブル。

Lambda では、複数の同時呼び出しを処理するために、関数の追加インスタンスが作成されます。CloudWatch Logs ロググループ内の各ログストリームは、関数インスタンスに対応します。関数のコードまたは設定を変更すると、新しい関数インスタンスも作成されます。スケーリングの詳細については、「AWS Lambda 関数スケーリング」を参照してください。

次のステップ

アプリケーションリソースを定義する AWS CloudFormation テンプレートでは、AWS サーバーレスアプリケーションモデル トランスフォームを使用して、リソース定義の構文を簡素化し、デプロイパッケージやその他のアーティファクトのアップロードを自動化します。AWS SAM は、コマンドラインインターフェイス (AWS SAM CLI) も提供しています。CLI には、AWS CLI と同じパッケージングおよびデプロイ機能があり、さらに Lambda アプリケーションに固有の機能が追加されています。AWS SAM CLIを使用して、Lambda 実行環境をエミュレートする Dockerコンテナでローカルにアプリケーションをテストします。

AWS Cloud9 は、Node.js、AWS SAM CLI、および Docker を含むオンライン開発環境を提供します。AWS Cloud9 を使用すると、開発をすばやく開始し、どのコンピュータからでも開発環境にアクセスできます。手順については、AWS Cloud9 ユーザーガイドの「開始方法」を参照してください。

ローカル開発の場合、統合開発環境 (IDE) 用の AWS ツールキットを使用すると、関数をリポジトリにプッシュする前にテストおよびデバッグできます。

トラブルシューティング

アプリケーションを開発する際、以下のタイプのエラーが発生する可能性があります。

  • ビルドエラー – コンパイル、テスト、パッケージングのエラーなど、ビルドフェーズ中に発生する問題。

  • デプロイエラー – AWS CloudFormation がアプリケーションスタックを更新できない場合に発生する問題。これには、アクセス許可のエラー、アカウントのクォータ、サービスの問題、またはテンプレートのエラーが含まれます。

  • 呼び出しエラー – 関数のコードまたはランタイムから返されるエラー。

ビルドエラーおよびデプロイエラーの場合は、Lambda コンソールでエラーの原因を特定できます。

アプリケーションエラーのトラブルシューティングを行うには

  1. Lambda コンソールアプリケーションページを開きます。

  2. アプリケーションを選択します。

  3. [デプロイ] を選択します。

  4. アプリケーションのパイプラインを表示するには、[Deployment pipeline (デプロイパイプライン)] を選択します。

  5. エラーが発生したアクションを特定します。

  6. コンテキストでエラーを表示するには、[詳細] を選択します。

ExecuteChangeSet アクション中に発生したデプロイエラーの場合、パイプラインは AWS CloudFormation コンソールのスタックイベントのリストにリンクされます。ステータスが UPDATE_FAILED のイベントを検索します。エラーの発生後に AWS CloudFormation はロールバックするため、関連するイベントは、リスト内の他のいくつかのイベントの下にあります。AWS CloudFormation が変更セットを作成できなかった場合、エラーは [イベント] の下ではなく [変更セット] の下に表示されます。

デプロイエラーや呼び出しエラーの一般的な原因は、1 つ以上のロールにアクセス許可が不足していることです。パイプラインには、AWS CloudFormation スタックを直接更新するために使用する ユーザーアクセス許可と同等のデプロイ用のロール (CloudFormationRole) があります。アプリケーションにリソースを追加する場合や、ユーザーアクセス許可を必要とする Lambda 機能を有効にする場合に、デプロイロールが使用されます。デプロイロールへのリンクは、アプリケーションの概要の [Infrastructure (インフラストラクチャ)] の下にあります。

関数が AWS の他のサービスやリソースにアクセスする場合、または追加のアクセス許可が関数に必要となる機能を有効にすると、関数の実行ロールが使用されます。アプリケーションテンプレートで作成されるすべての実行ロールには、アプリケーションのアクセス許可の境界も適用されます。この境界により、テンプレートの実行ロールにアクセス許可を追加した後で、追加のサービスやリソースへのアクセス権を IAM で明示的に付与する必要があります。

たとえば、関数を Virtual Private Cloud (VPC) に接続するには、VPC リソースを記述するためのユーザーアクセス許可が必要です。実行ロールには、ネットワークインターフェイスを管理するためのアクセス許可が必要です。この場合、以下のステップに従います。

  1. IAM でデプロイロールに必要なユーザーアクセス許可を追加します。

  2. IAM でアクセス許可の境界に実行ロールアクセス許可を追加します。

  3. アプリケーションテンプレートで実行ロールに実行ロールアクセス許可を追加します。

  4. コミットしてプッシュし、更新された実行ロールをデプロイします。

アクセス許可のエラーに対処したら、パイプラインの概要で [変更のリリース] を選択して、ビルドとデプロイを再実行します。

クリーンアップ

サンプルを引き続き変更して使用し、独自のアプリケーションを開発できます。サンプルを使い終わったら、アプリケーションを削除して、パイプライン、リポジトリ、およびストレージに課金されないようにします。

アプリケーションを削除するには

  1. AWS CloudFormation コンソールを開きます。

  2. アプリケーションスタック – my-app を削除します。

  3. Amazon S3 コンソールを開きます。

  4. アーティファクトバケット – us-east-2-123456789012-my-app-pipe を削除します。

  5. AWS CloudFormation コンソールに戻り、インフラストラクチャスタック – serverlessrepo-my-app-toolchain を削除します。

関数ログは、AWS CloudFormation のアプリケーションまたはインフラストラクチャスタックに関連付けられていません。ロググループは CloudWatch Logs コンソールで個別に削除します。

ロググループを削除するには

  1. Amazon CloudWatch コンソールのロググループページを開きます。

  2. 関数のロググループ (/aws/lambda/my-app-helloFromLambdaFunction-YV1VXMPLK7QK) を選択します。

  3. [Actions] (アクション) を選択してから、[Delete log group] (ロググループの削除) を選択します。

  4. [Yes, Delete] を選択します。