Go on AWS Lambda ことはじめ& SAM 化する手順

 お客さんとサーバレス勉強モブプロをやることになりました。 AWSによるサーバーレスアーキテクチャ を参考書籍として、Node.js で書かれている内容を全て Go にしてみようというもの。ワタシ、Python 以外で Lambda 書く自信ナイ。。そもそも Go 書いたことない。。

 ということで、勉強がてら

  • Golang で Lambda ファンクションを作る
  • ↑ を SAM 化する

をやってみましたので、手順についてメモします。「Go のお作法的にちがうだろー」などあればぜひご教示いただければと思います。

AWSによるサーバーレスアーキテクチャ

AWSによるサーバーレスアーキテクチャ

Go で Lambda ファンクションを作るまで

ローカル環境を整える

 まずは Go のインストールです。( brew update してなかったからか Go のバージョンが古くもう一度入れ直すはめに。後述します。)

$ brew install go

$ go version
go version go1.6.3 darwin/amd64

 次に GOPATH なるものをインストールし go get したときのパッケージ?モジュール?の配置先を指定する必要があるとのこと。

$ more ~/.bash_profile
-> `export GOPATH=$HOME/go` を追加する

$ source ~/.bash_profile

 試しに Hello World してみる。

package main
import "fmt"

func main() {
  hello()
}

func hello() {
  fmt.Println("Hello, go world!!")
}
$ go build helloworld.go 

$ ./helloworld 
Hello, go world!!

動きました:)

Lambda 用のパッケージを導入

 続いて、Lambda 用のパッケージの導入。

$ go get -u github.com/aws/aws-lambda-go/lambda
unrecognized import path "context"

unrecognized import path "context" ??🤔 どうやら Go のバージョンが古い模様🤔

Getting Started - The Go Programming Language

こちらから Go の最新バージョンをインストールし直し、配置場所を変更(これ正しいのか自信ないです。が、動作はします。)。

$ mv /usr/local/go/bin/go /usr/local/bin/

再度、Go パッケージの導入。

$ go get -u github.com/aws/aws-lambda-go/lambda

成功した模様。最初に設定した GOPATH を見ると何やらインストールされているようです。( GOPATH ってどこに設定すべきなのだろう? npm のようにプロジェクト毎に配置先変えるべきものな気もするけど。追って調べる。)

$ ll ~/go/src/github.com/aws/aws-lambda-go/
total 36
drwxr-xr-x 15 hogehoge staff   510  4 19 01:16 .
drwxr-xr-x  3 hogehoge staff   102  4 19 01:16 ..
drwxr-xr-x 15 hogehoge staff   510  4 19 01:26 .git
-rw-r--r--  1 hogehoge staff   974  4 19 01:16 .travis.yml
-rw-r--r--  1 hogehoge staff   893  4 19 01:16 Gopkg.lock
-rw-r--r--  1 hogehoge staff   534  4 19 01:16 Gopkg.toml
-rw-r--r--  1 hogehoge staff 11359  4 19 01:16 LICENSE
-rw-r--r--  1 hogehoge staff   879  4 19 01:16 LICENSE-LAMBDACODE
-rw-r--r--  1 hogehoge staff   300  4 19 01:16 LICENSE-SUMMARY
-rw-r--r--  1 hogehoge staff  2608  4 19 01:16 README.md
drwxr-xr-x 10 hogehoge staff   340  4 19 01:16 cfn
drwxr-xr-x  3 hogehoge staff   102  4 19 01:16 cmd
drwxr-xr-x 50 hogehoge staff  1700  4 19 01:16 events
drwxr-xr-x 11 hogehoge staff   374  4 19 01:16 lambda
drwxr-xr-x  4 hogehoge staff   136  4 19 01:16 lambdacontext

 次にソースコードを作成します。といっても、AWS 公式 GitHub からそのまま持ってきただけです。

package main

import (
    "github.com/aws/aws-lambda-go/lambda"
)

func hello() (string, error) {
    return "Hello World!", nil
}

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

 ビルドして、zip 化します。ビルド時は GOOSGOARCH を指定する必要があります。

$ GOOS=linux GOARCH=amd64 go build sample.go 
$ zip -r sample.zip ./sample

出来上がった sample.zip をアップロードしてみます。ハンドラを sample とするのを忘れないように。

f:id:ketancho_jp:20180419015242p:plain

実行してみると、

f:id:ketancho_jp:20180419021608p:plain

いい感じです😃

SAM 化する

 せっかくなので SAM 化してみます。下の記事を参考にしています。

まず、テンプレートの作成です。IAM ロールには DynamoDB 権限だけ振ってます(DynamoDB 参照していませんが、、そのうち。)。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Go on Lambda sample.

# SAM Resources
Resources:
  SamSampleLambda:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: sample.zip
      Handler: sample
      Runtime: go1.x
      Role: !GetAtt GoOnLambdaIamRole.Arn
      Timeout: 30
  GoOnLambdaIamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: "sts:AssumeRole"
      Policies:
        -
          PolicyName: "dynamodb_for_go_onlambda"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              -
                Effect: "Allow"
                Action: "dynamodb:*"
                Resource: "*"

 次にテンプレート置き場の S3 バケットを作ります。 --profile 指定は各環境に応じて置き換えて(削除して)ください。

aws s3 mb s3://(★任意のバケット名) --profile sam-sample

最後にデプロイ用のシェルを作ります。

GOOS=linux GOARCH=amd64 go build sample.go
zip -r sample.zip ./sample

aws cloudformation package \
    --template-file template.yaml \
    --s3-bucket (★任意のバケット名) \
    --output-template-file packaged-template.yaml \
    --profile sam-sample

aws cloudformation deploy \
    --template-file packaged-template.yaml \
    --stack-name (★任意のバケット名) \
    --capabilities CAPABILITY_IAM \
    --profile sam-sample

デプロイしてみます。上手くいったでしょうか??

$ sh deploy.sh

まとめ

 Python で SAM を学んでおくと、言語が変わってもナレッジをほぼそのまま使える!という感想を得ました。ぜひ SAM シリーズやってみてください!!(宣伝)。

参考ページ

github.com

www.ketancho.net

www.ketancho.net