Serverless Meetup Tokyo #16 (オンライン開催) を拝見していて、ちょうど今、AWS への各種リソースのデプロイの自動化が課題だったので、よい機会と思い Serverless Framework を使ってみた。 尚、Serlverless Framwork については知っていたが、offline-start しか使ったことがなかった程度の人間です。
弊社では Webシステムを、
で組むことが増えてきていて、プロジェクトの取っ掛かり時の環境構築を手動でやっているのがダルくなってきた。 今回は、「REST っぽいAPI: Lambda + API Gateway」のところを Serverless Framework で自動化してみた。
IAM コンソールで「serverless_deployment」という名前で作成。以下のポリシーをアタッチした。
さらに、以下のようなインラインポリシーを追加した。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:DeleteRolePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:PutRolePolicy"
],
"Resource": "*"
}
]
}
IAMFullAccess はさすがにヤバいかなと思い必要な権限だけ抽出したものだが、たぶん他の xxxFullAccess も必要なものだけにした方がよいだろう。
作成した IAM のアクセスキーなどを自PCの ~/.aws/credentials
に追加した。ちなみに環境は Windows 10 内の WSL(Ubuntu)。
.aws/credentials
[serverless-deployment]
aws_access_key_id = AKIAxxxxx
aws_secret_access_key = 49s9xxxxxxxxxxxxxxxxxxxxxxxxxxxx
awscli は現在最新の v2 をインストール
node は 12.14.1
そして Serverless Framework をインストールする。
npm install serverless -g
source ~/.bash_profile
serverless --version
> Framework Core: 1.65.0
> Plugin: 3.4.1
> SDK: 2.3.0
> Components: 2.22.3
global じゃなくてもいいけど、パス通すのが面倒なので。
serverless create --template aws-nodejs
で、nodejs のテンプレートから Serverless Framework のプロジェクトを作成。
また、npm init
で適当に package.json
を作って、
npm install --save-dev serverless-plugin-custom-binary
を実行しておく。これは後に必要になるプラグイン。
ls
すると以下のようなファイルとディレクトリがある。
handler.js node_modules package-lock.json package.json serverless.yml
serverless.yml
を開いて次のように編集する(これだと最早テンプレートの意味ないが)。
service: my-awesome-service
plugins:
- serverless-plugin-custom-binary
custom:
apiGateway:
binaryMediaTypes:
- image/jpeg
provider:
name: aws
runtime: nodejs12.x
stage: ${opt:stage, 'dev'}
region: ap-northeast-1
apiName: ${self:service}-${self:provider.stage}
functions:
api:
handler: handler.hello
name: ${self:service}-api-${self:provider.stage}
events:
- http:
path: /{proxy+}
method: get
integration: lambda
まず service: my-awesome-service
、これが AWS に作成されるリソース名の元になるのでちゃんと考えて命名しよう。重複したらどうなちゃうのかは不明。 kebab-case を採用しておくと良いと思われる。例えばサービス名で S3 Bucket を作りたいとき、Bucket 名は CamelCase(大文字) を許可してないため。
次に Plugins と binaryMediaTypes。これを行うために先に serverless-plugin-custom-binary をインストールしておいた。
provider-apiName。これは API Gateway の名前なんだけど、これをしない場合 <stage名>-<service名>
になる。Lambda とかは <service名>-<stage名>
となり逆で気持ち悪いので、他の同じになるように直している。
stage: ${opt:stage, 'dev'}。単純に stage: dev
とするだけだと、 --stage prod
を引数で指定された値が ${self:provider.stage}
に代入されないので注意。
functions-api。Labmda に <service名>-<stage名>-api
という名前の関数が作成される。"api" は任意の名称で ok。
functions-api-name。既定だと <service名>-<stage名>-api
になるが、<service名>-api-<stage名>
にしたい(stage名は最後尾に統一したい) ので name: ${self:service}-api-${self:provider.stage}
とした。
handler: handler.hello。 handles.js
の hello 関数を呼び出すの意。
path: /{proxy+}。呼び出し URL のパス部分を全てスルーする。https://hoge.net/dev/fuga/piyo/gege
とか。
integration: lambda。既定で ON ぽいので要らないかも。
serverless deploy --aws-profile serverless-deployment
を実行する。--aws-profile serverless-deployment
で AWSプロファイルを指定している事に注意。
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service MyAwesomeService.zip file to S3 (1.13 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...............................
Serverless: Stack update finished...
Service Information
service: MyAwesomeService
stage: dev
region: ap-northeast-1
stack: MyAwesomeService-dev
resources: 11
api keys:
None
endpoints:
GET - https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/{proxy+}
functions:
api: MyAwesomeService-dev-api
layers:
None
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.
なんやかんや実行されてデプロイされたみたい。
cURL で呼び出してみる。
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/aaa/bbb/ccc
{"statusCode":200,"body":"{\n \"message\": \"Go Serverless v1.0! Your function executed successfully!\"...
うまくいったみたい。
serverless remove --aws-profile serverless-deployment
ですべてのリソースがキレイさっぱり消えます。これはこれで怖いので IAM の権限で制限したほうが良さそう。
A: Console から CloudFormation の該当スタックを削除してリトライ
A: 該当バケット(my-awesome-service-veri-serverlessdeploymentbucke-rzr9e2jjdrlv
のようなごちゃごちゃしたやつ) を手動作成するか、Console から CloudFormation の該当スタックを削除してリトライ