サーバーレスシステム構築のベストプラクティス! Serverless Frameworkをもっと試してみよう! API GatewayとDynamoDB編

記事タイトルとURLをコピーする

こんにちは。サーバーワークス こけし部 部長でCS課の坂本(@t_sakam)です。前回に続いて、Serverless Frameworkの話題です。
 前回は、Serverless Frameworkのドキュメントに沿って、簡単に使い方を確かめてみました。今回は、API GatewayやDynamoDBをからめた使い方をみてみたいと思います。
 

 Serverless Frameworkを使うと、設定ファイルのserverless.ymlに必要な設定を書いて「serverless deploy」とコマンドを打つだけで、必要なリソースの作成ができます。Lambdaファンクションのデプロイだけでなく、API GatewayとDynamoDBのリソース作成もServerless Frameworkでやってしまいましょう。

  1. Serverless Frameworkのアップデート
  2. サービスの作成
  3. 必要なファイルを自動生成
  4. サービスの内容
  5. serverless.ymlの編集
  6. handler.pyの編集
  7. デプロイ
  8. 作成されたリソースの確認
  9. 動作確認
  10. まとめ

1. Serverless Frameworkのアップデート

今回の作業環境

名前 バージョン
OS OS X
Python 2.7.10
aws-cli aws-cli/1.10.36
npm 2.15.5
boto3 1.3.0
httpie 0.9.6

 前回のバージョンは「v1.0.0-beta1.1」でしたが、「v1.0.0-beta2」がリリースされていたので、以下のコマンドでローカル環境のServerless Frameworkをアップデートします。とくにアップデート用のコマンドがないので、前回と同じインストールコマンドでアップデートしましょう。

sudo npm install -g serverless@beta

 
 バージョンの確認ができれば、アップデートは成功です。

serverless --version
1.0.0-beta.2

 
 ※前回のクレデンシャル情報の設定では触れていませんでしたが、公式のドキュメントには、作業するユーザーに「AdministratorAccess」権限を付与するように書かれています。Serverless Frameworkは開発途中で、まだ必要な権限が定まらないと書かれているので、今回はいったん指示通り「AdministratorAccess」権限を付与してから作業しましょう。
 

2. サービスの作成

  アップデートできたら、次はサービスを作成します。今回は「こけし」の「工人さん」をデータベースに登録するサービスを作りたいと思います。 サービスの作成といってもやることは、サービス用のディレクトリを作成後、そのディレクトリに入るだけです。
 ※「こけし」の場合は、作る人を「職人さん」ではなく「工人さん」と呼びます。

mkdir kokeshi-craftsmen
cd kokeshi-craftsmen

 

3. 必要なファイルを自動生成

 以下のコマンドで必要なファイルを自動生成します。

serverless create --template aws-python

 前回と同様に4つのファイルが自動生成されました。

  1. event.json
  2. handler.py
  3. serverless.env.yml
  4. serverless.yml

4. サービスの内容

 今回は、『API Gawayのエンドポイントにアクセスしたとき、こけし工人さんの「系統」と「名前」のデータをPUTでわたして、DynamoDBに登録する』、という流れのサービスを作りたいと思います。
 ※「こけし」の「系統」についてはWikipediaの「伝統こけしの系統」をご確認ください。
 

 

5. serverless.ymlの編集

 まずは、Serverless Frameworkのメインの設定ファイルであるserverless.ymlを編集します。

serverless.yml

service: kokeshi-craftsmen

provider:
  name: aws
  runtime: python2.7
  iamRoleStatements:
    - Effect: Allow
      Resource: "arn:aws:dynamodb:us-east-1:*:*"
      Action:
        - "dynamodb:PutItem"

functions:
  put:
    handler: handler.handler
    events:
      - http:
          path: put
          method: put

resources:
  Resources:
    kokeshicraftsmen:
      Type: "AWS::DynamoDB::Table"
      Properties:
        AttributeDefinitions:
          - AttributeName: type
            AttributeType: S
          - AttributeName: craftsman
            AttributeType: S
        KeySchema:
          - AttributeName: type
            KeyType: HASH
          - AttributeName: craftsman
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: kokeshi_craftsmen

serverless.ymlの説明

provider

 「provider」の「iamRoleStatements」を変更して、DynamoDBにItemが追加できるようにしたいと思います。デプロイしたときに作成されるIAMロールに、ここで指定した権限が追加されます。

provider:
  name: aws
  runtime: python2.7
  iamRoleStatements:
    - Effect: Allow
      Resource: "arn:aws:dynamodb:us-east-1:*:*"
      Action:
        - "dynamodb:PutItem"

 

functions

 「functions」でLambdaファンクションの設定とAPI Gatewayの設定をします。まず、「handler」でLambdaファンクションの設定です。「ファイル名.ファンクション名」と設定します。
 「events」でイベントハンドラーを設定します。API GatewayをLambdaファンクションのトリガーにしたい場合は、「-http」と設定します。S3をトリガーにしたい場合は、「- s3」といった形で設定します。「path」は、API Gatewayのエンドポイントのパス、「method」は今回は「PUT」を使うので、「put」と設定します。「GET」や「POST」を使うときはそれぞれ「get」、「post」と設定します。

