MMMブログ

AWS SAMとGo言語で体感するサーバーレス開発

今回はAWS SAMを使用してサーバーレスアプリケーションを構築していきます。

API GatewayをトリガーとしてLambda関数が発火するという非常にシンプルな内容です。そのためサーバーレス開発のイメージを掴みやすいのではないかと思います。

AWS SAMとは

AWS SAM(Serverless Application Model)とは、AWS上にサーバーレスアプリケーションを構築することができるフレームワークです。YAMLまたはJSON形式で構成を記述することができます。

コマンドラインツールとしてAWS SAM CLIも提供されており、ローカル環境でもLambda関数を実行することができます。

準備

AWS CLIとAWS SAM CLIを導入します。pipやbrewといった、お好きなパッケージ管理ツールでインストールしてください。

1
2
$ pip install awscli
$ pip install aws-sam-cli
1
2
$ brew install awscli
$ brew install aws-sam-cli

AWS CLIで利用するプロファイルも設定しておきましょう。すでに設定済みの場合は不要です。

1
2
3
4
5
$ aws configure --profile iamSAM
AWS Access Key ID [None]: ******************
AWS Secret Access Key ID [None]: ******************
Default region name [None]: ap-northeast-1
Default output format [None]: json

サーバーレスアプリケーションのベースを作成

sam init コマンドでサーバーレスアプリケーションの雛形を作成します。

今回はGoで関数を作成していきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ sam init --runtime go1.x --name aws-sam-golang

Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1

Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git

-----------------------
Generating application:
-----------------------
Name: aws-sam-golang
Runtime: go1.x
Dependency Manager: mod
Application Template: hello-world
Output Directory: .

Next steps can be found in the README file at ./aws-sam-golang/README.md

$ cd aws-sam-golang

$ tree
.
├── Makefile
├── README.md
├── hello-world
│   ├── main.go
│   └── main_test.go
└── template.yaml

1 directory, 5 files

hello-world/main.go が、今回のLambda関数の実装を行うファイルです。 template.yaml にはサーバーレスアプリケーションの関数定義が記述されています。

また、今回はGoのライブラリバージョン管理にModulesを使います。
Modulesについてはこちらの記事を御覧ください。

1
2
$ go mod init
go: creating new go.mod: module hoge/fuga/aws-sam-golang

雛形の実行テスト

sam local start-api コマンドで、ローカルでもLambda関数を実行することができます(Docker上で動作します)。

Lambda関数の実行にはバイナリが必要ですので、makeコマンドでビルドしましょう。

1
2
3
4
5
6
7
8
$ make build
GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world

$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2020-01-19 20:38:36 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
Invoking hello-world (go1.x)

この状態で、curlコマンドでAPIを叩いてみましょう。

1
2
$ curl http://localhost:3000/hello
Hello, 118.***.***.**

雛形のhello-world/main.goに従い、自分のグローバルIPアドレスが返ってきました。

SAM Local側では次のようなログが確認できます。

1
2
3
4
5
6
7
Fetching lambci/lambda:go1.x Docker container image......
Mounting /Users/daisakuhazui/develop/aws-sam-golang/hello-world as /var/task:ro,delegated inside runtime container
START RequestId: c0308535-1ed4-15d2-a58d-ff1ac09907ad Version: $LATEST
END RequestId: c0308535-1ed4-15d2-a58d-ff1ac09907ad
REPORT RequestId: c0308535-1ed4-15d2-a58d-ff1ac09907ad Init Duration: 169.68 ms Duration: 891.58 ms Billed Duration: 900 ms Memory Size: 128 MB Max Memory Used: 27 MB
No Content-Type given. Defaulting to 'application/json'.
2020-01-19 20:38:58 127.0.0.1 - - [19/Jan/2020 20:38:58] "GET /hello HTTP/1.1" 200 -

Lambda関数の修正

雛形の動作確認が取れたので、次はLambda関数に手を加えましょう。

先ほど確認した通り、現状のコードはhttp://localhost:3000/helloへのリクエストに対しIPアドレスを返す実装になっています。

この実装をhttp://localhost:3000/hello/{user}に対してHello, {user}と返すよう、これから修正していきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
`main.go`

