LoginSignup
0
0

Serverless Frameworkを使ったAWS Lambdaの開発チュートリアル

Last updated at Posted at 2024-02-17

概要

最近、LINE Botを開発しました。
そのプロジェクトで、サーバレスアーキテクチャの構築と管理を容易にするServerless Frameworkを使用しました。
Serverless Frameworkを利用することで、AWSへのデプロイや管理が簡単になり、開発プロセスがスムーズになりました。
この記事では、その設定やプロセスについて詳しく説明していきます。

実行環境

前提条件として、Node.jsおよびAWS CLIインストールが必要です。
私の実行環境は以下の通りです。

$ node -v
v20.0.0
$ aws --version
aws-cli/2.15.12 Python/3.11.7 Darwin/23.2.0 source/x86_64 prompt/off

Serverless Framework のインストール

まずServerless Frameworkをインストールします。

$ npm install -g serverless
$ serverless --version
Framework Core: 3.38.0
Plugin: 7.2.0
SDK: 4.5.1

ちなみに、serverlessのエイリアスとしてslsが登録されているので、以下コマンドでも実行できます。

$ sls --version
Framework Core: 3.38.0
Plugin: 7.2.0
SDK: 4.5.1

Serverless Frameworkが使うIAMユーザーの作成

次にAWSアカウントのセットアップを行います。
AWSコンソールにログインし、IAMのユーザーの作成をクリックし、任意のユーザー名を入力します。
click-create-iam-user.png

ポリシーを直接アタッチするを選択し、AdministratorAccessを選択し、ユーザーを作成します。
create-iam-user.png
IAMロールの権限を制限したい場合は以下サイトを参考に独自でセットアップして下さい。

ユーザーが作成できたら、アクセスキーを作成からアクセスキーシークレットアクセスキーを作成します。
create-aws-access-key.png

AWS CLI の設定

次にAWS CLIを設定します。
先ほど作成したアクセスキーシークレットアクセスキーをAWSの認証情報としてAWS CLIに設定します。

$ serverless config credentials --provider aws --key "Your Access Key ID" --secret "Your AWS Secret Access Key"
✔ Profile "default" has been configured

上記コマンドは、~/.aws/credentialsファイルに認証情報を書き込む操作を内部で行います。
そのため、aws configureコマンドを使っても同じ設定が可能です。

$ aws configure
  AWS Access Key ID [None]: Your Access Key ID
  AWS Secret Access Key [None]: Your AWS Secret Access Key
  Default region name [None]:
  Default output format [None]:

もしdefaultプロファイルが既に設定されている場合、次のようなエラーメッセージが表示されます。

Error:
Profile "default" is already configured in ~/.aws/credentials. Use the overwrite flag ("-o" or "--overwrite") to force the update.

その場合--profileオプションでプロファイル名を指定して新しいプロファイルを作成するか、--overwriteオプションで既存のプロファイルを上書く必要があります。

$ serverless config credentials --provider aws --key "Your Access Key ID" --secret "Your AWS Secret Access Key" --profile sample
$ serverless config credentials --provider aws --key "Your Access Key ID" --secret "Your AWS Secret Access Key" --overwrite

設定が完了したら、~/.aws/credentialsファイルに保存された認証情報を確認できます。

$ cat ~/.aws/credentials 
[default]
aws_access_key_id=Your Access Key ID
aws_secret_access_key=Your AWS Secret Access Key

[sample]
aws_access_key_id=Your Access Key ID
aws_secret_access_key=Your AWS Secret Access Key

プロジェクトの作成

次に、プロジェクトを作成します。
serverlessコマンドを実行するとプロジェクトのテンプレートを選択するように求められるので、今回はAWS - Node.js - Express APIを選択します。

$ serverless

Creating a new serverless project

? What do you want to make? (Use arrow keys)
  AWS - Node.js - Starter 
  AWS - Node.js - HTTP API 
  AWS - Node.js - Scheduled Task 
  AWS - Node.js - SQS Worker
❯ AWS - Node.js - Express API
  AWS - Node.js - Express API with DynamoDB 
  AWS - Python - Starter 
  AWS - Python - HTTP API 
  AWS - Python - Scheduled Task 
  AWS - Python - SQS Worker 
  AWS - Python - Flask API 
  AWS - Python - Flask API with DynamoDB 
  Other 

プロジェクト名には任意の値を入力します。
今回はserverless-sampleとします。
Serverless Frameworkへの登録やログイン、そして即時デプロイを行うかどうかの質問が表示されます。
これらに答えることでプロジェクトが作成されます。

$ serverless

Creating a new serverless project

? What do you want to make? AWS - Node.js - Express API
? What do you want to call this project? serverless-sample

