68
@k_nishijima AWS Lambda in Golang JAWS-UG沖縄 真夏の熱すぎるサーバレス祭り! 2016年08月 @k_nishijima The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/) The design is licensed under the Creative Commons 3.0 Attributions license.

AWS Lambda in Golang

Embed Size (px)

Citation preview

Page 1: AWS Lambda in Golang

@k_nishijima

AWS Lambda in Golang

JAWS-UG沖縄 真夏の熱すぎるサーバレス祭り! 2016年08月 @k_nishijima

The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/) The design is licensed under the Creative Commons 3.0 Attributions license.

Page 2: AWS Lambda in Golang

@k_nishijima

皆さんこんにちは! Go言語でコード書いてますか?

2

Page 3: AWS Lambda in Golang

@k_nishijima

仕事で書いてる人? 趣味で書いてる人?

書いてない人?

3

Page 4: AWS Lambda in Golang

@k_nishijima

今日は実践 「Go言語でLambda関数を書く」

をお届けします

4

Page 5: AWS Lambda in Golang

@k_nishijima

あんた誰?

5

西島 幸一郎 / にしじま こういちろうアールスリーインスティテュート ソリューションアーキテクト https://www.r3it.com大阪の会社に所属、宜野湾の自宅から100%リモートワーク

okinawa.goのコアメンバー JAWS−UG沖縄のコアメンバー ハッカーズチャンプルー実行委員長

ご質問などあればFacebook/Twitterなどでお気軽に〜♪

@k_nishijima

nishijima.koichiro

Page 6: AWS Lambda in Golang

@k_nishijima

アジェンダ

6

๏ AWSとGolangの関係をおさらい ๏ 利用ツールの紹介 ๏ 実際のLambda関数の書き方 ๏ 簡単なハンズオン

Page 7: AWS Lambda in Golang

@k_nishijima

AWSとGo言語7

Page 8: AWS Lambda in Golang

@k_nishijima

AWSとGo言語

8

๏ AWS SDK for Go あります https://aws.amazon.com/jp/sdk-for-go/

๏ 新サービスにもかなりの勢いで追随してます https://github.com/aws/aws-sdk-go

๏ ただし今のところ公式にはLambdaの対応言語ではありません 【Node.js (JavaScript)、Python、および Java (Java 8 互換)】https://aws.amazon.com/jp/lambda/faqs/

Page 9: AWS Lambda in Golang

@k_nishijima

え、じゃあどうやって LambdaをGoで書くの?

9

Page 10: AWS Lambda in Golang

@k_nishijima

利用ツールの紹介

10

Page 11: AWS Lambda in Golang

@k_nishijima

三種の神器:利用ツールの紹介

11

๏ APEX : Lambda関数のデプロイ管理http://apex.run/https://github.com/apex/apex

๏ Simple API Gateway : API Gatewayの設定 https://github.com/horike37/simple-api-gateway

๏ Terraform : インフラの管理 https://www.terraform.io/

Page 12: AWS Lambda in Golang

@k_nishijima 12

๏ Lambda関数の管理に特化したツール

๏ 環境構築はTerraformを組み合わせて使うことを想定

๏ Node.jsのshimの魔法によりGo言語の実行をサポート→このおかげでGoでLambdaが書ける!

APEX

Page 13: AWS Lambda in Golang

@k_nishijima 13

๏ 個人的にも支援中 ๏ コードで貢献したかったがGoスキルが足りず…

ひとまずお金で支援することにした(^_^;)

APEX

Page 14: AWS Lambda in Golang

@k_nishijima

Simple API Gateway

14

๏ API Gatewayの設定をCLIで行うツール

๏ マネコンの設定画面は罠が多すぎるので…API作る際にはこれを利用して作るととても楽です

Page 15: AWS Lambda in Golang

@k_nishijima

Simple API Gateway

15

๏ こっちはコードで貢献できた!

Page 16: AWS Lambda in Golang

@k_nishijima 16

๏ みんな大好きHashiCorp社謹製のインフラ管理ツール

