まっしろけっけ

めもてきなやーつ

AWS SAM CLI を使って AWS Lambda をいい感じに管理する

はじめに

github.com
今回使うのは上記

Lambda 環境をローカルで動かしたり出来るので動作確認とかがすごく便利になるやーつ

実際に使う

インストール

今回は mac にインストールする

$ brew tap aws/tap
$ brew install aws-sam-cli
$ sam --version
SAM CLI, version 0.41.0

サンプルのアプリを作ってみる

今回は sam-app という名前のアプリを Golang で作成します。

$ sam init --name sam-app --runtime go1.x
$ cd sam-app
$ tree ./
├── Makefile
├── README.md
├── hello-world
│   ├── main.go
│   └── main_test.go
└── template.yaml

ローカルで動作確認

まずはローカルで動作確認をしてみる

$ GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world # まずは build
$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
# http://127.0.0.1:3000/hello にアクセスするとレスポンスが返ってくる
# 初回は Image の DL が走るので時間がかかる

デプロイする

$ sam deploy -g # 初回は対話式で色々入力したいので -g をつける
# 色々な IAM 周りの権限を作ってくれる
# samconfig.toml というファイルが作られる
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OutputKey-Description                                                                                OutputValue
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World function                       arn:aws:iam::0000:role/sam-app-HelloWorldFunctionRole-xxxxx
HelloWorldAPI - API Gateway endpoint URL for Prod environment for First Function                     https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
HelloWorldFunction - First Lambda Function ARN                                                       arn:aws:lambda:ap-northeast-1:0000:function:sam-app-HelloWorldFunction-xxxx
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ sam deploy # 2 回目以降

コレで deploy が完了するので上記の HelloWorldAPI - API Gateway endpoint URL for Prod environment for First Function に記載されている URL にアクセスするとレスポンスが返ってきます。

/hello/ をやめてみる

endpoint 変更したいなって気持ちなので変更してみる

$ git diff
diff --git a/template.yaml b/template.yaml
--- a/template.yaml
+++ b/template.yaml
@@ -22,7 +22,7 @@ Resources:
         CatchAll:
           Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
           Properties:
-            Path: /hello
+            Path: /
             Method: GET
       Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
         Variables:
@@ -34,7 +34,7 @@ Outputs:
   # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
   HelloWorldAPI:
     Description: "API Gateway endpoint URL for Prod environment for First Function"
-    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
+    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/"
   HelloWorldFunction:
     Description: "First Lambda Function ARN"
     Value: !GetAtt HelloWorldFunction.Arn
$ sam deploy 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------OutputKey-Description                                                                                OutputValue
------------------------------------------------------------------------------------------------------------------------------------------------------------------------HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World function                       arn:aws:iam::0000:role/sam-app-HelloWorldFunctionRole-xxxxx
HelloWorldAPI - API Gateway endpoint URL for Prod environment for First Function                     https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
HelloWorldFunction - First Lambda Function ARN                                                       arn:aws:lambda:ap-northeast-1:0000:function:sam-app-HelloWorldFunction-xxxx
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, 0.0.0.0

Golang の場合はどのアプリが使われるのか?

Golang の場合は build されたアプリが使われるのか勝手に build されるのか?という部分が少し謎だったので調べてみた。

$ git diff hello-world/
diff --git a/hello-world/main.go b/hello-world/main.go
--- a/hello-world/main.go
+++ b/hello-world/main.go
@@ -41,7 +41,7 @@ func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyRespo
        }

        return events.APIGatewayProxyResponse{
-               Body:       fmt.Sprintf("Hello, %v", string(ip)),
+               Body:       fmt.Sprintf("Hello, %v", string("test")),
                StatusCode: 200,
        }, nil
 }
$ sam deploy 
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, 0.0.0.0 # 変わってない
$ GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world
$ sam deploy 
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, test # 変わった

ということはどこかで build 後のバイナリを指定してるんだろうなと思って template.yaml を覗いてみたら Handler: hello-world と記述された部分があったのでもう少し実験

$ mv hello-world/hello-world hello-world/hoge
$ git diff template.yaml
diff --git a/template.yaml b/template.yaml
--- a/template.yaml
+++ b/template.yaml
@@ -15,14 +15,14 @@ Resources:
     Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
     Properties:
       CodeUri: hello-world/
-      Handler: hello-world
+      Handler: hoge
       Runtime: go1.x
$ sam deploy
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, test # 動いてる

ということでバイナリの名前を変えて template.yaml 内で指定していた場所を書き換えたら、元どおりに動いているので推測通り Handler 部分で指定されているというのが確認できた。

最後に

まだ AWS SAM CLI について調べきれていないので触りながら動作を確認してみた。

最終的にやりたいことは example.com > CDN > Lambda といった感じで CDN を挟んでアクセスを Lambda に向けたいというものなのだけれど、CDN が CloudFront ならサクッと出来るが今回は諸々の事情から Akamai を使うので Akamai の設定でハマって進捗が悪くここまで...

続きは第二回のブログがあるかもしれない