AWS LambdaでGoが正式にサポートされた!!
AWS Lambda Supports Go
https://aws.amazon.com/jp/about-aws/whats-new/2018/01/aws-lambda-supports-go/
aws/aws-lambda-go
https://github.com/aws/aws-lambda-go
2018/01/17現在、日本語版はまだだが、英語のDocsは公開されているので、それを基にGoでLambdaを動かす。
Programming Model for Authoring Lambda Functions in Go
https://docs.aws.amazon.com/en_us/lambda/latest/dg/go-programming-model.html
Announcing Go Support for AWS Lambda
https://aws.amazon.com/jp/blogs/compute/announcing-go-support-for-aws-lambda/
TL;DR
- 基本的にコードファイルひとつで実行バイナリまで作れる
- ハンドラ定義は5パターンのみ(
TIn,TOutはencoding/jsonが使える構造体) - 渡される
Contextの中にはLambdaContextが入っている - ログは
fmtやlogを使っていればよしなにしてくれる - エラー処理は
errorやpanicなど標準のものが使える os.Getenvで環境変数の確認ができる
実装したコードは以下
https://github.com/budougumi0617/sandbox-aws-lambda-go/blob/master/hello-lambda/main.go
package main
import (
"context"
"errors"
"fmt"
"log"
"os"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-lambda-go/lambdacontext"
)
func HelloLambdaHandler(ctx context.Context, config events.ConfigEvent) (string, error) {
lc, ok := lambdacontext.FromContext(ctx)
if !ok {
return "", errors.New("Cannot find LambdaContext")
}
log.Printf("log:InvokedFunctionArn = %s\n", lc.InvokedFunctionArn)
fmt.Printf("fmt:InvokedFunctionArn = %s\n", lc.InvokedFunctionArn)
log.Printf("config version is %v\n", config.Version)
log.Printf("\"%s\" executes on \"%s\".\n", os.Getenv("LAMBDA_TASK_ROOT"), os.Getenv("AWS_EXECUTION_ENV"))
return "function finished", nil
}
func main() {
lambda.Start(HelloLambdaHandler)
}
前提・準備
とりあえず動かすだけなのでzipでLambdaにコードをアップしてテストイベントで実行してみる。 事前に空のLambda関数を作っておく。自分の設定は以下。
- コードエントリタイプ
- .ZIPファイルをアップロード
- ランタイム
- Go 1.x
- ハンドラ
- main
- 実行ロール
- IAMで空のロールを作っておきそれを使う
- テストイベント
- イベントテンプレートの
AWS Config Change Triggered Ruleの値を少し変えたものを用意した。
- イベントテンプレートの
{
"configRuleId": "config-rule-0123456",
"version": "6.17",
"configRuleName": ...
}
もろもろのGoの開発環境は済んでいると想定する。
ハンドラ定義は5パターンのみ(TIn, TOutはencoding/jsonが使える構造体)
Lambda Function Handler (Go)
https://docs.aws.amazon.com/en_us/lambda/latest/dg/go-programming-model-handler-types.html
ハンドラにはcontext.Contextやイベント情報が渡される。定義出来るパターンは以下。
func ()func () errorfunc (TIn), errorfunc () (TOut, error)func (context.Context) errorfunc (context.Context, TIn) errorfunc (context.Context) (TOut, error)func (context.Context, TIn) (TOut, error)
引数は0〜2個まで。引数を指定するときはcontext.Contextを第一引数にするのが必須。
戻り値も0〜2個。最終戻り値はerrorになる形。
TInとTOutはencoding/jsonでUnmarshalできる必要がある。
AWS内のイベントは既に構造体が定義されているので、それをつかえる。
https://godoc.org/github.com/aws/aws-lambda-go/events
今回はevents.ConfigEventを使ってみた。
package events
// ConfigEvent contains data from an event sent from AWS Config
type ConfigEvent struct {
...
Version string `json:"version"`
}
渡されるContextの中にはLambdaContextが入っている
The Context Object (Go)
https://docs.aws.amazon.com/en_us/lambda/latest/dg/go-programming-model-context.html
https://godoc.org/github.com/aws/aws-lambda-go/lambdacontext
ハンドラに渡されるcontext.Contextの中には、LambdaContextが入っていて、AWSの情報がよしなに入っている。
lc, ok := lambdacontext.FromContext(ctx)
if !ok {
return "", errors.New("Cannot find LambdaContext")
}
fmt.Printf("InvokedFunctionArn = %s\n", lc.InvokedFunctionArn) // InvokedFunctionArn = arn:aws:lambda:ap-no...
lambdacontext.NewContextを使って
自分でContextの中にLambdaContextを入れることも出来る(ハンドラ内でgoroutine回したりする時用?)
ログはfmtやlogを使っていればよしなにしてくれる
Logging (Go)
https://docs.aws.amazon.com/en_us/lambda/latest/dg/go-programming-model-logging.html
ログは他の言語で実装したとき同様標準出力に出力すればCloudWatchに保存される。logを使えばタイムスタンプを付与しておく事もできる。
log.Printf("log:InvokedFunctionArn = %s\n", lc.InvokedFunctionArn) // 2018/01/16 23:07:46 log:Invoked...
fmt.Printf("fmt:InvokedFunctionArn = %s\n", lc.InvokedFunctionArn) // fmt:Invoked...
エラー処理はerroやpanicなど標準のものが使える
Function Errors (Go)
https://docs.aws.amazon.com/en_us/lambda/latest/dg/go-programming-model-errors.html
エラー処理は普通のGoとあまり変わらないようだ。ちゃんと試せてはいない。
panicを仕込むとStackTraceなども取れるらしい?
以下、上記公式の内容を引用。
{
"errorMessage": "Something went wrong",
"errorType": "errorString",
"stackTrace": [
{
"path": "github.com/aws/aws-lambda-go/lambda/function.go",
"line": 27,
"label": "(*Function).Invoke.function"
},
...
]
}
os.Getenvで環境変数の確認ができる
Using Environment Variables (Go)
https://docs.aws.amazon.com/en_us/lambda/latest/dg/go-programming-model-env-variables.html
他の言語と同様、os.Getenvで環境変数を取得できる。
fmt.Printf("\"%s\" executes on \"%s\".\n", os.Getenv("LAMBDA_TASK_ROOT"), os.Getenv("AWS_EXECUTION_ENV")) // "/var/task" executes on "".
ちなみにAWS_EXECUTION_ENVがどうなるか書いてなかったので、興味本位で見ようと思ったら本当に設定されてなかった(?)
Environment Variables Available to Lambda Functions
https://docs.aws.amazon.com/en_us/lambda/latest/dg/current-supported-versions.html#lambda-environment-variables
2018/01/17現在、用意されている内容はこれくらい。
デプロイ・動作確認
上記内容を全て実装したのが、冒頭に記載した以下のリンク先のコード
https://github.com/budougumi0617/sandbox-aws-lambda-go/blob/master/hello-lambda/main.go
これをAWS Lambda上で動かしてみる。Goの(一番簡単な方法をする)場合はビルドしてzipに入れてアップするだけ。 Linux用にビルドするのと、「前提・準備」で設定した「ハンドラ」と同じ名前のバイナリをするところだけ注意する。 これをLambdaのWebコンソールからアップロードすれば実行できる
$ GOOS=linux go build -o main
$ zip deployment.zip main
作成したテストイベントで実行した結果がこちら。
START RequestId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX Version: $LATEST
2018/01/16 23:07:46 log:InvokedFunctionArn = arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXXXX:function:myFirstLambda
fmt:InvokedFunctionArn = arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:myFirstLambda
2018/01/16 23:14:26 config version is 6.17
2018/01/16 23:14:26 "/var/task" executes on "".
END RequestId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXX
REPORT RequestId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX Duration: 0.59 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 27 MB

