サーバーレスのシステムではサーバーが姿を消し、それとともにアーキテクチャ図のいつもの形も消えます。代わりに重要になるのは、各関数が何によってトリガーされるのか、失敗したときに何が起きるのか、そしてどのイベントがシステムのある部分を次の部分へつないでいるのかです。Lambda のボックスを 20 個並べてトリガーを 1 つも描いていない図は、完成しているように見えて何も説明していません。
このガイドでは、新しく入ったメンバーでも追える AWS のサーバーレス構成図の描き方を紹介します。取り上げるのは、1 つの実例、呼び出しタイプと失敗時の経路の表記法、そしてこの種の図を誤解のもとにしてしまう間違いです。
各関数がどう呼び出されるかから始める
図に載る Lambda 関数は、どれも何かによって起動されます。AWS には 3 つの呼び出しモデルがあり、問題が起きたときの挙動がそれぞれ異なります。サーバーレスの図が示せる情報のなかで、これがいちばん役に立ちます。
| 呼び出しモデル | 典型的なソース | 失敗時に誰が再試行するか | 失敗したものの行き先 |
|---|---|---|---|
| 同期 | API Gateway、関数 URL、SDK 呼び出し | 呼び出し元が決める | 呼び出し元へのエラーレスポンス |
| 非同期 | EventBridge、S3 通知、SNS | Lambda がデフォルトで 2 回再試行する | 失敗時の送信先またはデッドレターキュー(設定している場合) |
| イベントソースマッピング(Lambda がポーリング) | SQS、DynamoDB Streams、Kinesis | Lambda がバッチを再試行し続ける | SQS: キューのデッドレターキュー。Streams: 失敗時の送信先、なければレコードが期限切れになる |
トリガーのエッジにはそれぞれ、ソースとモデルをラベルとして付けます。sync、async、poll, batch 10 といった具合です。障害が「メッセージが溜まっている」という報告から始まったとき、皆が真っ先に探すのがこの線です。
例: サーバーレスの注文 API
マネージドサービスだけで構築した、小さな注文サービスです。
- クライアントが API Gateway の HTTP API を呼び出します。JWT オーソライザーが、Amazon Cognito のユーザープールが発行したトークンを検証します。
- API Gateway が
createOrderを同期的に呼び出します。関数はリクエストを検証し、注文をordersDynamoDB テーブルに書き込みます。 - テーブルの DynamoDB ストリームが
publishOrderEventsをトリガーし、この関数がOrderPlacedをカスタムの EventBridge バスに送信します。イベントはストリームから来るので、書き込みが成功した場合にだけ発行されます。 - EventBridge ルールが
OrderPlacedに一致し、イベントをreceiptsSQS キューに送ります。 - Lambda がキューをポーリングし、最大 10 件のバッチで
sendReceiptを呼び出します。この関数は Amazon SES を通じて顧客にメールを送ります。 - 5 回失敗したメッセージは
receipts-dlqに移され、そこでアラームがチームに知らせます。
ダイアグラムの内容
- Clients
- Amazon Cognito
- orders-service stack (SAM)
- API Gateway
- createOrder
- DynamoDB: orders
- publishOrderEvents
- EventBridge bus: orders
- SQS: receipts
- sendReceipt
- SQS: receipts-dlq
- CloudWatch alarm
- Amazon SES
- POST /orders
- JWT authorizer
- sync
- PutItem
- stream, poll
- PutEvents: OrderPlaced
- rule: OrderPlaced
- poll, batch 10
- SendEmail
- after 5 receives
- messages > 0
リクエストパスはステップ 2 で終わり、注文が保存された時点でクライアントはレスポンスを受け取ります。それ以降はすべて非同期で、図ではそれらのトリガーを破線のエッジで描いています。
サーバーレスの図のルール
トリガーはラベル付きのエッジで描く
関数に入るエッジが、その関数を何が起動するのかを示します。POST /orders、DynamoDB stream、rule: OrderPlaced、SQS, batch 10 などです。入ってくるエッジのない関数は、デッドコードか、図に描き漏れた線のどちらかです。
リクエストパスと非同期処理を分ける
同期呼び出しには実線のエッジを、後から起きることにはすべて破線のエッジを使います。読み手が、ラベルを一つひとつ読まなくても、ユーザーにとってのレイテンシーを増やす経路をたどれるようにします。
失敗時の経路を意図して描く
非同期のエッジごとに、失敗したものの行き先を決めて描きます。デッドレターキュー、失敗時の送信先、あるいは「レコードは 24 時間で期限切れになる」と書いたメモです。DynamoDB Streams はレコードを 24 時間保持するため、失敗し続けるコンシューマーは、期限切れになったイベントを失います。S3 の失敗時の送信先は失敗したレコードのコピーを保持しますが、SQS や SNS の送信先が受け取るのはメタデータだけです。そのため、その 24 時間のうちに何かがストリームからレコードを読み直す必要があります。
1 ノードに 1 関数
30 個の関数を 1 つの「Lambda」ノードで表すと、トリガーが隠れてしまいます。そして、トリガーこそがアーキテクチャです。関数が多すぎる場合は、ボックスをまとめるのではなく、サービスごとに図を分けます。
デプロイ単位でフレームにまとめる
SAM、CDK、Terraform のスタック 1 つ分のように、一緒にデプロイされるリソースをフレームでまとめます。誰が所有しているか、何が一緒に変わるかがわかります。
権限と制限はメモに残す
どの関数にも IAM 実行ロールがあり、予約済み同時実行や長いタイムアウトが設定されているものもあります。関数ごとにロールを描くのはやめましょう。レビューで重要になる点をメモに書きます。たとえば「orders に書き込めるのは createOrder だけ」「SES の制限を守るため、sendReceipt の SQS トリガーの最大同時実行数は 5」のようにです。
よくある間違い
- API Gateway をロードバランサーとして描く。 API Gateway は認証、スロットリング、リクエストの変換も担います。オーソライザーも図に含めましょう。
- デッドレターキューがない、または誰も監視していない。アラームも描きましょう。
- ルールのないイベントバス。 EventBridge バスはルールごとにファンアウトします。エッジにはバスだけでなくルールをラベルとして付けましょう。
- 同期と非同期を区別していない。 これは、遅い API と遅いメールの違いです。
- インフラのノイズ。 ロググループ、レイヤー、すべての IAM ポリシーは、全体図ではなくテンプレートに書くものです。
Archboard で描く
Archboard のクラウドパックのノードは特定のプロバイダーに依存せず、ポートを持っています。そのため、各ノードには AWS のサービス名をラベルとして付けます。
- Google または GitHub でサインインし、図を作成します。
- クライアントと Amazon SES 用の基本パックのボックスノード、クラウドパックの APIゲートウェイ、
Amazon Cognitoというラベルを付けたセキュリティパックの IDプロバイダーを追加します。 - Lambda 関数ごとにクラウドパックの関数を 1 つ追加し、テンプレートとまったく同じ名前を付けます。
DynamoDB: ordersというラベルを付けたクラウドパックのマネージドデータベース、EventBridge busというラベルを付けたデータパックのトピック、キューとそのデッドレターキュー用のクラウドパックのキューノード、アラーム用の DevOps パックのアラートを追加します。- ポート同士を接続します。リクエストパスは実線のままにし、非同期のエッジは破線に設定して、すべてのトリガーにソースと呼び出しモデルのラベルを付けます。
- スタックを基本パックのフレームで囲み、権限と制限についてのメモを追加したら、ライブリンクをチームと共有します。
この例で使う図のノードは 13 個で、Free プランに収まります。サーバーレスやコンテナのワークロードを取り巻くネットワークについては AWS VPC 構成図のガイドを、ほかのクラウドのパターンについてはクラウドのユースケースページを参照してください。
よくある質問
Lambda 関数はすべて描くべきですか? サービスの図では、すべて描きます。関数ごとにトリガーと失敗時の挙動が異なるからです。システム全体の概要図では、サービスを 1 つのノードとして示し、そのサービスの図にリンクします。
AWS の公式アイコンは使えますか?
Archboard には AWS 専用のパックはありません。クラウド、ネットワーク、セキュリティの各パックにある、ポートを持つ型付きノードで図を組み、Amazon SES や DynamoDB: orders のようにそれぞれサービス名のラベルを付けてください。ロゴも使いたい場合は、検索して挿入に AWS Lambda など AWS サービスのブランドアイコンがあり、アイコンノードとして配置できます。
Step Functions はどう表しますか? アーキテクチャ図では、ステートマシン名をラベルにした 1 つのノードとして描きます。ワークフロー自体は、別のフローチャートか BPMN 図にします。
コールドスタートや同時実行はどこに書きますか? それが問題になる関数の横のメモに書きます。たとえば、レイテンシーに敏感なエンドポイントのプロビジョニングされた同時実行です。
IAM ロールは描く必要がありますか? ノードとしては不要です。設計を左右する権限をメモに書き、ポリシーの全文はインフラのコードで管理します。