サーバーレスアーキテクチャのすすめ(公開版)

34
社内技術報告会 サーバーレスアーキテクチャのすすめ

Upload: keisuke-kadoyama

Post on 07-Feb-2017

462 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: サーバーレスアーキテクチャのすすめ(公開版)

社内技術報告会

サーバーレスアーキテクチャのすすめ

Page 2: サーバーレスアーキテクチャのすすめ(公開版)

サーバーレスアーキテクチャとは

Page 3: サーバーレスアーキテクチャのすすめ(公開版)

サーバーレスアーキテクチャとは

● サーバたてない

● エンジニアがサーバのことを考えたり管理する必要がない(PaaS、BaaS)● イベントドリブンでコードが動く、常にプロセスが動いているのではなく、非常駐型で

コードを動かし、そのリソース分のみ課金されるアーキテクチャ

● 決まったPaaSではなく、クラウドサービスを組み合わせて実現するDIY PaaS● 実現したい機能からインフラストラクチャが解き放たれた

● マイクロサービスと相性がいい○ マイクロサービスでは各機能を分割・モジュール化

○ 個別機能単位で独立したサーバを用意していたら管理コストが増大する

Lambdaでイベントドリブンによりコード実行が可能になり、API Gatewayで常駐型プロセ

スだったものを非常駐型に落とし込んだ

Page 4: サーバーレスアーキテクチャのすすめ(公開版)

事例

Page 5: サーバーレスアーキテクチャのすすめ(公開版)

事例のシステム構成

● 外部APIのデータを加工して表示するWEBサービス

● シングルページアプリケーション(SPA)● API Gatewayを多段構成にして各処理を抽象化

● 以降、この事例のシステム構成例を元に解説

Page 6: サーバーレスアーキテクチャのすすめ(公開版)

API Gateway

● バックエンドはLambda、Mock、リバースプロキシの3種類

フロント(js)

API Gateway(フロントエンド用)

Mock

API Gateway(バックエンド用)

API Gateway(外部API用)

リバプロ

外部API

静的なマスタ定義など

適切なバックエンドの APIへリクエストレスポンス用にデータを加工

実際にデータを取得する処理

外部APIへのリバプロヘッダやリクエストパラメータのマッピング

Page 7: サーバーレスアーキテクチャのすすめ(公開版)

API Gateway

● 認証なし、IAM、共通のAPI Key(HTTPのx-api-keyヘッダ)による認証

フロント(js)

API Gateway(フロントエンド用)

Mock

API Gateway(バックエンド用)

API Gateway(外部API用)

リバプロ

外部API

基本的に全APIがIAM認証ログインなど一部の APIは認証なし

公開しないので共通の API Key認証公開しないので共通の API Key認証

Page 8: サーバーレスアーキテクチャのすすめ(公開版)

API Gateway

● APIのまるごとクローンや、Stage機能でバージョン管理可能○ Stageごとにキャッシュ、スロットリング、変数によるパラメータなどの設定

○ フェージングによる環境の分岐も Stage機能で楽だった

フロント(js)

API Gateway(フロントエンド用)

Mock

API Gateway(バックエンド用)

API Gateway(外部API用)

リバプロ

外部API

development

staging

production

development

staging

production

development

staging

production

Page 9: サーバーレスアーキテクチャのすすめ(公開版)

API Gateway

● swaggerによるコード化、エクスポートやインポート

● そこそこの規模でLambdaと一緒に使うならフレームワークの併用を強く推奨○ 特にMapping Templateを利用する場合などはバージョン管理必須

AWS SAM※特にAPI Gatewayをリバプロで動かす場合は Mapping Templateが複雑になりやすい

Lamvery

chalice

Page 10: サーバーレスアーキテクチャのすすめ(公開版)

API Gateway

● 他社クラウドとの比較

Azure ● API Managementを2014年頃から提供● 出来ることはAPI Gatewayとよく似ているがFunctionsが実行できない

GCP● Google Cloud Endpointsを2013年頃から提供● Google App Engineがバックエンドに使用出来る● 2016年9月にApigeeを買収

Bluemix ● 2015年にStrongLoopを買収し、2016年頃からIBM API Connectを提供● loopbackというAPIフレームワークを使用して各APIを作成する

Page 11: サーバーレスアーキテクチャのすすめ(公開版)

Lambda

● ランタイムにnode.js、python、java● RequestResponseとEventの2種類の実行方法

○ API Gatewayから実行する場合はRequestResponse○ S3のアップロードをトリガーにするなどイベントドリブンで実行するときは大体 Event○ Eventはエラー終了時に最大 3回まで自動リトライ

■ 逆に言うとリトライされても大丈夫なコードを書かないとダメ

○ スケジュールをトリガーにも出来る( CloudWatch Eventsによる擬似cron)

