[レポート]AWS Lambdaを用いたマイクロサービスの構築 #SVS343 #reinvent
はじめに
SVS343-R1 - Building microservices with AWS Lambdaのセッションレポートです。
[REPEAT 1] Building microservices with AWS Lambda
このセッションでは、AWSでの普遍的なマイクロサービスパターン、及びLambdaでのマイクロサービス作成について触れます。
AWSのmicroservice
AWSのサービスは数多くのマイクロサービスの上に成り立っています。例えば、Amazon S3はロンチ時に8つの異なるマイクロサービスの上に成り立っていました。2018年時点では235以上の異なるマイクロサービスの上に成り立っています。
マイクロサービスの組み合わせのパターンは数多く存在し、そのうち一つのパターンを図にすると以下のような形になります。公開された一つのインターフェイスだけのように見えますが、実体としては数多くのマイクロサービスが氷山のように水面下に存在します。
AWS Lambda
コードはイベントソースの関数のように扱われます。機能構成としては以下の通り。
- 最大3GB RAM
- 最大15分の処理時間
- 最大250MBまでのアプリケーション構成
- 最大512MBまでの一時ファイル
セキュリティ、モニタリング、ビルトインログは関数レベルでスコープされ、呼び出しと実行時間毎に請求が発生します。
Lambda API
Lambda関数はAPI経由によってのみアクセス及び実行が可能です。これはイベントAPIによる動作となるためです。API経由でLambda関数にアクセスすることは、所謂コンテナ上でのアプリケーション、例えばサイドカーやnginx等呼び出しとは少々異なります。
APIへのアクセス
Amazon API Gateway、Application Load Balancer、AWS AppSyncの異なる3つの手段があります。
Amazon API Gateway
REST APIとWebSocketの2つの異なるタイプと、新しくアナウンスしたHTTP APIがあります。
HTTP APIはREST APIを使うよりも幾分シンプルになっています。REST API以前のAPI Gatewayに比べると70%ほど安く、オーバーヘッドが50%減っています。
詳しくはSVS212、及びSVS402のレポートを参照してみてください。
Application Load Balancer
基本機能としてHTTPリクエストをLambdaに返すなど、幾つもの理由でアプリケーションに素晴らしいものとなっています。
AppSync
モバイル系サービスです。Graph QLについてはFacebookの利用や、Starbucksが使い始めたことについて聞いた人もいると思います。
Facebook’s GraphQL gets its own open-source foundation | TechCrunch
多くの異なるデータソース、データテーブル、複数の箇所からデータを取得することを1行で行うような複雑なクエリを可能にします。
AppSyncでDynamoDB、ElasticSearch、Lambda Function、RDBからデータを取得し、クライアントに同等のレスポンスを返すことができます。
APIフロントエンドサービスのチートシート
- 複数のデータソースあるいはデータに対して複雑なクエリを実行する場合
- AWS AppSync。GraphQLが業界標準として強く機能
- WebSocketを使う場合
- Amazon API Gateway。IoTアプリケーションやリアルタイムアプリケーション、チャットアプリのダッシュボードなど
- データ変換や送信の制限、利用料の抑制、柔軟な認証が必要な場合
- Amazon API Gateway
- 通常のAPI呼び出しで、潜在的に月毎の高リクエストでデータ変換が不要な場合
- Applicatoin Load Balancer
- あるいは通常のAPI呼び出しで、月毎のリクエストが数百万以下の場合
- Amazon API Gateway
認証の選択肢
- オープン
- 証明しない、あるいは委任しない
- AWS Identity And Access Management(IAM) permissions
- 権限付与にはIAMポリシーとAWS credentialsを用いる
- Amazon Cognito authorizer
- ユーザディレクトリの認証を管理する
- API Gatewayでのカスタム認証としてLambdaが使える
リクエストルートの制御地点
個々のルートは個々のLambda Functionへと返され、関数とアクション単位で実行されます。
Lambda内でとても細かくルーティングを行う場合、通常は特定言語のみで行います。この場合、フレームワークは単一のLamdba関数にて全てリクエストをプロキシします。このケースも現在上手く機能します。
Lambda内でルーティングするモデルについて
先に述べたLambdaでのルーティングモデルで、カスタマーを危険にさらしてしまう特性について。
- セキュリティ構成は全体にかかり、機能毎に設定することはできない。
- パフォーマンス設定は全体に適用され、機能毎に設定することはできない。
セキュリティとパフォーマンスについてはIAMロールやLambdaの構成にも同じことが言えます。
- 合計アプリケーションサイズは合計で250MB
- 処理時間の制約
AWS Step Functionか非同期モデルを介した外部関数でのロジックを利用する手もあります。
ルーティングをこれら2つのやり方で考えた場合
より多くのケースで使われているのはAPI Gatewayです。
- API Gateway
- API Gatewayの恩恵が得られる
- 優れたAWSツールとの互換性
- 優れたセキュリティ粒度
- 優れたパフォーマンス粒度
そしてLambdaで完結させる場合の特徴は以下の通り
- Lambda
- ネイティブのフレームワークはとても強力
- コードの移植性にてポテンシャルがある
- IAMロール、ポリシーなどのセキュリティ構成が薄い(潜在的な欠点)
- コールドスタートが少なくなるかもしれない(by Yan Cui Blog)
コールドスタートとは、リクエストを受け取ったあとにアプリケーションコードを取得して起動するまでに掛かる時間のことです。
Monitor Lambda cold start durations with CloudWatch | Lumigo
正直なところ、これらに確たる答えはありません。カスタマーからのフィードバックは限定的です。フレームワークを愛するのであれは徹底的に使えばよく、極力手を動かさずかつコード総量も減らしたいのであれば、マネージドサービスの恩恵を受けましょう。
アプリケーション通信での同期と非同期
同期アプリケーションとの通信
単純なケース。
失敗したら再試行します。
分散型、あるいはマイクロサービスでの構成は少し複雑になります。
同期方式の注文サービスを例に上げると、注文サービスから請求書のサービスが呼び出され、注文サービスへと同期適用されます。その後クライアントへ適用されます。
ただ、これはステップが膨らむだけでなく、例外の発生箇所増加とも言えます。サービス間の通信、クライアントへの通信のバックアップ等の取り扱いにも考慮が必要です。再実行箇所や、クライアントにどのタイミングで伝えるかなど、懸念事項は数多くあります。
そこでそれを避けるために非同期での構成となります。
非同期でのやり方を考える
同期及び非同期でのサービス呼び出しの違いは下図のようになります。
非同期では、クライアントは注文サービスへとアクセスしたあと、請求書サービスへとアクセスします。
SperkerのChris曰く、
The time spent to try making a process async will pay for itself in you gaining deeper understanding of what is really happening with you data.
訳:プロセスを非同期にするために費やした時間は、データで実際に起こっていることを深く理解するためのものだったのだろう
とのことです。
AWSとAmazon.comは色々な場所で同期を行っています。Amazon.comで注文が行われると、注文プロセスについての非同期処理を非常に迅速に目にすることができ、数分後にはメールを受け取ることでしょう。クレジットカードチャージ等、幾つもの非同期のシーンがあります。
クライアント側で管理させる必要のないことを非同期で行う時、フロント及びバックエンドと呼ばれているサービスを再接続させるオプションが幾つかあります。
- Amazon Simple Notfication Service (Amazon SNS)
- Amazon Simple Queue Service (Amazon SQS)
- Amazon EventBridge
- Amazon Kinesis Data Streams
これらは製品ごとに豊かな機能をもち、とてもたくさんの異なる機能で、たくさんの物事を解決することができます。
機能を比較する方法
多くの時間を通してカスタマーに接することを考える時、基本的に6つの特性に落とし込みます。
- Scale/concurrency controls
- どのようにスケールし、平行しながら作業するか
- Durability
- サービスやイベント内にあるメッセージをいかに持続させるか
- Persistence
- このケースでは、持続性と永続性は異なるものとして扱う
- Consummption models:
- PushとPull
- Retries
- 考えてみるべきこと
- Pricing
- 勿論
直近の非同期イベントソースについてのアナウンス
pre:Invent2019で告知されています。気になる方は併せて参照してください。
- SQS FIFOをLambdaの呼び出し元として使える
- SNS Dead Letter Queues (DLQs)
- Lambda Destinations (Lambdaの実行結果を元に次のアクションを起こす) 等
ICYMI: Serverless pre:Invent 2019 | AWS Compute Blog
非同期サービスを決めるチートシート
- 巨大なスループットやデータの順序に気をつける必要がある場合、ログデータやストリームを扱う場合
- Kinesis Data Streams
- 1対多あるいは少数への拡散、Lambda/HTTPへの直送信
- Amazon SNS
- 消費されるまでのバッファ要求、順番があるかどうか
- Amazon SQS
- 1対多の拡散、たくさん異なるコンシューマを対象、スキーママッチング、粒度のあるルール
- EventBridge
EventBridgeはこれら全てを対象とできる点で大きく変わります。
API304, API315, API320, SVS308, SVS317も参照してみてください。
共有機能
考慮することは数多くあります。
- シークレット/構成管理
- 簡潔なコード管理
- デバッグ/トラブルシューティング
- パフォーマンスコントロール
- セキュリティ
AWS Lambdaの環境変数
- Key-valueの組み合わせを関数に直接渡すことができる
- Node.jsのprocess.envやPythonのos.environのようなことが標準の環境変数API経由で可能
- AWS Key Management Service(AWS KMS)経由で暗号化も可能
- 情報の暗号化解除のキーへのアクセス用IAMロールの指定許可が要ります
- ステージ毎(dev,testing,prod)毎に環境変数を手軽に作れる
AWS Systems Manager - Parameter Store
構成データを管理するための集中型ストアです。
- 階層化をサポート
- 生テキストあるいはAWS KMSでの暗号化に対応
- Amazon SNS/AWS Lambdaに変更通知を送信可能
- IAMでセキュアに
- AWS CloudTrailでの記録を呼び出せる
- tag付け可能
- AWS Secrets Managerと連携可能
- API / SDKで呼び出せる
集中させた環境変数、保護管理、機能フラグが使いやすくなります。
AWS Systems Manager パラメータストア - AWS Systems Manager
サーバレスアプリケーションの解剖
Lambda Layer
コードの共有が簡単にできます。一度レイヤーをアップロードし、他の関数内で参照します。
レイヤーは依存構成やトレーニングデータ、構成ファイル等など流用可能です。疎結合となるので、ビジネスロジック作成の開発をより素早く繰り返しやすくなります。
エコシステムによりセキュアな共有がビルトインサポートされています。
Lambda Layerを使う
共通コンポーネントをZipファイルにして、Lambdaレイヤーとしてアップロードします。レイヤーは固定化され、アップデートを管理することでバージョン処理が可能です。
バージョンが削除されたあるいはパーミッションを再設定しても関数は引き続き動作しますが、削除前のものを復旧することはできません。
カスタムランタイムも含めて、5つまでのレイヤーを参照可能です。
AWS X-Ray
サーバレスアプリケーションのプロファイルとトラブルシューティングを行います。
- Lambdaは、すべての対応済み言語でかかるリクエストと、コードによる呼び出しを補足する道具です。
- API Gatewayは、レポートデータと同じようにHTTPの呼び出しにトレーシングヘッダを挿入し、X-Rayそのものへ戻します。
直近のX-RayとAmazon CloudWatchに関するアナウンス
ICYMI: Serverless pre:Invent 2019 | AWS Compute Blog
- CloudWatch ServiceLens
- カメラの単一ペインのようなモニタリングツール
- CloudWatch Synthetics
- APIと他のサービス向けにカナリアテストを生成
- CloudWatchLogsの埋め込みメトリックフォーマット
- CloudWatch Contributor Insights
- ログの普遍パターンから多く出力されているものを定義
- X-Ray Trace Maps
- 配布済みアプリケーションでも可能
- X-RayはCloudWAtch Syntheticsと連携
Lambdaの関数毎並行コントロール
- 通常は共有プールにて並行処理されます。
- 分割には関数毎の並行設定を用います。予約が必要です。
- 関数毎に最大並行設定を指定できます
- 関数の並行数を0にすることでkill switchとなります
Lambdaのパーミッションモデル
- 関数ポリシー
- リソースポリシーはクロスアカウントアクセスを受け入れる
- 同期と非同期の呼び出しに用いられる
- 実行ロール
- 関数のIAM経由でのアクセスが可能になるようにAWS resources/APIで定義する
- ストリーム呼び出しに用いられる
AWS Serverless Application Model (AWS SAM)
サーバレスに最適化されたAWS CloudFormationの拡張です。特別なサーバレスリソースタイプとして、functions, API、table, layerそしてアプリケーションがあります。AWS CloudFormationでの構成にも対応します。
Apache 2.0 準拠です。
serverless-application-model/policy_templates.json at develop · awslabs/serverless-application-model
AWS SAM Command Line Interface (AWS SAM CLI)
サーバレスアプリケーションをローカルで開発、デバッグ、テスト、デプロイ及びモニタリングするためのツールです。
API Gateway "proxy-style"とLambdaサービスAPIのテストをサポートします。ローカル環境でのオブジェクトのレスポンスと関数ログが有効になります。
brew tap aws/tap brew install aws-sam-cli
Installing the AWS SAM CLI on macOS - AWS Serverless Application Model
Lambda実行環境のタイムアウト、メモリ上限、ランタイムについて倣うには、オープンソースのdocker-lambdaイメージを使いましょう。
CloudWatch Logsから本番環境のログをtailも可能です。ネイティブな依存構成のビルドの手助けもしてくれます。
おさらい
マイクロサービスを作るにあたり、おさえておくべきLambdaの特徴は以下の通りです。
- AWS Lambdaによるサービスの限界は構成次第
- APIの作り方には大きく3つのやり方がある
- Amazon API GateWay
- ALB
- AWS AppSync
- 4つのストリーム及び非同期処理がある
- Amazon SNS
- Amazon SQS
- EventBridge
- Kinesis Data Stream
- たくさんのものを簡略化してくれるツールによるエコシステム
- X-Ray
- CloudWatch metrics & log
- AWS SAM + AWS CloudFormation
- Secrets Manager + Parameter Store
あとがき
Lambdaを用いたマイクロサービスを検討する際に、漏れやすい事項をガッチリとフォローしているセッションでした。
トーク文脈も解釈が可能な範囲にて記載していますが、言い回しや事例等である程度省略した箇所もあります。気になる方はセッション動画の視聴をおすすめします。