Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

3,121 views

Published on

2016年7月に行った社内勉強会のスライド資料(公開版)です。
サーバーレスアーキテクチャで作ったシステムを具体例に話をしました。

Published in: Technology
  • Be the first to comment

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

  1. 1. 社内技術報告会 サーバーレスアーキテクチャのすすめ
  2. 2. サーバーレスアーキテクチャとは
  3. 3. サーバーレスアーキテクチャとは ● サーバたてない ● エンジニアがサーバのことを考えたり管理する必要がない(PaaS、BaaS) ● イベントドリブンでコードが動く、常にプロセスが動いているのではなく、非常駐型で コードを動かし、そのリソース分のみ課金されるアーキテクチャ ● 決まったPaaSではなく、クラウドサービスを組み合わせて実現するDIY PaaS ● 実現したい機能からインフラストラクチャが解き放たれた ● マイクロサービスと相性がいい ○ マイクロサービスでは各機能を分割・モジュール化 ○ 個別機能単位で独立したサーバを用意していたら管理コストが増大する Lambdaでイベントドリブンによりコード実行が可能になり、API Gatewayで常駐型プロセ スだったものを非常駐型に落とし込んだ
  4. 4. 事例
  5. 5. 事例のシステム構成 ● 外部APIのデータを加工して表示するWEBサービス ● シングルページアプリケーション(SPA) ● API Gatewayを多段構成にして各処理を抽象化 ● 以降、この事例のシステム構成例を元に解説
  6. 6. API Gateway ● バックエンドはLambda、Mock、リバースプロキシの3種類 フロント (js) API Gateway (フロントエンド用) Mock API Gateway (バックエンド用) API Gateway (外部API用) リバプロ 外部API 静的なマスタ定義など 適切なバックエンドの APIへリクエスト レスポンス用にデータを加工 実際にデータを取得する処理 外部APIへのリバプロ ヘッダやリクエストパラメータのマッピング
  7. 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認証
  8. 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
  9. 9. API Gateway ● swaggerによるコード化、エクスポートやインポート ● そこそこの規模でLambdaと一緒に使うならフレームワークの併用を強く推奨 ○ 特にMapping Templateを利用する場合などはバージョン管理必須 AWS SAM ※特にAPI Gatewayをリバプロで動かす場合は Mapping Templateが複雑になりやすい Lamvery chalice
  10. 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を作成する
  11. 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リクエスト分無料
  12. 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単位でわけたほうがいいかも?
  13. 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
  14. 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コンテナも動く
  15. 15. 認証・認可まわり ● 認証は外部APIがもつログインAPIを使用 ● 認可はCognitoのカスタム認証プロバイダを使用してIAM Roleと紐付け ○ 他案件ではゲストや Facebook、TwitterなんかのSNS連携での利用が多め login.example
  16. 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を発行する
  17. 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認証
  18. 18. 認証・認可まわり ● 負荷試験 ○ API GatewayのAWS_IAM認証を突破するために sigv4署名を行うAPIを作った sigv4署名用Lambda 負荷試験対象の APIの、 ● Temporary Credentials(AccessKey、SecretKey) ● APIのURI、メソッド ● リクエストヘッダ、リクエストパラメータ をリクエストパラメータで渡すとその情報を元に sigv4署名を行う IAM認証 認証なし ①負荷試験の最初に必要な API分sigv4署名を行う ②生成したsigv4署名を沿えて負荷試験対象の APIを叩く 外部API 本来負荷試験したい API
  19. 19. ログまわり ● API GatewayのログもLambdaのログもCloudWatchLogsに出力される ● CloudWachLogsはストリームで別れている ○ 正直見づらい… ○ 見やすいように同じストリーム(日付とか)にすると並列での同時出力に適していない
  20. 20. ログまわり ● API Gateway+Lambdaで独自のログを出力したい場合、CloudWatchLogsは適さず KinesisやElasticSearchServiceの利用を推奨 ○ 事例のシステム構成では Kinesis経由でS3に保存している ● なおCloudWatchLogsはS3にエクスポート出来る ● awslogs(https://github.com/jorgebastida/awslogs)などのCLIも併用 CloudWatchLogs 同期出力 ElasticSearchService Kinesis 非同期出力 エクスポート
  21. 21. データストア ● RDS ○ 外部APIから取得したデータの保管庫 ● ElastiCache ○ 外部APIのレスポンスをキャッシュ ○ Lambda内の計算結果をキャッシュ ● DynamoDB ○ ユーザ情報、ユーザに紐づくお気に入りなどの情報を保存(不定データは JSONで保存) ○ バッチで使う時間の記録とかちょっとしたデータ ● S3 ○ Lambdaで生成した一時的な画像ファイルや PDFファイルを保存、S3の機能で1日で自動削除 ○ バッチ連携のtsvファイルや各種ログファイルの保管 ● Cognito ○ ユーザを識別するユニーク IDの発行(IdentityID)
  22. 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に変更
  23. 23. Docker ● Dockerもサーバーレスアーキテクチャを構成する一要素 ○ コードをLambda(というコンテナ)で動かすか、 Dockerで動かすか ○ ここで言うDockerはサーバ上に自前でDockerを環境を構築するのではなく、コンテナが動くDocker のマネジメントサービスを利用 する、という文脈 ● 事例ではElasticBeanstalk Multi-Containerを使用 ○ デプロイが遅いというデメリット以外は特に不満なし ○ 環境のクローニングのしやすさ、マルチコンテナの実現しやすさ nginx ecs-agent mackerel-agent
  24. 24. ハマリポイント
  25. 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
  26. 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を返す
  27. 27. ハマリポイント3 ● オンライン処理でLambdaを使用すると同時実行数が不足する可能性に注意 ○ デフォルト100、要サポートへ緩和申請( 2〜3営業日かかるので) ● 同じくDynamoDBのスループットも注意
  28. 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” } ] }
  29. 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がバグってて反映されなかったりとか 開発期間中でもサポート契約推奨!
  30. 30. まとめ
  31. 31. 良かった点1 ● 独立した機能を丸ごとエンジニアにお願いできた ○ API Gatewayで動かすから、ここで動くこういう機能の Lambdaを作ってー ● お客さんがAPIを叩くのに抵抗がなかったので、運用ツールをAPIで提供して運用負 荷を軽減できた ○ スケジュールで動かしている LambdaをAPI Gateway経由で外部から任意実行できるようにした ○ サイトへのお知らせ機能を API GatewayのMock機能で作成 ○ メンテナンスサイトへの切り替えを APIとして提供 ● サーバの有無を抜きに、実現したい機能とそれを発火するイベントを元にアーキテ クチャを考える習慣が身につく ● サーバが減ることでインフラコスト、運用における管理コストも減る ○ ただしサーバレスアーキテクチャの採用でシステムが複雑化するならその限りではない
  32. 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のキャッシュを有効にすると高くなる
  33. 33. 改善ポイント ● API Gateway+Lambdaを管理できるフレームワークを使えば良かった ● サーバはリバプロしてるだけなので、CloudFrontを使えばサーバもなくせた 学習方法 ● まずはどんなものか触ってみる(チュートリアルやHello World的なの) ● 各コンポーネントで何が出来るかはBlackBeltのスライドに目を通せば大体OK サーバーレスアーキテクチャで新しい未来を!! ご利用は計画的に
  34. 34. EOF

×