AWS 障害から学ぶ分散システムの原則 - 過去の大規模障害が変えたアーキテクチャ
S3 障害 (2017)、Kinesis 障害 (2020)、us-east-1 の特殊性など、AWS が公開した障害レポートを題材に、Shuffle Sharding、Static Stability、Cell-based Architecture といった設計原則を解説します。
障害レポートという教科書
AWS は大規模障害が発生した際、Post-Event Summary と呼ばれる詳細な障害レポートを公開しています。これらのレポートは単なる謝罪文ではなく、障害の根本原因、影響の連鎖、復旧プロセス、そして再発防止策を技術的に記述した貴重な資料です。分散システムの設計原則は抽象的に語られがちですが、実際の障害事例と紐づけることで、なぜその原則が重要なのかが具体的に理解できます。ここでは AWS が公開した代表的な障害事例を取り上げ、そこから導き出された設計原則を解説します。
S3 障害 (2017 年 2 月) - カスケード障害と復旧の困難さ
2017 年 2 月 28 日、us-east-1 リージョンで S3 が約 4 時間にわたって停止しました。AWS の公式レポートによると、課金システムの問題をデバッグする過程で、S3 のインデックスサブシステムとプレースメントサブシステムから意図した以上のサーバーが削除されました。問題はここからです。これらのサブシステムは S3 の読み書き操作に不可欠であり、残されたサーバーだけでは処理能力が不足しました。さらに深刻だったのは、これらのサブシステムが長年にわたって完全な再起動を経験していなかったことです。サブシステムの再起動には既存のメタデータの整合性チェックが必要で、データ量の増大に伴い再起動時間が想定以上にかかりました。この障害は 2 つの教訓を残しました。第一に、依存関係の連鎖 (カスケード障害) の危険性です。S3 に依存していた多数のサービスやウェブサイトが連鎖的に停止しました。AWS の障害ダッシュボード自体が S3 に依存していたため、障害状況の通知すらできないという皮肉な事態も発生しました。第二に、大規模システムの再起動コストです。長期間停止しないことが前提のシステムは、再起動時に予想外の時間がかかるリスクを抱えています。
Kinesis 障害 (2020 年 11 月) - キャパシティ増強が引き起こした障害
2020 年 11 月 25 日、us-east-1 で Kinesis が約 21 時間にわたって障害を起こしました。AWS の公式レポートが明かした原因は、キャパシティの増強そのものでした。Kinesis のフロントエンドサーバー群は、相互に通信するためにサーバーごとに OS スレッドを 1 本ずつ使用するメッシュ構造を持っていました。バックエンドにサーバーを追加したところ、フロントエンドの各サーバーが保持するスレッド数が OS の設定上限を超えてしまいました。この障害の皮肉は、サービスを改善するための容量追加が障害の引き金になったことです。さらに、Kinesis の障害は CloudWatch、Cognito、Lambda など Kinesis に依存する多数のサービスに波及しました。AWS はこの障害を受けて、フロントエンドサーバーをより大きな CPU とメモリを持つサーバーに移行し、サーバー台数を減らすことでスレッド数の問題を根本的に解消しました。また、フロントエンドのキャッシュ構造を見直し、バックエンドの変更がフロントエンドに与える影響を軽減する設計変更を行いました。
us-east-1 の特殊性 - なぜこのリージョンだけ障害が多いのか
AWS の障害報告を追うと、us-east-1 (バージニア北部) が繰り返し登場することに気づきます。これは偶然ではありません。us-east-1 は AWS 最古のリージョンであり、IAM、Route 53、CloudFront などのグローバルサービスのコントロールプレーンが集中しています。グローバルサービスとは、特定のリージョンに紐づかず世界中で共通のエンドポイントを持つサービスです。これらのコントロールプレーン (設定変更や認証を処理する管理系コンポーネント) が us-east-1 に置かれているため、このリージョンの障害は他のリージョンにも波及する可能性があります。2021 年 12 月の障害では、us-east-1 内部のネットワーク機器の問題が、リージョン内の複数サービスのコントロールプレーンに影響を与えました。データプレーン (実際のデータ処理を行うコンポーネント) は正常に動作していたにもかかわらず、新しいリソースの作成や設定変更ができない状態が続きました。この事例は、コントロールプレーンとデータプレーンを分離し、コントロールプレーンの障害時でもデータプレーンが独立して動作し続ける設計の重要性を示しています。
障害から生まれた設計原則
AWS はこれらの障害経験から、Builders' Library やホワイトペーパーを通じて設計原則を体系化しています。Shuffle Sharding は、顧客をランダムに選ばれたサーバーの組み合わせ (シャード) に割り当てる手法です。従来の固定シャーディングでは、1 つのシャードの障害がそのシャードの全顧客に影響しますが、Shuffle Sharding では顧客ごとにシャードの組み合わせが異なるため、障害の影響を受ける顧客の割合を確率的に大幅に縮小できます。Route 53 のネームサーバー割り当てにこの手法が使われています。Static Stability は、依存先のサービスが障害を起こしても、現在の状態を維持して動作し続ける設計です。たとえば、Auto Scaling グループが各 Availability Zone に十分なインスタンスを事前に配置しておけば、AZ 障害時にスケーリングの判断 (コントロールプレーン操作) ができなくても、既存のインスタンスで処理を継続できます。Cell-based Architecture は、システムを独立した複数のセル (レプリカ) に分割し、各セルが自律的に動作する設計です。1 つのセルに障害が発生しても、他のセルには影響しません。S3 障害後に AWS が推進した設計パターンであり、障害の爆発半径を物理的に制限します。
自分のシステムへの応用
これらの原則は AWS 規模のシステムだけでなく、一般的なアプリケーション設計にも応用できます。まず、依存関係を明示的に把握することです。自分のシステムがどのサービスに依存し、そのサービスが停止したときに何が起きるかを事前に整理します。次に、コントロールプレーンとデータプレーンの分離を意識することです。設定変更や管理操作ができなくても、既存のデータ処理が継続できる設計を目指します。Circuit Breaker パターンを導入し、依存先の障害を検知したら即座にフォールバック処理に切り替えることも有効です。マルチ AZ 構成は最低限の耐障害性として採用し、ビジネス要件に応じてマルチリージョン構成を検討します。ただし、マルチリージョンはデータの整合性やレイテンシのトレードオフを伴うため、すべてのワークロードに適用すべきではありません。障害は必ず起きるという前提で設計し、障害時の影響範囲を最小化することが、分散システム設計の本質です。 分散システムの設計原則を体系的に学ぶには専門書 (Amazon) が役立ちます。
まとめ
AWS の大規模障害は、分散システム設計の原則を学ぶ最良の教材です。S3 障害はカスケード障害と再起動コストの危険性を、Kinesis 障害はキャパシティ変更時の予期せぬ副作用を、us-east-1 の繰り返す障害はグローバルサービスの集中リスクを教えてくれました。これらの経験から生まれた Shuffle Sharding、Static Stability、Cell-based Architecture といった設計原則は、AWS 内部だけでなく、あらゆる分散システムの設計に適用できる普遍的な知見です。