● 従来cronで起動していたバッチにも使用○ タイムアウトは5分、LambdaからLambdaをコールすることで擬似的に伸ばせる

○ バッチの処理時間を短くするため、並列で 20Lambdaくらい動かしている

● 1年たっても無料枠が消えない(重要)○ 毎月1,000,000リクエスト分無料

Page 12: サーバーレスアーキテクチャのすすめ(公開版)

Lambda

● バージョン管理されていて、Aliasというラベルをつけることができる

フロント(js)

API Gateway(フロントエンド用)

Mock

API Gateway(バックエンド用)

API Gateway(外部API用)

リバプロ

外部API

development

staging

production

development

staging

production

CloudWatchLogsにはAlias単位ではなくLambda Function単位でLogGroupができる

環境ごとにログを見たいならLambda Function単位でわけたほうがいいかも?

Page 13: サーバーレスアーキテクチャのすすめ(公開版)

Lambda

● API GatewayのStageとLambdaのAliasをそろえることで各環境を管理

フロント(js)

API Gateway(フロントエンド用)

Mock

API Gateway(バックエンド用)

API Gateway(外部API用)

リバプロ

外部API

development

staging

production

development

staging

production

development

staging

production

development

staging

production

development

staging

production

Page 14: サーバーレスアーキテクチャのすすめ(公開版)

Lambda

● 他社クラウドとの比較

イベントドリブンでコードを動かすサーバーレスアーキテクチャ

の流れは今後加速する!!

Azure● Azure Functionsを2016年4月より提供● ランタイムをOSS化● C#やPHPもサポートする

GCP ● Google Cloud Functionsを2016年2月より提供● API GatewayなしでFunctions単体でHTTPリクエストにより起動できる

Bluemix● OpenWhiskを2016年2月より提供● ランタイムをOSS化● Bluemix上のサービスとして提供され、イベントドリブンでSwiftやDockerコンテナも動く

Page 15: サーバーレスアーキテクチャのすすめ(公開版)

認証・認可まわり

● 認証は外部APIがもつログインAPIを使用

● 認可はCognitoのカスタム認証プロバイダを使用してIAM Roleと紐付け○ 他案件ではゲストや Facebook、TwitterなんかのSNS連携での利用が多め

login.example

Page 16: サーバーレスアーキテクチャのすすめ(公開版)

認証・認可まわり

● 外部APIで認証を行い、その認証結果でCognitoからIdentityIdを発行○ こちらのシステムではCognitoで認証管理、付随するユーザデータは DynamoDBに保存

DynamoDBのキーはCognitoのIdentityIdだが、環境変わるとプライマリキーも変わるので注意

● STSで一時的なAWSのTempolary Credentialsを発行し、それを元にAPI GatewayのIAM認証を行う

外部API

②外部のログイン APIによる認証

フロント(js)

①ID/パスワードでログイン

④ログイン IDを元にCognitoからIdentityIdを発行

⑥IdentityIdをキーとしてユーザ情報とセッション IDをDynamoDBに保存

③ログイン成功後認証キー払い出し

⑦STSからTemporary Credentialsを発行

⑧ログイン後は Temporary Credentialsを使って IAM認証をクリアする(Credentialsはcookieに保存)

⑤Lambdaでセッション IDを発行する

Page 17: サーバーレスアーキテクチャのすすめ(公開版)

認証・認可まわり

● sigv4署名○ AWSのCredentialsを使ってAWSのAPIにHTTPSリクエストを送るのに必要な署名

STSでTemporary Credentialsを発行し、sigv4署名を行ったHTTPSリクエストをAPIに対して行う

○ API GatewayではSDKをダウンロードでき、この SDKがAPI GatewayへHTTPSリクエストを行う際に

sigv4署名してくれている

フロント(js)

API Gateway

SDK

● Temporary Credentials(AccessKey、SecretKey)● APIのURI、メソッド● リクエストヘッダ、リクエストパラメータ

を元にsigv4署名を行う※SDKが勝手にやってくれる

署名結果をAuthorizationヘッダに入れてHTTPSリクエストでAPIを実行

IAM認証

Page 18: サーバーレスアーキテクチャのすすめ(公開版)

認証・認可まわり

● 負荷試験○ API GatewayのAWS_IAM認証を突破するために sigv4署名を行うAPIを作った

sigv4署名用Lambda負荷試験対象の APIの、

● Temporary Credentials(AccessKey、SecretKey)● APIのURI、メソッド● リクエストヘッダ、リクエストパラメータ

をリクエストパラメータで渡すとその情報を元に sigv4署名を行う

IAM認証

認証なし

①負荷試験の最初に必要な API分sigv4署名を行う

②生成したsigv4署名を沿えて負荷試験対象の APIを叩く

外部API本来負荷試験したい API

Page 19: サーバーレスアーキテクチャのすすめ(公開版)

