見出し画像

それサーバレスでできません? 〜③Lambdaを使ったAPIのサーバレス化(Node.js)

本章のゴール

EC2上でホストされているAPI(Node.js)をLambdaとAPI Gatewayを使った構築に移行する。
使用するサービスは下記
①Lambda
②API Gateway
(以下CI/CDパイプラインに利用)
③Code Commit
④Code Build
⑤CloudFormation
⑥Code Pipeline

3章_説明0_パイプライン構成

移行によるメリット

そもそもの話ですが、S3でのサイト構築同様、サーバーレス構成にすることで金銭面と運用面でメリットが得られます。具体的な内容は下記になります。

金銭面
課金形態が使用時間からリソースの使用量に変更されます。リクエスト数が少ない場合はLambdaの方が、膨大なリクエストを処理する必要がある場合は、EC2の方がお得になります。ただ、Lambdaでは冗長性が標準で備わっているため、サービス利用料以外についても考慮が必要となります。
・課金形態
Lambdaでの運用:利用処理負荷あたりの従量課金
EC2:利用時間あたりの従量課金

一定程度のアクセスであればLambdaの方がサービス利用料が低いですが、大量のトラフィックを扱う場合はEC2の方がサービス利用料が低くなります。尚、どちらの構成とするかについては、運用にかかる人件費を含めて検討する必要があります(運用面でのポイントは後続の内容を参照)。

3章_説明5_料金説明1

3章_説明6_料金説明2

運用面
Lambdaは非機能要件の観点で以下が保証されています。
インフラの管理が不要(OSの更新、使用量に合わせたスケールイン・スケールアウト など)
AZ全体での耐障害性を保証
自動スケーリング
他AWSサービスとの連携が容易
リクエスト数などの都合により、サービス利用料自体がEC2の方が安い場合でも、運用の際に必要な人的リソースを加味することで、総合的な費用が安くなることがあります。

構築手順

1.  CICDパイプライン、Lambda関数の作成
Node.jsのAPIについては、パイプラインのテンプレートを使用することができます。このテンプレートを使用して叩き台となるパイプラインを作成します。

1-1. アプリケーションの作成
AWSマネジメントコンソールから、Lambdaへ移動し、アプリケーションの新規作成を行います。

3章_説明1_アプリケーション作成

「一から作成」を選択します。

3章_説明2_1から作成

各設定を行い、パイプラインを作成します(設定は以下参照)。
 ・アプリ名:(任意の名称)
 ・ランタイム:Node.js 10.x
 ・ソース管理サービス:Code Commit

1-2. 1-1で「作成」押下後、CICDパイプラインに関連するリソースが作成されたことを確認できます。 
※下図赤枠内のリソースが作成される。

3章_説明3_初期リソース

2. API Gatewayの追加
手順1でCICDパイプラインとLambda関数は作成されたので、API Gatewayを追加します。

2-1. ローカル環境へのリポジトリのクローン
手順1で作成されたリソースの各設定を変更するため、ローカル環境へリポジトリ(Code Commit)をクローンします。

Code Commitのリポジトリ一覧上、作成したアプリと同名のリポジトリのURLをコピーします。

3章_説明4_リポジトリのクローン

ローカル環境(≒お使いのデスクトップ)で、作業を行うフォルダを作成し、作成したフォルダにリポジトリをクローンします。

#"https://~" は上図でコピーしたURLを記載
$ git clone https://~

#クローンされたフォルダ(リポジトリ内のコード一式)へ移動
#"sample-lambda-nodejs"はリポジトリ名
cd sample-lambda-nodejs

以下内容のディレクトリ構造がダウンロードされたことを確認できます。

- __tests__ -> ビルドの際に実行されるテストコード
- src -> APIとして実行されのソースコード
.DS_Store
.gitignore
buildspec.yml -> ビルド設定
LICENSE
package.json
README.md
template.yml -> デプロイ設定(CloudFormataionのテンプレート)

2-2. デプロイ設定(template.yml)の変更
手順1で作成したLambda関数を外部から実行できるよう、API Gatewayを追加します。
※template.ymlにAPI Gatewayの設定(下記コードの "Events"以下)を追記する

AWSTemplateFormatVersion: 2010-09-09
Description: >-
 

Transform: AWS::Serverless-2016-10-31

Globals:
 Function:
   PermissionsBoundary: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${AppId}-${AWS::Region}-PermissionsBoundary'

Parameters:
 AppId:
   Type: String

Resources:
 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.
     Policies:
       - AWSLambdaBasicExecutionRole
     #Events配下にAPI Gatewayの設定として以下内容を追加する
     Events:
       HelloWorld:
         Type: Api
         Properties:
           Path: /get
           Method: get

2-3. ビルド設定(buildspec.yml)の変更
手順1で作成されてビルド設定には、初期設定向けのテストコードがあるため、コメントアウトします。
※テストコードが必要な場合は適宜アレンジください。

version: 0.2
phases:
 install:
   commands:
     # Install all dependencies (including dependencies for running tests)
     - npm install
 
 #テスト用の設定を一度コメントアウトする
 #pre_build:
   #commands:
     # Discover and run unit tests in the '__tests__' directory
     #- npm run test
     # Remove all unit tests to reduce the size of the package that will be ultimately uploaded to Lambda
     #- rm -rf ./__tests__
     # Remove all dependencies not needed for the Lambda deployment package (the packages from devDependencies in package.json)
     #- npm prune --production
 build:
   commands:
     # Use AWS SAM to package the application by using AWS CloudFormation
     - aws cloudformation package --template template.yml --s3-bucket $S3_BUCKET --output-template template-export.yml
artifacts:
 type: zip
 files:
   - template-export.yml

2-4. APIコード(~/src/handlers/hello-from-lambda.js)の変更
API Gatewayと連携するために、特定のヘッダー情報が必要になります。
レスポンスとしてこのヘッダー情報が返されるよう、APIの処理として使用されるコードを編集します。

/**
* A Lambda function that returns a string.
*/
exports.helloFromLambdaHandler = async () => {
   // If you change this message, you will need to adjust tests in hello-from-lambda.test.js
   const message = 'Hello from Lambda!';

   // All log statements are written to CloudWatch by default. For more information, see
   // https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-logging.html
   console.log(message);

   //return message;
   //responseの内容として特定のヘッダーを返すよう変更
   var response = {
       "statusCode": 200,
       "headers": {
           "my_header": "my_value"
       },
       "body": message,
       "isBase64Encoded": false
   };
   return response;
};

2-5. 変更内容の反映
リポジトリへ、2-2~2-4で変更した内容を反映します。

$ git add .
$ git commit -m 'Initial Commit'
$ git push 

リポジトリの変更を検知してCode Piplineがビルドとデプロイを自動実行します。
デプロイ後API Gatewayで発行されたURLへWebブラウザでアクセスし、レスポンスが返されることを確認できれば設定は完了となります。

画像6


この記事が気に入ったらサポートをしてみませんか?