๏ JSONライクな設定ファイルからインフラを自動生成/破棄

๏ 組み合わせとしては、IAMの権限設定やLambda以外のリソース管理に利用すると吉

Terraform

Page 17: AWS Lambda in Golang

@k_nishijima

この辺のツールを使って 実際に何かLambdaを使ってWeb APIを作ってみましょう

17

Page 18: AWS Lambda in Golang

@k_nishijima

お題

問い合わせフォームをDynamoDBに保存する

API

18

Page 19: AWS Lambda in Golang

@k_nishijima

実際には

管理者にメールしたり 送信元にメールしたり Slackに通知したり 色々やりたいけど

その辺は簡単に実装できるので各自!

19

Page 20: AWS Lambda in Golang

@k_nishijima 20

๏ https://github.com/k-nishijima/lambda-handson-jawsug-okinawa-201608

๏ infra以下にTerraformのtfファイル ๏ lambda以下にLambda関数のファイル

ソースリポジトリ

Page 21: AWS Lambda in Golang

@k_nishijima 21

๏ Terraformで作られたAWSの環境(IAMロール、DynamoDB) ๏ API GatewayでホストされるWeb API ๏ Goで書かれたLambda関数(APEXでデプロイ) ๏ Goで書かれたコアライブラリ(AWSリソースを利用する実体)

全体構成

Goで書かれたLambdaSimple API Gatewayで設定

HTTPリクエスト Lambdaで動いてるところにAPI GatewayでHTTP経由で呼び出すインターフェイス

をつけるイメージ

Page 22: AWS Lambda in Golang

@k_nishijima

実際の開発の流れ

22

1. Terraform でDB環境・IAM実行権限などを設定 2. Goでコーディング、テスト 3. APEXでLambda関数としてデプロイ 4. Simple API GatewayでAPI作成、デプロイ(はじめの1回だけ) 5. APIを叩いてテスト。OK?

問題があれば、2と3と5をぐるぐる繰り返す…

Page 23: AWS Lambda in Golang

@k_nishijima 23

๏ インストールはhttps://www.terraform.io/intro/getting-started/install.html

๏ リポジトリのinfraディレクトリのREADME.mdを確認の上、“terraform apply"

๏ DynamoDBのテーブルとIAM Roleが作られる

Terraformで環境構築

Page 24: AWS Lambda in Golang

@k_nishijima

さあGoでコーディング

24

๏ その前に!プロジェクト構成をどうすべきか考える必要がある。

๏ 自分の場合は、GOPATH配下にコアライブラリを置き、Lambda関数側からはそれを呼ぶ、という形にした。ベストかどうかは分からんです・・・教えて偉い人!

Page 25: AWS Lambda in Golang

@k_nishijima

プロジェクト構成(例)

25

コアライブラリ: ~/gopath/src/github.com/k-nishijima/lambda-handson

APEX管理配下のLambda関数:

~/lambda-handson/functions/funcname/

importして使う

๏ コアライブラリはそれだけで単体テスト ๏ APEX管理配下の関数からimportして利用

Page 26: AWS Lambda in Golang

@k_nishijima

この構成のメリット

26

๏ コアライブラリ側の、通常のGo言語のコーディング・デバッグでほとんど作業は完結する(Lambda関数としてのデバッグはほぼ不要)

๏ AWSのサービスを呼び出すものもローカルで完結 ๏ DynamoDB local、GoAws(未使用だけどSNS/SQSエミュレータ)

Page 27: AWS Lambda in Golang

@k_nishijima

コアライブラリのコーディング、テスト

27

๏ https://github.com/k-nishijima/lambda-handson-golang-201608/blob/master/dao.go

๏ 普通にGoでAWSを利用するコーディング(制約はさておき、Lambdaから呼ばれるからといって特殊なコーディングはない)

๏ HTTPリクエストを構造体経由で受け取る想定で書くと良い

Page 28: AWS Lambda in Golang

@k_nishijima

コアライブラリのコーディング、テスト

28

๏ 構造体はJSONとvalidateのアノテーションに注目