functions:
  put:
    handler: handler.handler
    events:
      - http:
          path: put
          method: put

 

resources

 「resources」では、CloudFormationで作成するリソースを設定します。今回はDynamoDBのテーブル「kokeshi_craftsmen」を作成したいので、キーやカラム(アトリビュート)などの情報などをここで設定します。

resources:
  Resources:
    kokeshicraftsmen:
      Type: "AWS::DynamoDB::Table"
      Properties:
        AttributeDefinitions:
          - AttributeName: type
            AttributeType: S
          - AttributeName: craftsman
            AttributeType: S
        KeySchema:
          - AttributeName: type
            KeyType: HASH
          - AttributeName: craftsman
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: kokeshi_craftsmen

 

6. handler.pyの編集

 次にhandler.pyの編集です。
 

handler.py
from __future__ import print_function

import json
import boto3

def handler(event, context):
    try:
        if len(event['body']) == 0:
            return 'There is no data'

        body = event['body']

        kokeshi_type = ''
        kokeshi_craftsman = ''

        for key, value in body.iteritems():
            if key == 'type':
                kokeshi_type = value
            if key == 'craftsman':
                kokeshi_craftsman = value

        if kokeshi_type == '' or kokeshi_craftsman == '':
            return 'There is no Type or Craftsman'

        client = boto3.client('dynamodb')

        table_name = 'kokeshi_craftsmen'

        response = client.put_item(
            TableName = table_name,
            Item = {
                'type': {
                    'S': kokeshi_type,
                },
                'craftsman': {
                    'S':  kokeshi_craftsman
                },
            }
        )
        return response

    except Exception as e:
        return e
handler.pyの説明

 PUTでわたされたデータは「events」の「body」に入っています。PUTでデータがわたってきているかをチェックしたあと、工人さんが作っているこけしの系統のデータと工人さんの名前を、それぞれDynamoDBの「type」と「craftsman」カラム(アトリビュート)に入れる処理をおこなっています。
 

7. デプロイ

 これで設定ファイルとLambdaファンクションが完成したので、デプロイしてみましょう。

serverless deploy

 
 「Deployment successful!」とメッセージがでたら、成功です。API GatewayのエンドポイントやLambdaファンクションの「arn」が返ってきています。

8. 作成されたリソースの確認

 デプロイが成功したら、想定していたリソースが問題なく作成されているか、マネジメントコンソールで確認してみましょう。
 

CloudFormation

 まずは、CloudFormationを確認します。「kokeshi-craftsmen-dev」というスタックが作成されています。  

 
 CloudFormationで作成されたリソースを確認すると、LambdaファンクションやDynamoDBのテーブル、Lambdaファンクションのコードのアップロード先になるS3バケット、IAMやAPI Gatewayのリソースが作成されていることが確認できます。

 

IAMロール

 次は、IAMロールを確認します。「kokeshi-craftsmen-dev-IamRoleLambda-XXX...」という名前のロールが作成されています。  

 
 上記のロールには以下の「dev-kokeshi-craftsmen-lambda」というポリシーがひもづいています。Serverless Frameworkでデプロイしたときにデフォルトで作成されるCloudWatch Logsのポリシーと、先ほどserverless.ymlで設定したDynamoDBの「PutItem」を許可する設定がきちんとできていることがわかります。

Lambdaファンクション

 次は、Lambdaファンクションです。こちらもserverless.ymlで設定したLambdaファンクションのファイル名とファンクション名の設定である「handler.handler」が設定されています。ロールには先ほど確認した「kokeshi-craftsmen-dev-IamRoleLambda-XXX...」が設定されています。  

 

API Gateway

 API Gatewayも確認します。serverless.ymlで設定したエンドポイントのパス「/put」にPUTメソッドが設定されています。  

 

DynamoDB

 最後にDynamoDBを確認します。serverless.ymlで設定した「type」と「craftsman」カラム(アトリビュート)をもった「kokeshi-craftsmen」テーブルが作成されています。  

 

9. 動作確認

 それでは、実際に「こけし」の「工人さん」のデータをPUTしてみたいと思います。今回は「httpie」を使って簡単に確かめます。

 以下のコマンドを打って、鳴子系の桜井昭寛工人のデータをDynamoDBに入れます。  

http PUT https://85qlz6ddnf.execute-api.us-east-1.amazonaws.com\
/dev/put type='Naruko' craftsman='Akihiro Sakurai'

 
 DynamoDBのマネジメントコンソールを見ると、データが投入されています。

 

10. まとめ

 今回は、Serverless Frameworkを使ってAPI GatewayとDynamoDBをからめたときの設定方法を試してみました。
 serverless.ymlに設定を書いて「serverless deploy」とコマンドを打つだけで、必要なリソースの作成ができてしまうのでとても便利ですね。
 これで、こけし工人さんのデータが簡単に登録できるようになり、個人的にもとても満足です。  
 いや〜、Serverless Frameworkって本当にいいものですね。