✔ Project successfully created in serverless-sample folder

? Register or Login to Serverless Framework No

? Do you want to deploy now? No

What next?
Run these commands in the project directory:

serverless deploy    Deploy changes
serverless info      View deployed endpoints and resources
serverless invoke    Invoke deployed functions
serverless --help    Discover more commands

プロジェクト構造

プロジェクトが作成されると基本的なフォルダ構造が自動的に生成されます。
directory.png

ファイル 説明
serverless.yml Serverless Frameworkの設定ファイルです。
サービス名や使用するクラウドプロバイダー、Lambda関数の設定などを記述します。
index.js Lambda関数の具体的なロジックを実装するファイルです。

serverless.yml の初期設定

serverless.ymlの初期設定は以下の通りです。

serverless.yml
service: serverless-sample
frameworkVersion: '3'

provider: 
  name: aws
  runtime: nodejs18.x

functions:
  api:
    handler: index.handler
    events:
      - httpApi: '*'
セクション 説明
service Serverless プロジェクトの名前を指定します。
この例ではserverless-sampleとしています。
frameworkVersion 使用するServerless Frameworkのバージョンを指定します。
'3' はバージョン 3 を示します。
provider 使用するクラウドプロバイダーを指定します。
この例では、プロバイダーaws と、Node.jsのランタイムバージョンnodejs18.xを設定しています。
functions Lambda関数とその設定を指定します。
このセクションで関数のハンドラー、イベントトリガーなどを設定しています。

今回の設定では、functionsセクションでapiという名前のLambda関数を設定しています。
handlerはその関数がどのファイルに記述されているかを指定します。
今回の設定ではindex.jshandler関数にそのロジックが実装されています。
eventsはどのイベントがこの関数をトリガーするかを定義しています。
今回の設定ではhttpApiを使用しAPI Gateway経由で受け取る全てのHTTPリクエストをこの関数にルーティングするように設定されています。

index.jsの初期設定

index.jsの初期設定は以下の通りです。

index.js
const serverless = require("serverless-http");
const express = require("express");
const app = express();

app.get("/", (req, res, next) => {
  return res.status(200).json({
    message: "Hello from root!",
  });
});

app.get("/path", (req, res, next) => {
  return res.status(200).json({
    message: "Hello from path!",
  });
});

app.use((req, res, next) => {
  return res.status(404).json({
    error: "Not Found",
  });
});

module.exports.handler = serverless(app);

上記のindex.jsはExpressフレームワークを使ったNode.jsのコードです。
このコードは、ルートパス("/")と"/path"へのGETリクエストに応じて、異なるJSONメッセージを返します。
また、未定義のパスへのリクエストに対しては404エラーとエラーメッセージが返されます。
serverless(app)により、Expressで作成されたWebアプリケーションappをServerless Frameworkを通じてAWS Lambda関数としてデプロイすることが可能です。

ローカルのテスト

Serverless Frameworkをローカルでテストする方法は2通りあります。

serverless offline

1つ目はserverless offlineを使用する方法です。
この方法では、ローカル環境でAPI GatewayやLambda関数の動作をエミュレートし、実際のAWS環境を模倣してテストを行うことができます。
開発中のAPIの挙動を確認したり、フロントエンドの開発と連携させて動作テストを行うのに便利です。
serverless offlineプラグインをプロジェクトに追加し、設定を行うことで、簡単にローカル環境でのAPIテスト環境を構築できます。

以下コマンドでserverless-offlineを導入します。

$ npm install serverless-offline --save-dev

その後serverless.ymlpluginsに以下を追記します。

serverless.yml
plugins:
  - serverless-offline

serverless offlineコマンドを実行すると、ローカルエンドポイントが出力されます。
このエンドポイントに対してcurlコマンドなどを用いることで、関数の動作をテストできます。

$ serverless offline
(中略)
   ┌───────────────────────────────────────────────────────────────────────┐
   │                                                                       │
   │   ANY | http://localhost:3000/{default*}                              │
   │   POST | http://localhost:3000/2015-03-31/functions/api/invocations   │
   │                                                                       │
   └───────────────────────────────────────────────────────────────────────┘

Server ready: http://localhost:3000 🚀

serverless invoke local

2つ目はserverless invoke localコマンドを使用する方法です。
このコマンドを使うと、特定のLambda関数をローカル環境で直接実行することができます。
デプロイする前に個々の関数の挙動をテストしたい場合に便利です。

$ serverless invoke local --function api
{
    "statusCode": 200,
    "headers": {
        "x-powered-by": "Express",
        "content-type": "application/json; charset=utf-8",
        "content-length": "30",
        "etag": "W/\"1e-n7v8BWYZG0cayfAnplsH5ynO6ec\""
    },
    "isBase64Encoded": false,
    "body": "{\"message\":\"Hello from root!\"}"
}