package main

(中略)

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
user, _ := request.PathParameters["user"]

return events.APIGatewayProxyResponse{
Body: fmt.Sprintf("Hello, %s", user),
StatusCode: 200,
}, nil
}

func main() {
lambda.Start(handler)
}

関数を修正したらtemplate.yamlにも修正が必要です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
`template.yaml`
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
aws-sam-golang

Sample SAM Template for aws-sam-golang

Globals:
Function:
Timeout: 5

Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: hello-world
Runtime: go1.x
Tracing: Active
Events:
CatchAll:
Type: Api
Properties:
Path: /hello/{user} # パスパラメータをセット
Method: GET
Environment:
Variables:
PARAM1: VALUE



Type: AWS::Serverless::FunctionでLambda関数であることを表し、Events配下のCatchAllでAPIの定義を行っています。

今回はパスパラメータを受け取れるようにPathの値を修正しました。

動作確認

関数とテンプレートの修正が終わったのでローカルで動作確認していきます。

1
2
3
4
5
6
7
8
$ make build
GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world

$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello/{user} [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2020-01-19 20:47:07 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
Invoking hello-world (go1.x)

今度はパスパラメータを与えてcurlコマンドを叩いてみましょう。

1
2
$ curl http://localhost:3000/hello/Daisaku
Hello, Daisaku

OKです。想定通りの動きになっています。

AWS上にデプロイ

ローカルで動作確認を終えたので、実際にAWS上にデプロイしてみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
$ sam validate --profile iamSAM
/Users/daisakuhazui/develop/aws-sam-golang/template.yaml is a valid SAM Template

$ sam package \
--template-file template.yaml \
--s3-bucket <YOUR BUCKET NAME> \
--output-template-file packaged.yaml \
--profile iamSAM

Uploading to a1342a2f62dce02aba5dfa11e11a6d1d 5023955 / 5023955.0 (100.00%)

Successfully packaged artifacts and wrote output template to file packaged.yaml.
Execute the following command to deploy the packaged template
sam deploy --template-file /Users/daisakuhazui/develop/aws-sam-golang/packaged.yaml --stack-name <YOUR STACK NAME>

$ sam deploy \
--profile iamSAM \
--region ap-northeast-1 \
--template-file /Users/daisakuhazui/develop/aws-sam-golang/packaged.yaml \
--stack-name aws-sam-golang \
--capabilities CAPABILITY_IAM

Deploying with following values
===============================
Stack name : aws-sam-golang
Region : ap-northeast-1
Confirm changeset : False
Deployment s3 bucket : None
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}

Initiating deployment
=====================

Waiting for changeset to be created..

(中略)

Stack aws-sam-golang outputs:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OutputKey-Description OutputValue
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World function arn:aws:iam::************:role/aws-sam-golang-HelloWorldFunctionRole-*************
HelloWorldAPI - API Gateway endpoint URL for Prod environment for First Function https://**********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
HelloWorldFunction - First Lambda Function ARN arn:aws:lambda:ap-northeast-1:************:function:aws-sam-golang-
HelloWorldFunction-*************
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - aws-sam-golang in ap-northeast-1

これでAWS上へのデプロイが完了しました。

最後にAPI Gatewayのエンドポイントにアクセスしてみましょう。(API Gateway endpoint URL for Prod environment for First Functionの右にあるURL)

1
2
$ curl https://**********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/Daisaku
Hello, Daisaku

API Gateway経由でも期待通りのレスポンスが返ってきました。

まとめ

AWS SAMとGo言語を使って非常にシンプルなサーバーレス構成を構築しました。

昨年のアップデートでAWS SAMのデプロイ方法が非常に簡単になり、とても使いやすくなったんじゃないかなと思います。(sam packagesam deployのパラメータは複雑ですが…)

参考になれば幸いです。

このエントリーをはてなブックマークに追加

お問い合わせ

見積もり依頼や詳しいご相談など、クラウド・AWSに関する困りごとをお気軽にご相談ください。
以下のお問い合わせ先から受け付けています。

お問合わせはこちら

※通常1営業日内にご回答いたします。