๏ AWSの権限を取る部分をProfile指定とロール指定

の両対応にしておくと後で便利 (svcメソッドの部分)

Page 29: AWS Lambda in Golang

@k_nishijima

コアライブラリのコーディング、テスト

29

๏ テストが終わったら、”go install” しておく※これでAPEX管理下のLambdaから呼び出す準備が整う

๏ コアライブラリを改修したら 再度go installをお忘れなく

Page 30: AWS Lambda in Golang

@k_nishijima 30

やっと本題(?)

GoでLambda関数を書く

Page 31: AWS Lambda in Golang

@k_nishijima

APEXでプロジェクトひな形作成

31

๏ $ apex -p lambda-handson-201608 init でプロジェクト雛形作成(-pはプロジェクトを作るときに使うAWS profile名)。

๏ Lambda関数の実行用ロールなんかも作ってくれる (が、今回はTerraformで作ったロールを使う)

Page 32: AWS Lambda in Golang

@k_nishijima

APEXでプロジェクトひな形作成

32

├── functions │   └── hello │   └── index.js └── project.json

── 関数ディレクトリ ── ディレクトリ名が関数名suffix ── 実装 ── プロジェクト全体の設定ファイル

๏ Node.jsならそのままindex.jsをいじっていけばhello関数が出来上がる(が、今回は削除する)

Page 33: AWS Lambda in Golang

@k_nishijima

project.json重要

33

๏ project.jsonはプロジェクト全体の設定ファイル

๏ name: 各関数のprefixになる ๏ メモリ量とかタイムアウトとかここで書ける

๏ Lambda関数実行時のroleもここで指定 ๏ 同じような書式で関数ごとの設定もfunction.jsonで可

Page 34: AWS Lambda in Golang

@k_nishijima

GoでLambda関数作成時の注意点

34

๏ APEXではSTDINとSTDOUTをNodeとGo言語のやり取りに使うので、例えばロギングなどは必ずSTDERRに出力しないといけない。 os.Stderr.WriteString(“hoge”) みたいな

Page 35: AWS Lambda in Golang

@k_nishijima

実際のソース: イベントから構造体への変換

35