AWS へのデプロイ

serverless deployコマンドを使用してアプリケーションを AWS にデプロイする事が出来ます。

$ serverless deploy

Deploying serverless-sample to stage dev (us-east-1)

✔ Service deployed to stack serverless-sample-dev (117s)

endpoint: ANY - https://XXXXXXXXX.execute-api.us-east-1.amazonaws.com
functions:
  api: serverless-sample-dev-api (894 kB)

デプロイ後、エンドポイントURLにアクセスすることで、API Gateway経由でLambda関数を呼び出す事ができます。

デプロイしたサービスの削除

デプロイしたサービスは、serverless removeコマンドを使ってAWSから削除できます。

$ serverless remove
Removing serverless-sample from stage dev (us-east-1)

✔ Service serverless-sample has been successfully removed (29s)

プロジェクトが完了したり、不要になったサービスは削除しておきましょう。

serverless.ymlのカスタマイズ

最近、LINE Botの実装に使用したserverless.ymlを紹介します。
定期実行、もしくはメッセージに対する応答時にLambda関数が実行されます。

serverless.yml
service: amazon-wishlist-to-line
frameworkVersion: "3"

useDotenv: true

provider:
  name: aws
  runtime: nodejs18.x
  region: ap-northeast-1
  environment:
    AMAZON_WISHLIST_URL: ${env:AMAZON_WISHLIST_URL}
    CHANNEL_ACCESS_TOKEN: ${env:CHANNEL_ACCESS_TOKEN}
    CHANNEL_SECRET: ${env:CHANNEL_SECRET}
    USER_ID: ${env:USER_ID}
  timeout: 600

functions:
  lineWebhookHandler:
    handler: src/index.handler
    events:
      - http:
          method: post
          path: "/webhook"
          cors: true
  scheduledHandler:
    handler: src/handlers/scheduledHandler.handleScheduledEvent
    events:
      - schedule:
          rate: cron(0 22 * * ? *)
          enabled: true

plugins:
  - serverless-offline

サービスの設定

サービス名をamazon-wishlist-to-lineと指定し、Serverless Frameworkのバージョン3を使用します。
useDotenvを使用する事で、.envファイルから環境変数を読み込むように設定します。

プロバイダーの設定

AWSをクラウドプロバイダーとして、Node.js 18.xをランタイムとして使用します。
必要な環境変数とLambda関数のタイムアウト時間も設定しています。

関数の定義

lineWebhookHandler

LINEのWebhookからのリクエストを処理する関数です。
src/index.handlerにそのロジックが実装されています。
/webhookのパスで待機していて、HTTP POSTリクエストを受け取ります。
CORSを有効にして、外部のドメインからのリクエストも受け入れるようにしています。

scheduledHandler

定期的に実行される関数です。
src/handlers/scheduledHandler.handleScheduledEventにそのロジックが実装されています。
この関数はAWS EventBridgeを利用しており、cron(0 22 * * ? *)により、UTC時間で毎日22時(日本時間の朝7時)に実行されるようスケジュールされています。

ローカル開発のサポート

serverless-offlineプラグインを使用してローカルでの開発を容易にします。
このプラグインを導入することでAPIのローカルテストを可能にします。

AWS へのデプロイ

serverless deployコマンドを使用してアプリケーションを AWS にデプロイできます。
この実装では、API Gatewayを通じてLambda関数(lineWebhookHandlerのみ)が呼び出されます。
そのため、HTTP POSTリクエスト用のエンドポイントURLのみが出力されます。
scheduledHandlerはAWS EventBridgeを使用して定期的に実行されるため、エンドポイントURLは出力されません。

$ serverless deploy
 (中略)
 Deploying amazon-wishlist-to-line to stage dev (ap-northeast-1)
 ✔ Service deployed to stack kindle-wishlist-to-line-dev (49s)

 endpoint: POST - https://XXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/webhook
  functions:
   lineWebhookHandler:  amazon-wishlist-to-line-dev-lineWebhookHandler (71 MB)
   scheduledHandler:  amazon-wishlist-to-line-dev-scheduledHandler (71 MB)

詳細なコードは、GitHubのリポジトリでも公開しています。
興味のある方は是非チェックしてみてください。

まとめ

この記事では、Serverless Frameworkを利用したAWSへのデプロイや管理について解説しました。
間違っている箇所や疑問に思ったことがあれば、ぜひコメントをください!

最後まで読んでいただき、ありがとうございました。

上記Serverless Frameworkを基にしたLINE Botの開発について記事を書いているので、こちらも読んでいただけると嬉しいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0