こんにちは。サーバーワークス こけし部 部長でCS課の坂本(@t_sakam)です。前回に続いて、Serverless Frameworkの話題です。
前回は、Serverless Frameworkのドキュメントに沿って、簡単に使い方を確かめてみました。今回は、API GatewayやDynamoDBをからめた使い方をみてみたいと思います。
Serverless Frameworkを使うと、設定ファイルのserverless.ymlに必要な設定を書いて「serverless deploy」とコマンドを打つだけで、必要なリソースの作成ができます。Lambdaファンクションのデプロイだけでなく、API GatewayとDynamoDBのリソース作成もServerless Frameworkでやってしまいましょう。
- Serverless Frameworkのアップデート
- サービスの作成
- 必要なファイルを自動生成
- サービスの内容
- serverless.ymlの編集
- handler.pyの編集
- デプロイ
- 作成されたリソースの確認
- 動作確認
- まとめ
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つのファイルが自動生成されました。
- event.json
- handler.py
- serverless.env.yml
- 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って本当にいいものですね。