Top Banner
@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.
68

AWS Lambda in Golang

Apr 21, 2017

Download

Internet

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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?