分散システムの障害は、一見すると限定的なエラーから始まっても、多くのコンポーネントが相互に依存していると、すぐに一連の障害へと発展する可能性があります。ソフトウェアエンジニアリングの独立コンサルタントであるSam Newmanは、ある講演で、土木工学における連鎖的崩壊(Progressive Collapse)の概念とデジタルシステムのレジリエンスに関する問題を結び付け、あらゆる障害を防ぐことはできないものの、その拡散と影響の可能性は低減できると結論付けています。
Ronan Pointの建物からクラウドサービスまで
Newmanは、1968年にロンドンのCanning Town地区にあるRonan Pointタワーで発生した部分的な崩壊事故を振り返ります。Mrs. Ivy Hodgeのアパート内で発生した小規模なガス爆発により、建物の一部を支えていた外壁が吹き飛びました。爆発地点の上にあった4つの階が崩壊し、その後、連鎖的な影響によってタワーの角の一部が崩落しました。4人が死亡しましたが、事故が1968年の午前6時直前に発生したことが、犠牲者数の抑制に寄与しました。
ソフトウェアにとっての意味は、建物とデジタルサービスの物理的な類似性ではなく、障害のパターンにあります。小さな初期障害が、他のコンポーネントが依存するコンポーネントを停止させ、その結果、被害の範囲が拡大します。分散システムでは、サービス、データベース、ロードバランサー、DNSシステムの間の関係が、ドミノの列のように常に目に見えるわけではないため、この連鎖を理解することは困難です。
連鎖的障害のデジタルな例
AWSのus-east-1リージョンが10月に停止した際、DynamoDBのサブコンポーネントがAWSのインフラストラクチャ内でDNSルートを更新する際に問題に直面しました。プラン更新処理の不具合により、Route 53のルートが削除され、その後、ネットワークロードバランサー、コンピューティング、キュー、EKSなど、これらのルートに依存するサービスが停止し始めました。これらの基盤サービスは他のサービスでも利用されていたため、問題はAlexa、Ring、Slack、Snapchat、Zoom、Shopifyなど、ユーザー向けの製品や企業へと広がり、一部は部分的に、別の一部は完全に影響を受けました。
AWSの報告書に基づくNewmanの説明によれば、このシステムには、DNS変更計画を作成するプランナーと、それを適用する複数のエグゼキューターが含まれていました。ある計画の処理に通常より長い時間がかかり、その後、別のエグゼキューターが別の計画を作成して迅速に実行しました。後になって古い計画の実行が完了した際、新しい計画が作成したルートが削除されました。その結果、DNSエントリーの削除につながる競合状態(Race Condition)が発生しました。
2つ目の例は、中古車、オートバイ、トレーラーを販売するウェブサイトで、Sauronというコードネームのアプリケーションを10台のサーバー上で稼働させていました。このアプリケーションは通常、同時に30~60件のリクエストを処理していましたが、800件を超えるリクエストに直面しました。依存先のサイトの1つが接続を受け付けた後、応答しないまま停止し、アプリケーションはリクエストを終了するまで30秒間待機しました。接続プールが枯渇し、その後、スレッドが蓄積して、プロセッサーがそれらの管理に時間を費やすようになり、システム全体が停止しました。ユーザーが更新ボタンを繰り返し押したことで、負荷はさらに増大しました。
崩壊を抑える3つの道筋
Newmanは、単一の「根本原因」に焦点を当てると、過度な単純化につながると考えています。火種を防ぐことは有益かもしれませんが、火災が広がることを可能にするすべての条件に対処できるわけではありません。そのため、レジリエンスエンジニアリングでは、障害が発生する可能性を受け入れ、次の3つの相互に関連するカテゴリーを通じて、その影響を抑える準備に重点を置きます。
- リスクの低減:危険の源を取り除くか、リソースを枯渇させる能力を制限します。AWSの場合、問題を処理するまでDNSの自動管理を一時停止することや、コンポーネントのテストを改善することが含まれます。Sauronアプリケーションでは、システムの処理能力を超えるリクエストを蓄積させて崩壊させるのではなく、一定数のリクエストだけを受け付け、容量を超える分を拒否する負荷遮断(Load Shedding)を利用できました。
- コンポーネントの強化:冗長化、監視、テスト、実装の改善によって、サービスの一部の障害に耐える能力を高めます。ロードバランサーの背後でサービスの複数のインスタンスを稼働させることを意味する場合もありますが、その判断はコンポーネントの重要性とコストから切り離せません。Sauronアプリケーションは廃止段階にあり、収益の一部しか占めていなかったため、当時は追加のバックアップインスタンスを稼働させることは、商業的に魅力のない選択肢でした。
- 結合の低減:単一のコンポーネントの障害がシステムの他の部分へ伝播するのを防ぎます。これには、バルクヘッド(Bulkheads)、タイムアウト、代替経路、可能な場合にはローカルファーストの設計を利用することが含まれます。システムの一部が別の部分に依存する度合いが低いほど、障害を拡散させるのではなく封じ込めることができます。
技術チームにとって実際に何が変わるのか
レジリエンスとは、システムを自動的に2つのリージョンまたは2つのクラウドで稼働させることを意味しません。Newmanは、選択肢がバックアップと復旧から、インフラストラクチャ全体を稼働させずにデータを複製するPilot Light構成、さらにウォームリカバリー、そして2つのサイトを同時にアクティブ化する構成まで広がることを説明しています。これらの選択肢は、停止時間とデータ損失を段階的に減らしますが、コストと複雑さを高めます。
また、特にそのために設計されていない既存のアプリケーションに追加する場合、サイト間の双方向同期を単純なものと見なさないよう警告しています。マルチクラウドについても同じことが当てはまります。マルチクラウドは単一プロバイダーへの依存を減らせる可能性がありますが、各プラットフォームで異なるスキルと運用が必要になります。AWSとAzureに同じコードをデプロイするだけでは独立性は保証されません。同じソフトウェア上の欠陥が両方の環境を停止させる可能性があるためです。
結論
基本的な教訓は、レジリエンスとは障害が発生しない環境を探すことではなく、ある部分が障害を起こしてもシステムの一部が稼働し続けられるように設計することだという点です。そのため、リスク、容量の限界、ボトルネック、依存経路を評価し、冗長化、隔離、コストのバランスを取る必要があります。マルチリージョンやマルチクラウドでの運用といった判断は、一般的な処方箋ではなく、サービスの重要性に結び付いた技術的・商業的な選択肢であり続けます。
ニュースの出典
InfoQ - Architecture Articles
原文を開く ↗