はじめに
私はこれまでWebコンソールからポチポチと弄っていたのですが、設定を間違えて動かなくなることがあったので、コマンドラインでサクッとできたらいいなぁと思っておりました。
これを解決すべく、素晴らしいフレームワークが公開されておりますので、今回はこれを使ってみます。
執筆にあたり、以下の記事を参考にさせていただきました。
どうもありがとうございます😄
Serverless Frameworkならすぐ出来るよね AWSでサーバーレス(API+Lambda[java]を簡単セットアップ)
AWS Lambdaとは
AWS Lambda を使用すれば、サーバーのプロビジョニングや管理なしでコードを実行できます。
課金は実際に使用したコンピューティング時間に対してのみ発生し、コードが実行されていないときには料金も発生しません。
魔法のような言葉が羅列していますが、実際にWebコンソールから使ってみると、ソースコード、ビルド、デプロイがバラバラになり、使い勝手が良くありません。
そこで、そこら辺のソリューションをフレームワークとして提供してくれるのがServerless Frameworkです。
Serverless Frameworkでは、LambdaのTemplateとして、以下が用意されています。
今回は、aws-java-gradleを採用します。
- aws-nodejs
- aws-python
- aws-java-maven
- aws-java-gradle
- aws-scala-sbt
- aws-csharp
事前準備
設定済みの方は不要です。
私の開発環境は、MacOSXとなっております。
あまり詳しいことは書いておりませんので、ご了承ください。
環境のセットアップ
Serverless Frameworkのインストール
npmコマンドを使って、serverlsss Frameworkをインストールします。
$ node -v
v7.5.0
$ npm install -g serverless
$ serverless —version
1.27.2
nodeやnpmが使えない方は、Homebrewからインストール可能です。
スクリプトをターミナルに貼り付け実行して下さい。
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
AWS CLIのインストール
コマンド内部で、AWS CLIを叩くのでインストールします。
(インストール済みの場合は、読み飛ばしてください)
$ pip install awscli
必要な権限のあるIAMユーザを用意し、設定をします。
(詳細は調べていません)
$ aws configure
AWS Access Key ID [None]:(Access Key)
AWS Secret Access Key [None]:(Secret Key)
Default region name [None]: ap-northeast-1
Default output format [None]:json
アプリケーションの作成
hello world的なものを作成します。
Serviceの作成
まずはテンプレートを作成します。
プロジェクト名は、myService
としました。適宜変更してください。
$ serverless create --template aws-java-gradle --path myService
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/hogehoge/Documents/myService"
_______ __
| _ .-----.----.--.--.-----.----| .-----.-----.-----.
| |___| -__| _| | | -__| _| | -__|__ --|__ --|
|____ |_____|__| \___/|_____|__| |__|_____|_____|_____|
| | | The Serverless Application Framework
| | serverless.com, v1.27.2
-------'
Serverless: Successfully generated boilerplate for template: "aws-java-gradle"
Eclipseにインポート
Eclipseを起動して、Project Explorer -> 右クリック -> Gradle -> Existing Gradle Projectsで先程作成した「myService」フォルダを選択します。
serverless.ymlの修正とBuild
serverless.ymlの20行目あたりにある設定を変更します。
provider:
name: aws
runtime: java8
stage: prod
region: ap-northeast-1
せっかくなのでコマンドラインから、ビルド出来るか試してみます。
Eclipseから実行する場合は、Gradleタスクの実行からbuildを選択してください。
$ gradle build
Starting a Gradle Daemon (subsequent builds will be faster)
BUILD SUCCESSFUL in 8s
4 actionable tasks: 4 executed
$ ls -l build/libs
total 16
-rw-r--r-- 1 hogehoge staff 4907 5 15 10:04 myService.jar
LambdaのみDeployしてみる
Serveress Frameworkでは、Lambdaのセットアップ、JarのアップロードをCloudFormationを使って実行します。
これで Lambda関数に myService-prod-hello
が出来ていればOKです。
WebコンソールでLambdaを設定して、Jarアップロードして...面倒な作業が不要となります。
$ cd myService
$ serverless deploy -v
Serverless: Packaging service...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - myService-prod
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - myService-prod
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (1.81 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - myService-prod
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionAMFqcDHAse48pHCLO4T8bZ0tcLP0S5hwaqiXFZhekc
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionAMFqcDHAse48pHCLO4T8bZ0tcLP0S5hwaqiXFZhekc
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - HelloLambdaVersionAMFqcDHAse48pHCLO4T8bZ0tcLP0S5hwaqiXFZhekc
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - myService-prod
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - myService-prod
Serverless: Stack update finished...
Service Information
service: myService
stage: prod
region: ap-northeast-1
stack: myService-prod
api keys:
None
endpoints:
None
functions:
hello: myService-prod-hello
Stack Outputs
HelloLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:************:function:myService-prod-hello:1
ServerlessDeploymentBucketName: myservice-prod-serverlessdeploymentbucket-n1n0p0oovbe7
テスト
早速動くかテストしてみましょう。
テストケースを作成してから実行します。
echo '{"key1":"value1","key2":"value2","key3":"value3"}' > event.json
$ serverless invoke --function hello -p event.json
{
"statusCode": 200,
"body": "{\"message\":\"Go Serverless v1.x! Your function executed successfully!\",\"input\":{\"key1\":\"value1\",\"key2\":\"value2\",\"key3\":\"value3\"}}",
"headers": {
"X-Powered-By": "AWS Lambda & serverless"
},
"isBase64Encoded": false
}
API Gateway+Lambdaの構成でデプロイ
上記手順では、endpoints がありません。
API Gateway+Lambdaとなるよう、設定を変更後にDeployします。
serverless.ymlの51行目周辺のfunction句を書き換えます。
functions:
hello:
handler: com.serverless.Handler
events:
- http:
path: users/create
method: get
Deployしてみます。
Amazon API Gatewayにprod-myService
が作成されます。
$ serverless deploy -v
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (1.81 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - myService-prod
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceUsers
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceUsers
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceUsers
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceUsersCreate
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceUsersCreate
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceUsersCreate
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodUsersCreateGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodUsersCreateGet
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodUsersCreateGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1526347394711
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1526347394711
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1526347394711
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - myService-prod
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - myService-prod
Serverless: Stack update finished...
Service Information
service: myService
stage: prod
region: ap-northeast-1
stack: myService-prod
api keys:
None
endpoints:
GET - https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/prod/users/create
functions:
hello: myService-prod-hello
Stack Outputs
HelloLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:************:function:myService-prod-hello:1
ServiceEndpoint: https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/prod
ServerlessDeploymentBucketName: myservice-prod-serverlessdeploymentbucket-n1n0p0oovbe7
テスト
endpointに向けてリクエストして、反応するか確認します。
curl https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/prod/users/create | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1541 100 1541 0 0 7820 0 --:--:-- --:--:-- --:--:-- 7822
{
"message": "Go Serverless v1.x! Your function executed successfully!",
"input": {
"resource": "/users/create",
"path": "/users/create",
"httpMethod": "GET",
"headers": {
"Accept": "*/*",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "JP",
"Host": "**********.execute-api.ap-northeast-1.amazonaws.com",
"User-Agent": "curl/7.54.0",
"Via": "2.0 *********.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "************",
"X-Amzn-Trace-Id": "Root=********",
"X-Forwarded-For": "XXX.XXX.XXX.XXX, XXX.XXX.XXX.XXX",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"queryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
"resourceId": "***",
"resourcePath": "/users/create",
"httpMethod": "GET",
"extendedRequestId": "******************",
"requestTime": "15/May/2018:01:27:55 +0000",
"path": "/prod/users/create",
"accountId": "************",
"protocol": "HTTP/1.1",
"stage": "prod",
"requestTimeEpoch": *****,
"requestId": "********-****-****-****-************",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"sourceIp": "XXX.XXX.XXX.XXX",
"accessKey": null,
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "curl/7.54.0",
"user": null
},
"apiId": "hogehoge"
},
"body": null,
"isBase64Encoded": false
}
}
Stackの削除
上記で作成したCloudFormationのStackごと削除できます。
$ serverless remove
Serverless: Getting all objects in S3 bucket...
Serverless: Removing objects in S3 bucket...
Serverless: Removing Stack...
Serverless: Checking Stack removal progress...
................
Serverless: Stack removal finished...
参考
Serverless Frameworkならすぐ出来るよね AWSでサーバーレス(API+Lambda[java]を簡単セットアップ)