View
1.414
Download
2
Category
Preview:
Citation preview
@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.
@k_nishijima
皆さんこんにちは! Go言語でコード書いてますか?
2
@k_nishijima
仕事で書いてる人? 趣味で書いてる人?
書いてない人?
3
@k_nishijima
今日は実践 「Go言語でLambda関数を書く」
をお届けします
4
@k_nishijima
あんた誰?
5
西島 幸一郎 / にしじま こういちろうアールスリーインスティテュート ソリューションアーキテクト https://www.r3it.com大阪の会社に所属、宜野湾の自宅から100%リモートワーク
okinawa.goのコアメンバー JAWS−UG沖縄のコアメンバー ハッカーズチャンプルー実行委員長
ご質問などあればFacebook/Twitterなどでお気軽に〜♪
@k_nishijima
nishijima.koichiro
@k_nishijima
アジェンダ
6
๏ AWSとGolangの関係をおさらい ๏ 利用ツールの紹介 ๏ 実際のLambda関数の書き方 ๏ 簡単なハンズオン
@k_nishijima
AWSとGo言語7
@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/
@k_nishijima
え、じゃあどうやって LambdaをGoで書くの?
9
@k_nishijima
利用ツールの紹介
10
@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/
@k_nishijima 12
๏ Lambda関数の管理に特化したツール
๏ 環境構築はTerraformを組み合わせて使うことを想定
๏ Node.jsのshimの魔法によりGo言語の実行をサポート→このおかげでGoでLambdaが書ける!
APEX
@k_nishijima 13
๏ 個人的にも支援中 ๏ コードで貢献したかったがGoスキルが足りず…
ひとまずお金で支援することにした(^_^;)
APEX
@k_nishijima
Simple API Gateway
14
๏ API Gatewayの設定をCLIで行うツール
๏ マネコンの設定画面は罠が多すぎるので…API作る際にはこれを利用して作るととても楽です
@k_nishijima
Simple API Gateway
15
๏ こっちはコードで貢献できた!
@k_nishijima 16
๏ みんな大好きHashiCorp社謹製のインフラ管理ツール
๏ JSONライクな設定ファイルからインフラを自動生成/破棄
๏ 組み合わせとしては、IAMの権限設定やLambda以外のリソース管理に利用すると吉
Terraform
@k_nishijima
この辺のツールを使って 実際に何かLambdaを使ってWeb APIを作ってみましょう
17
@k_nishijima
お題
問い合わせフォームをDynamoDBに保存する
API
18
@k_nishijima
実際には
管理者にメールしたり 送信元にメールしたり Slackに通知したり 色々やりたいけど
その辺は簡単に実装できるので各自!
19
@k_nishijima 20
๏ https://github.com/k-nishijima/lambda-handson-jawsug-okinawa-201608
๏ infra以下にTerraformのtfファイル ๏ lambda以下にLambda関数のファイル
ソースリポジトリ
@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経由で呼び出すインターフェイス
をつけるイメージ
@k_nishijima
実際の開発の流れ
22
1. Terraform でDB環境・IAM実行権限などを設定 2. Goでコーディング、テスト 3. APEXでLambda関数としてデプロイ 4. Simple API GatewayでAPI作成、デプロイ(はじめの1回だけ) 5. APIを叩いてテスト。OK?
問題があれば、2と3と5をぐるぐる繰り返す…
@k_nishijima 23
๏ インストールはhttps://www.terraform.io/intro/getting-started/install.html
๏ リポジトリのinfraディレクトリのREADME.mdを確認の上、“terraform apply"
๏ DynamoDBのテーブルとIAM Roleが作られる
Terraformで環境構築
@k_nishijima
さあGoでコーディング
24
๏ その前に!プロジェクト構成をどうすべきか考える必要がある。
๏ 自分の場合は、GOPATH配下にコアライブラリを置き、Lambda関数側からはそれを呼ぶ、という形にした。ベストかどうかは分からんです・・・教えて偉い人!
@k_nishijima
プロジェクト構成(例)
25
コアライブラリ: ~/gopath/src/github.com/k-nishijima/lambda-handson
APEX管理配下のLambda関数:
~/lambda-handson/functions/funcname/
importして使う
๏ コアライブラリはそれだけで単体テスト ๏ APEX管理配下の関数からimportして利用
@k_nishijima
この構成のメリット
26
๏ コアライブラリ側の、通常のGo言語のコーディング・デバッグでほとんど作業は完結する(Lambda関数としてのデバッグはほぼ不要)
๏ AWSのサービスを呼び出すものもローカルで完結 ๏ DynamoDB local、GoAws(未使用だけどSNS/SQSエミュレータ)
@k_nishijima
コアライブラリのコーディング、テスト
27
๏ https://github.com/k-nishijima/lambda-handson-golang-201608/blob/master/dao.go
๏ 普通にGoでAWSを利用するコーディング(制約はさておき、Lambdaから呼ばれるからといって特殊なコーディングはない)
๏ HTTPリクエストを構造体経由で受け取る想定で書くと良い
@k_nishijima
コアライブラリのコーディング、テスト
28
๏ 構造体はJSONとvalidateのアノテーションに注目
๏ AWSの権限を取る部分をProfile指定とロール指定
の両対応にしておくと後で便利 (svcメソッドの部分)
@k_nishijima
コアライブラリのコーディング、テスト
29
๏ テストが終わったら、”go install” しておく※これでAPEX管理下のLambdaから呼び出す準備が整う
๏ コアライブラリを改修したら 再度go installをお忘れなく
@k_nishijima 30
やっと本題(?)
GoでLambda関数を書く
@k_nishijima
APEXでプロジェクトひな形作成
31
๏ $ apex -p lambda-handson-201608 init でプロジェクト雛形作成(-pはプロジェクトを作るときに使うAWS profile名)。
๏ Lambda関数の実行用ロールなんかも作ってくれる (が、今回はTerraformで作ったロールを使う)
@k_nishijima
APEXでプロジェクトひな形作成
32
├── functions │ └── hello │ └── index.js └── project.json
── 関数ディレクトリ ── ディレクトリ名が関数名suffix ── 実装 ── プロジェクト全体の設定ファイル
๏ Node.jsならそのままindex.jsをいじっていけばhello関数が出来上がる(が、今回は削除する)
@k_nishijima
project.json重要
33
๏ project.jsonはプロジェクト全体の設定ファイル
๏ name: 各関数のprefixになる ๏ メモリ量とかタイムアウトとかここで書ける
๏ Lambda関数実行時のroleもここで指定 ๏ 同じような書式で関数ごとの設定もfunction.jsonで可
@k_nishijima
GoでLambda関数作成時の注意点
34
๏ APEXではSTDINとSTDOUTをNodeとGo言語のやり取りに使うので、例えばロギングなどは必ずSTDERRに出力しないといけない。 os.Stderr.WriteString(“hoge”) みたいな
@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 }
@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": "foo@bar.com", "message": "hello golang"}
まあunmarshalだけなら アノテーション書かなくても
大丈夫だけど・・・
JSONをレスポンスするときアノテーション重要
リクエストのJSON
@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
๏ 他にも同種の便利なパッケージはあると思うので探してみて!
@k_nishijima
実際のソース: 実行したいメソッドを呼ぶ
38
err = dao.Put(request) if err != nil { return nil, err }
๏ Lambda関数側はほぼ定形的なコーディングとするように仕向け、可能な限りシンプルにしておく
๏ Lambda上にロジックやら条件分岐やらを書き出すと・・・(^_^;)
@k_nishijima
Lambda環境で動かす時のTIPS:必要な権限の取り方
39
๏ LambdaはIAM Roleを使って動くので、権限はAccessKeyなどを 指定などする必要はない= 「Profile指定とロール指定の両対応にしておくと便利」の件
๏ このコードの実装では、Lambda関数が読む設定ファイルから、 Profileの指定を削除しておけばOK
@k_nishijima
ダメ・ゼッタイ(^^;
40
@k_nishijima 41
$ apex -p lambda-handson-201608 deploy contact
๏ これで contact関数をデプロイ。コードを修正してテストを通したらデプロイ、そして確認。これを何度も繰り返す。
๏ これをマネコンのGUIでやってたら死んじゃいます(^_^;)
APEXでデプロイ
@k_nishijima
APEXでデプロイ
42
関数名がproject.jsonのname + functionディレクトリ名になっているのが分かる
@k_nishijima
APEXでLambda関数実行
43
$ apex -p lambda-handson-201608 invoke contact < request_contact.json
๏ JSONファイルを引数としてcontact関数をinvoke。 上手く動けばレスポンスが返ってくる。
@k_nishijima
今回はDynamoDBの中身を見る関数を作ってないので
44
๏ 手動でマネージメントコンソールからDynamoDBの中身を見てください(^_^;)
๏ コアライブラリにGetItemsというメソッドを付けておきましたので、データ取得APIもすぐ出来ると思います!
@k_nishijima
APEXで実行時ログを見る
45
$ apex -p lambda-handson-201608 logs contact
๏ 動かなかったりした時はログをチェック
@k_nishijima 46
以上です!
@k_nishijima
ここまでで
47
๏ Goで書いた自前のライブラリを利用する、Goで書かれたLambda関数が動くようになりました。
๏ このような関数を例えばスケジューリング実行やS3のイベントに反応して実行するようにすれば、実務にもそのまま使えます。
@k_nishijima
だがしかし まだWeb APIになってない><
Lambda関数はそのままではHTTPS経由で呼べない…
48
@k_nishijima
ここで
API Gateway
の登場です
49
@k_nishijima
Web APIになれば ブラウザから普通に叩ける。
HTMLだけホストしておけば大丈夫になる!
50
@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
@k_nishijima
Simple API GatewayでAPI作成
52
@k_nishijima
実際作ってみる
53
๏ POST /contactにリクエスト投げると ๏ Lambdaが呼ばれてよろしく処理される ๏ そんなAPIを作りましょう
@k_nishijima
利用するAWSの権限の設定は?
54
๏ https://github.com/horike37/simple-api-gateway/issues/5
๏ コントリビュートチャンス!!お待ち申し上げております(^_^;)
@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
@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.
@k_nishijima
マッピングテンプレートって何?
57
๏ Integration Requestに指定できる、URLパラメータ/パスパラメータ/HTTPヘッダなどをLambda関数のコードに渡すためのテンプレート
๏ 想定するURLパラメータとともに、APIGWのステージやHTTPヘッダなどをLambda関数に渡すことが出来る
@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のエイリアスと連動したり、このコードの例のように環境変数と
して扱ってプログラムの動作を切り替えたり、いろいろ利用できます。
@k_nishijima
呼び出してみる
59
$ curl -H "Content-Type: application/json" -X POST -d "email=curl@foo.com&message=hello world via curl" https://あなたのURL.execute-api.ap-northeast-1.amazonaws.com/dev/contact "ok"
@k_nishijima 60
出来た!?
@k_nishijima
はじめに戻って:サーバレスアーキテクチャとは?
61
๏ Q: 開発は楽になった? ๏ A: 1関数の責任範囲がとても狭くなるので、相対的に楽にな
る。デバッグも楽。また、とにかく繰り返しになるデプロイが楽なのがいい。
@k_nishijima
はじめに戻って:サーバレスアーキテクチャとは?
62
๏ Q: スケールする感じする? ๏ A: 極力ステートレスな実装にして、バックエンドのデータ
ソースも速度で詰まらないDynamoDBなどを活用すれば、スケールしないほうがおかしい
@k_nishijima
セッションとか クライアント側の状態管理は!?
63
๏ 何を言っとるんですか、時代は21世紀ですよ。そんなものはありません(建前
๏ JavaScriptでAWS SigV4を実装した話を聞きたいですか、
そうですか(イラネw
@k_nishijima
おや、こんなのも…
64
๏ A Go framework for AWS Lambda microservices http://gosparta.io/
๏ 誰か試してLTしてくださいな(^^)/
@k_nishijima
まとめ
65
๏ AWS SDK for Go があるのでAWSリソースを使ったLambdaを書くのはとても簡単
@k_nishijima
まとめ
66
๏ Goは非常にパワフルな言語なので、生産性高くサクサクLambda関数が書ける
@k_nishijima
まとめ
67
๏ きっとAWS CLIがGoでリライトされる未来が来る!(来ないかもw ๏ それはどうでもいいとして(^_^;)
現状でまったく不満はないですが、公式にLambdaでサポートされると更に嬉しいですね!
@k_nishijima 68
Thank you so much!Any questions?
Recommended