APIGateway + Lambda + Go(Echo)で開発するためのローカル環境をSAM(Serverless Application Model)で再現する
はじめに
前回の記事では、サーバレス環境をローカルに用意するためにserverless frameworkを利用しました。そこで今回はSAMを利用して同じ環境を構築してみます。
基本的にServerlessFrameworkを利用してきたのでSAMを使うのは今回が初めてでした。
構成は Client
--> APIGW
--> Lambda
で進めます。
ローカル環境構築
brew tap aws/tap brew install aws-sam-cli
今回はGoで環境構築するので go1.x
をruntimeに指定してプロジェクトを作成します。
❯ sam init --runtime go1.x --name serverless Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Choose an AWS Quick Start application template 1 - Hello World Example 2 - Infrastructure event management 3 - Multi-step workflow Template: 1 Based on your selections, the only Package type available is Zip. We will proceed to selecting the Package type as Zip. Based on your selections, the only dependency manager available is mod. We will proceed copying the template using mod. Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: n Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)
sam-initすると自動でディレクトリとファイルが作成されます。今回は hello-world
を削除して echo
ディレクトリを配置しました。
こちらは前回の記事と同じもので、echoフレームワークでヘルスチェックAPIを実装しています。
ソースコードはこちらです。
ディレクトリ構成
serverless ├── README.md ├── echo │ ├── Makefile │ ├── api │ │ └── healthcheck │ │ └── healthcheck.go │ ├── conf │ │ └── config.go │ ├── echo │ ├── go.mod │ ├── go.sum │ ├── handler │ │ └── auth │ │ └── auth.go │ └── main.go ├── events │ └── event.json └── template.yaml
echoフレームワークの部分は前回の記事になどに記載していますので今回は省略します。 goをコンパイルするときに利用するMakefileと samを実行する template.yaml のコードを記載します。
- echo/Makefile
PHONY: deps clean build deps: go get -u ./... clean: rm -rf echo # 変更 build: GOOS=linux GOARCH=amd64 go build -o echo ./main.go
- template.yaml (
# 修正
の部分を自動生成されたファイルを修正しました)
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > description # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 30 # 修正 Resources: HelloWorldFunction: 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: echo # 修正 Handler: echo # 修正 Runtime: go1.x Architectures: - x86_64 Events: 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: /api/{proxy+} # 修正 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: PARAM1: VALUE Outputs: # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function # Find out more about other implicit resources you can reference within SAM # 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/" HelloWorldFunction: Description: "First Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn
このtemplate.yamlですが、AWSに展開することも考えて以下のように書き換えました。どちらもローカルでは同じ動きをします。
- template.yaml
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > description Globals: Function: Timeout: 30 Resources: MyAPI: Type: AWS::Serverless::Api Properties: Name: sam-echo-test StageName: v1 EndpointConfiguration: REGIONAL SAMEchoFunction: Type: AWS::Serverless::Function Properties: CodeUri: echo Handler: echo Runtime: go1.x Architectures: - x86_64 Events: GetApi: Type: Api Properties: Path: /api/{proxy+} Method: get RestApiId: !Ref MyAPI Auth: ResourcePolicy: CustomStatements: [{ "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:ap-northeast-1:*:*/*", "Condition": { "IpAddress": { "aws:SourceIp": "X.X.X.X/32" } } }] #Environment: # Variables: # PARAM1: VALUE
デプロイと動作確認
❯ make build GOOS=linux GOARCH=amd64 go build -o echo ./main.go
- ローカルでsam実行
❯ sam local start-api Mounting HelloWorldFunction at http://127.0.0.1:3000/api/{proxy+} [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 2022-11-03 16:35:45 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit) Invoking echo (go1.x) Skip pulling image and use local one: public.ecr.aws/sam/emulation-go1.x:rapid-1.61.0-x86_64. Mounting /Users/hidetoshi/github-repos/github.com/yhidetoshi/serverless-sam-go-local/serverless/echo as /var/task:ro,delegated inside runtime container START RequestId: 22427e50-7eb8-425a-a06e-2739449f6d7a Version: $LATEST 2022/11/03 07:38:23 echo cold start END RequestId: 22427e50-7eb8-425a-a06e-2739449f6d7a REPORT RequestId: 22427e50-7eb8-425a-a06e-2739449f6d7a Init Duration: 113.63 ms Duration: 735.62 ms Billed Duration: 736 ms Memory Size: 128 MB Max Memory Used: 128 MB 2022-11-03 16:38:23 127.0.0.1 - - [03/Nov/2022 16:38:23] "GET /api/healthcheck HTTP/1.1" 200 -
- clientからヘルスチェクAPIを実行
❯ curl http://127.0.0.1:3000/api/healthcheck {"status":200,"message":"Success to connect echo"}
リクエスト実行中には以下のコンテナが起動して lambdaをエミュレートして処理終了したらコンテナは削除されました。
❯ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7eb1599fd838 public.ecr.aws/sam/emulation-go1.x:rapid-1.61.0-x86_64 "/var/rapid/aws-lamb…" 1 second ago Up Less than a second 127.0.0.1:5959->8080/tcp focused_wilson
(追記) ローカルではなく、AWSにデプロイする方法については、↓の記事にまとめました。
さいごに
前回の記事と同様にサーバーレス環境(APIGW + Lambda + Go(echo))のローカル環境を構築することができました。 この程度のローカル環境を構築するだけだと SAMとServerlessFrameworkはほとんど負担感は変わらない感じでした。 ServerlessFrameworkとSAMで機能や特徴が異なると思うので構築する環境で使い分けていければと思います。