func main() { apex.HandleFunc(func(event json.RawMessage, ctx *apex.Context) (interface{}, error) { // リクエストを格納する構造体 var request lambdaHandson.AddValueRequest if err := json.Unmarshal(event, &request); err != nil { return nil, err }

Page 36: AWS Lambda in Golang

@k_nishijima

実際のソース: json.Unmarshalするときに、JSONアノテーションが効く

36

type AddValueRequest struct { Stage string `json:"stage" valid:"required"` Email string `json:"email" valid:"email,length(1|512),required"` Message string `json:"message" valid:"length(1|1024),required"` }

{ "stage": "dev", "email": "[email protected]", "message": "hello golang"}

まあunmarshalだけなら アノテーション書かなくても

大丈夫だけど・・・

JSONをレスポンスするときアノテーション重要

リクエストのJSON

Page 37: AWS Lambda in Golang

@k_nishijima

実際のソース: validateはgovalidatorを使ってみました

37

type AddValueRequest struct { Stage string `json:"stage" valid:"required"` Email string `json:"email" valid:"email,length(1|512),required"` Message string `json:"message" valid:"length(1|1024),required"` }

๏ https://github.com/asaskevich/govalidator

๏ 他にも同種の便利なパッケージはあると思うので探してみて!

Page 38: AWS Lambda in Golang

@k_nishijima

実際のソース: 実行したいメソッドを呼ぶ

38

err = dao.Put(request) if err != nil { return nil, err }

๏ Lambda関数側はほぼ定形的なコーディングとするように仕向け、可能な限りシンプルにしておく

๏ Lambda上にロジックやら条件分岐やらを書き出すと・・・(^_^;)

Page 39: AWS Lambda in Golang

@k_nishijima

Lambda環境で動かす時のTIPS:必要な権限の取り方

39

๏ LambdaはIAM Roleを使って動くので、権限はAccessKeyなどを 指定などする必要はない= 「Profile指定とロール指定の両対応にしておくと便利」の件

๏ このコードの実装では、Lambda関数が読む設定ファイルから、 Profileの指定を削除しておけばOK

Page 40: AWS Lambda in Golang

@k_nishijima

ダメ・ゼッタイ(^^;

40

Page 41: AWS Lambda in Golang

@k_nishijima 41

$ apex -p lambda-handson-201608 deploy contact

๏ これで contact関数をデプロイ。コードを修正してテストを通したらデプロイ、そして確認。これを何度も繰り返す。

๏ これをマネコンのGUIでやってたら死んじゃいます(^_^;)

APEXでデプロイ

Page 42: AWS Lambda in Golang

@k_nishijima

APEXでデプロイ

42

関数名がproject.jsonのname + functionディレクトリ名になっているのが分かる

Page 43: AWS Lambda in Golang

@k_nishijima

APEXでLambda関数実行

43

$ apex -p lambda-handson-201608 invoke contact < request_contact.json

๏ JSONファイルを引数としてcontact関数をinvoke。 上手く動けばレスポンスが返ってくる。

Page 44: AWS Lambda in Golang

@k_nishijima

今回はDynamoDBの中身を見る関数を作ってないので

44

๏ 手動でマネージメントコンソールからDynamoDBの中身を見てください(^_^;)

๏ コアライブラリにGetItemsというメソッドを付けておきましたので、データ取得APIもすぐ出来ると思います!

Page 45: AWS Lambda in Golang

@k_nishijima

APEXで実行時ログを見る

45

$ apex -p lambda-handson-201608 logs contact

๏ 動かなかったりした時はログをチェック

Page 46: AWS Lambda in Golang

@k_nishijima 46

以上です!

Page 47: AWS Lambda in Golang

@k_nishijima

ここまでで

47

๏ Goで書いた自前のライブラリを利用する、Goで書かれたLambda関数が動くようになりました。

๏ このような関数を例えばスケジューリング実行やS3のイベントに反応して実行するようにすれば、実務にもそのまま使えます。

Page 48: AWS Lambda in Golang

@k_nishijima

だがしかし まだWeb APIになってない><

Lambda関数はそのままではHTTPS経由で呼べない…

48

Page 49: AWS Lambda in Golang

@k_nishijima

ここで

API Gateway

の登場です

49

Page 50: AWS Lambda in Golang

@k_nishijima

Web APIになれば ブラウザから普通に叩ける。

HTMLだけホストしておけば大丈夫になる!

50

Page 51: AWS Lambda in Golang

@k_nishijima

Simple API GatewayでAPI作成

51

๏ インストールは“npm install -g simple-api-gateway”

๏ ES6のコードなのでNodeは4以上、勿論AWS CLIも必要です。詳しくはhttps://github.com/horike37/simple-api-gateway

Page 52: AWS Lambda in Golang

@k_nishijima

Simple API GatewayでAPI作成

52

Page 53: AWS Lambda in Golang

@k_nishijima

実際作ってみる

53

๏ POST /contactにリクエスト投げると ๏ Lambdaが呼ばれてよろしく処理される ๏ そんなAPIを作りましょう

Page 54: AWS Lambda in Golang

@k_nishijima

利用するAWSの権限の設定は?

54

๏ https://github.com/horike37/simple-api-gateway/issues/5

๏ コントリビュートチャンス!!お待ち申し上げております(^_^;)

Page 55: AWS Lambda in Golang

@k_nishijima

実際作ってみる

55

west-mbp:lambda-handson-jawsug-okinawa-201608 nishijima$ apigw create ? Please select Region for API Gatway ap-northeast-1 ? Please input API Name Handson API API Create Success!! Please action `apigw edit` and set up API

Page 56: AWS Lambda in Golang

@k_nishijima

実際作ってみる

56

west-mbp:lambda-handson-jawsug-okinawa-201608 nishijima$ apigw edit ? Please select Region for API Gatway ap-northeast-1 ? Please select API Handson API

? Do you want to use an existing Resources on Handson APIor create a new one? Create A New Resouce

? Please select parent Resource / ? Please input Resouce Path contact

? Please select method POST ? Please select backend lambda function lambda-handson-jawsug-okinawa-201608_contact

? May I set enable CORS? Yes ? Set up mapping template? (y/N) y で、エディタが開くのでマッピングテンプレートを入れて? Please edit mapping template Received

? May I create the API? Yes Create Success!! Resource and Method on Handson API API.

Page 57: AWS Lambda in Golang

@k_nishijima

マッピングテンプレートって何?

57

๏ Integration Requestに指定できる、URLパラメータ/パスパラメータ/HTTPヘッダなどをLambda関数のコードに渡すためのテンプレート

๏ 想定するURLパラメータとともに、APIGWのステージやHTTPヘッダなどをLambda関数に渡すことが出来る

Page 58: AWS Lambda in Golang

@k_nishijima

APIを作ったら、ステージ名をつけてデプロイ

58

west-mbp:lambda-handson-jawsug-okinawa-201608 nishijima$ apigw deploy ? Please select Region for API Gatway ap-northeast-1 ? Please select API Handson API ? Please input Stage Name dev Deploy success! Endpoint:https://あなたの.execute-api.ap-northeast-1.amazonaws.com/dev

๏ これでステージ「dev」のAPI完成。ステージ = 環境と言い換えてもOK。 ๏ ステージごとURLが発行されるので、まったく別の環境として利用可能。 ๏ Lambdaのエイリアスと連動したり、このコードの例のように環境変数と

して扱ってプログラムの動作を切り替えたり、いろいろ利用できます。

Page 59: AWS Lambda in Golang

@k_nishijima

呼び出してみる

59

$ curl -H "Content-Type: application/json" -X POST -d "[email protected]&message=hello world via curl" https://あなたのURL.execute-api.ap-northeast-1.amazonaws.com/dev/contact "ok"

Page 60: AWS Lambda in Golang

@k_nishijima 60

出来た!?

Page 61: AWS Lambda in Golang

@k_nishijima

はじめに戻って:サーバレスアーキテクチャとは?

61

๏ Q: 開発は楽になった? ๏ A: 1関数の責任範囲がとても狭くなるので、相対的に楽にな

る。デバッグも楽。また、とにかく繰り返しになるデプロイが楽なのがいい。

Page 62: AWS Lambda in Golang

@k_nishijima

はじめに戻って:サーバレスアーキテクチャとは?

62

๏ Q: スケールする感じする? ๏ A: 極力ステートレスな実装にして、バックエンドのデータ

ソースも速度で詰まらないDynamoDBなどを活用すれば、スケールしないほうがおかしい

Page 63: AWS Lambda in Golang

@k_nishijima

セッションとか クライアント側の状態管理は!?

63

๏ 何を言っとるんですか、時代は21世紀ですよ。そんなものはありません(建前

๏ JavaScriptでAWS SigV4を実装した話を聞きたいですか、

そうですか(イラネw

Page 64: AWS Lambda in Golang

@k_nishijima

おや、こんなのも…

64

๏ A Go framework for AWS Lambda microservices http://gosparta.io/

๏ 誰か試してLTしてくださいな(^^)/

Page 65: AWS Lambda in Golang

@k_nishijima

まとめ

65

๏ AWS SDK for Go があるのでAWSリソースを使ったLambdaを書くのはとても簡単

Page 66: AWS Lambda in Golang

@k_nishijima

まとめ

66

๏ Goは非常にパワフルな言語なので、生産性高くサクサクLambda関数が書ける

Page 67: AWS Lambda in Golang

@k_nishijima

まとめ

67

๏ きっとAWS CLIがGoでリライトされる未来が来る!(来ないかもw ๏ それはどうでもいいとして(^_^;)

現状でまったく不満はないですが、公式にLambdaでサポートされると更に嬉しいですね!

Page 68: AWS Lambda in Golang

@k_nishijima 68

Thank you so much!Any questions?