ログまわり

● API GatewayのログもLambdaのログもCloudWatchLogsに出力される

● CloudWachLogsはストリームで別れている○ 正直見づらい…

○ 見やすいように同じストリーム(日付とか)にすると並列での同時出力に適していない

Page 20: サーバーレスアーキテクチャのすすめ(公開版)

ログまわり

● API Gateway+Lambdaで独自のログを出力したい場合、CloudWatchLogsは適さず

KinesisやElasticSearchServiceの利用を推奨○ 事例のシステム構成では Kinesis経由でS3に保存している

● なおCloudWatchLogsはS3にエクスポート出来る

● awslogs(https://github.com/jorgebastida/awslogs)などのCLIも併用

CloudWatchLogs

同期出力

ElasticSearchService

Kinesis

非同期出力

エクスポート

Page 21: サーバーレスアーキテクチャのすすめ(公開版)

データストア

● RDS○ 外部APIから取得したデータの保管庫

● ElastiCache○ 外部APIのレスポンスをキャッシュ

○ Lambda内の計算結果をキャッシュ

● DynamoDB○ ユーザ情報、ユーザに紐づくお気に入りなどの情報を保存(不定データは JSONで保存)

○ バッチで使う時間の記録とかちょっとしたデータ

● S3○ Lambdaで生成した一時的な画像ファイルや PDFファイルを保存、S3の機能で1日で自動削除

○ バッチ連携のtsvファイルや各種ログファイルの保管

● Cognito○ ユーザを識別するユニーク IDの発行(IdentityID)

Page 22: サーバーレスアーキテクチャのすすめ(公開版)

データストア

● localStorage → 後にCookieに○ STSで生成したAWSのTempolary Credentials、ユーザのセッション IDを保存

○ IE 11でタブ間での localStorageのデータ同期が安定しない不具合

http://stackoverflow.com/questions/20565508/how-to-work-around-ie11-localstorage-events-firing-twice-or-not-at-all-in-iframe※iframeを使ったりしたけどやっぱり安定せず最終的に Cookieに変更

Page 23: サーバーレスアーキテクチャのすすめ(公開版)

Docker

● Dockerもサーバーレスアーキテクチャを構成する一要素○ コードをLambda(というコンテナ)で動かすか、 Dockerで動かすか

○ ここで言うDockerはサーバ上に自前でDockerを環境を構築するのではなく、コンテナが動くDockerのマネジメントサービスを利用する、という文脈

● 事例ではElasticBeanstalk Multi-Containerを使用○ デプロイが遅いというデメリット以外は特に不満なし

○ 環境のクローニングのしやすさ、マルチコンテナの実現しやすさ

nginx ecs-agent mackerel-agent

Page 24: サーバーレスアーキテクチャのすすめ(公開版)

ハマリポイント

Page 25: サーバーレスアーキテクチャのすすめ(公開版)

ハマリポイント1

● API Gatewayのログは見づらい、特にリバプロで使う場合は注意○ API Gateway内の全APIのログが出るので目的のログが非常に探しづらい

○ 1リクエストあたり1,024byteまでで切られる、そこそこ大きい JSONをパラメータにしていると簡単に越

えてTRUNCATEされる

● API GatewayのStageをコピーしても変数やキャッシュ設定はコピーされない、API KeyもStageごとで設定が必要

● API Gatewayでダウンロード出来るSDKはそのままだと一部の文字(RFC 3986 非予

約文字)がパラメータに使えない○ エンコードされず、 sigv4署名が失敗して常に認証失敗( 403)になる

○ javascriptで確認、iOSやAndroidは不明

○ 特に検索のフリーワードに「 !」や「*」などを入れられるケースで困る

○ SDKに手を加えることで対応

https://gist.github.com/bageljp/cfeb9e43ba513cadf8c83af488bbc6b5/revisions?diff=unified

Page 26: サーバーレスアーキテクチャのすすめ(公開版)

ハマリポイント2

● API Gatewayのタイムアウトは29秒(最近まで10秒だった)○ サポートに言っても伸ばせない

○ Lambdaのタイムアウト5分より圧倒的に短いので Lambdaの処理は29秒を意識する

○ 事例では外部APIが非同期でデータを用意していたので、 29秒以内にデータが準備されない場合は

一旦408を返してクライアント側でリトライしている

フロント(js)

API Gateway(フロントエンド用)

API Gateway(バックエンド用)

API Gateway(外部API用)

リバプロ

外部API

バックエンドから 408を受け取ったらそのまま408を返す

クライアント側で 408が返ってきたらAPIリクエストをリトライする

リバプロの結果、まだ外部 APIでデータが出来てない場合は 408を返す

Page 27: サーバーレスアーキテクチャのすすめ(公開版)

ハマリポイント3

● オンライン処理でLambdaを使用すると同時実行数が不足する可能性に注意○ デフォルト100、要サポートへ緩和申請( 2〜3営業日かかるので)

● 同じくDynamoDBのスループットも注意

Page 28: サーバーレスアーキテクチャのすすめ(公開版)

ハマリポイント4

● Lambda(Python)のクラス変数は初期化されない○ Lambdaは一度起動したらしばらく待機していて、その間に次のリクエストが来れば使い回す

○ そのためクラス変数を変更すると変更された状態で次の処理を行うため不正な値になる

http://blog.father.gedow.net/2015/12/10/aws-lambda-python-class-variable/○ クラス変数は変更しない

● DynamoDB Streams→Lambdaを試したが、重たい処理はタイムアウトする○ S3とか他サービスをトリガーに Event起動する場合全般当てはまりそう

○ 一応リトライしてくれるのでタイムアウトしてもリトライして最終的に終わればいいがなんか気持ち悪

DynamoDB

レコードの更新をトリガーにLambdaを実行

DynamoDB

3レコード更新

処理に2分くらいかかる2分 * 3レコードで6分>5分3つ目の処理がタイムアウト

{ “Records”: [ { “record A” }, { “record B” }, { “record C” } ]}

Page 29: サーバーレスアーキテクチャのすすめ(公開版)

ハマリポイント5

● CloudWatchLogsへのログ出力コードを入れた途端タイムアウト頻発○ 10秒くらいで終わるLambdaの処理が、CloudWatchLogsのAPIでログ出力するコード入れたら

5分以上かかってタイムアウト

○ 同時実行しないバッチなら利用に耐えれるが、オンライン処理は絶望的

● API GatewayへのリバプロはHTTPヘッダの書き換え or TCPでないとダメ○ ELB→nginxはTCPリスナー、nginx→API GatewayはHTTPヘッダを書き換えた

● API Gatewayで1メソッド内のHTTPレスポンスコードに200番台を複数使用すると、

SDKがダウンロード出来ない○ 一応CLIでSDKをダウンロードするとエラーメッセージが表示される、、

https://forums.aws.amazon.com/thread.jspa?threadID=230219

● 他にも地味にAWS管理コンソールから設定できない項目があったりとか、AWS管理

コンソールのUIがバグってて反映されなかったりとか

開発期間中でもサポート契約推奨!

Page 30: サーバーレスアーキテクチャのすすめ(公開版)

まとめ

Page 31: サーバーレスアーキテクチャのすすめ(公開版)

良かった点1

● 独立した機能を丸ごとエンジニアにお願いできた○ API Gatewayで動かすから、ここで動くこういう機能の Lambdaを作ってー

● お客さんがAPIを叩くのに抵抗がなかったので、運用ツールをAPIで提供して運用負

荷を軽減できた○ スケジュールで動かしている LambdaをAPI Gateway経由で外部から任意実行できるようにした

○ サイトへのお知らせ機能を API GatewayのMock機能で作成

○ メンテナンスサイトへの切り替えを APIとして提供

● サーバの有無を抜きに、実現したい機能とそれを発火するイベントを元にアーキテ

クチャを考える習慣が身につく

● サーバが減ることでインフラコスト、運用における管理コストも減る○ ただしサーバレスアーキテクチャの採用でシステムが複雑化するならその限りではない

Page 32: サーバーレスアーキテクチャのすすめ(公開版)

良かった点2

● バッチをLambdaにしたのでサーバの心配をしなくて良くなった○ データ移行など大きなオペレーションはサーバ上で Lambdaのコードを直接実行

● 各機能ごとでLambdaが分かれているので、炎上時にエンジニアを大量増員しても

conflict頻発するなどの混乱はなかった

● 負荷には強い、勝手にバックエンドでスケールしてさばいてくれる

● フロントで使っていたjavascriptのライブラリをLambdaで動かしてpythonから呼ぶみ

たいなこともした(スケジュール優先の苦肉の策)

● なおリリース翌月のAWSの料金は、、、微妙?

API Gateway $ 155.31 DynamoDB $ 64.69

Lambda $ 81.14 Data Transfer $ 45.00

CloudWatch $ 68.64 合計 $ 414.78

※何も考えずAPI Gatewayのキャッシュを有効にすると高くなる

Page 33: サーバーレスアーキテクチャのすすめ(公開版)

改善ポイント

● API Gateway+Lambdaを管理できるフレームワークを使えば良かった

● サーバはリバプロしてるだけなので、CloudFrontを使えばサーバもなくせた

学習方法

● まずはどんなものか触ってみる(チュートリアルやHello World的なの)

● 各コンポーネントで何が出来るかはBlackBeltのスライドに目を通せば大体OK

サーバーレスアーキテクチャで新しい未来を!!

ご利用は計画的に

Page 34: サーバーレスアーキテクチャのすすめ(公開版)

EOF