動いた!LambdaContextの中身も確認できている。
終わりに
この発表を聞いて初めてAWSの無料枠に入ったレベルだったので、今回はひとつのLambda内に閉じた実装だけ確かめた。
Goでの実装はコードひとつだけでビルドできるので、非常に簡単だった。
(正直コーディングの時間より
初回登録時の電話認証のほうが時間かかっている。)
自分はあまりクラウドに詳しくないのだが、これくらい小さく始められるのは嬉しい。CloudWatchにログ流したり、別のサービスのイベント拾ったり、少しずつ視野を広げられそう。
設定ファイルを置けばAWS CodePipelineなどを使って自動デプロイなども出来るらしいので、後日確かめてみたい。
(冒頭の
ブログに詳しく書かれている。)
Creating a Deployment Package (Go)
https://docs.aws.amazon.com/en_us/lambda/latest/dg/lambda-go-how-to-create-deployment-package.html
参考
aws/aws-lambda-go
https://github.com/aws/aws-lambda-go
GoDoc:aws/aws-lambda-go
https://godoc.org/github.com/aws/aws-lambda-go
AWS Lambda Supports Go
https://aws.amazon.com/jp/about-aws/whats-new/2018/01/aws-lambda-supports-go/
Announcing Go Support for AWS Lambda
https://aws.amazon.com/jp/blogs/compute/announcing-go-support-for-aws-lambda/
Programming Model for Authoring Lambda Functions in Go
https://docs.aws.amazon.com/en_us/lambda/latest/dg/go-programming-model.html
Creating a Deployment Package (Go)
https://docs.aws.amazon.com/en_us/lambda/latest/dg/lambda-go-how-to-create-deployment-package.html
AWS SAMを利用してGolangなLambdaをデプロイする
https://qiita.com/ikeisuke/items/3c0c422888ae8ae09831
awsのlamdaがGo言語対応したので雑にsampleを動かしてみる
https://qiita.com/ieee0824/items/5bf3f9649f2378c6f2e5
budougumi0617/sandbox-aws-lambda-go
https://github.com/budougumi0617/sandbox-aws-lambda-go