3月1日、AWSのme-central-1リージョンのアベイラビリティゾーンmec1-az2が、AWSが "objects that struck the data center, creating sparks and fire" と表現するものに見舞われた。約18時間後、2つ目のゾーンmec1-az3も電源を失った。3つ目のmec1-az1は終始稼働し続けた。3つのうち2つのゾーンが障害を受けたことで、S3とDynamoDBがリージョン全体で失敗し始め、AWSの顧客への助言は、Health Dashboard上の自らの言葉で、"enact their disaster recovery plans and recover from remote backups into alternate AWS Regions, ideally in Europe" というものだった。アベイラビリティゾーンの独立性は、電源障害、冷却障害、ネットワーク障害に対して設計されている。3月、それは一度も設計対象とされてこなかった原因に出会い、その原因は設計など気にかけなかった。

これは Nothing Fails Alone の第2回だ。第1回は5月のus-east-1インシデントを検討し、ゾーン境界は持ちこたえたと論じた。実際そうだった。1つのデータホールでの冷却障害は、設計通りに1つのゾーンの内側にとどまり、その後の障害は顧客が構築したものだった。その論は正しく、特定の問いに答えていた。AZ分離は、それが設計対象とする障害モードを封じ込めるのか、という問いだ。3月のme-central-1のイベントは別の問いを投げかける。それは第1回が書かれる前に起きており、当時は戦時の特殊ケース、通常のアーキテクチャには何の教訓もない戦争行為の脚注として片付けるのは容易だった。一般的な形を見えるようにしたのは5月のインシデントだ。第1回はゾーン境界が守るものについての話であり、この回はそれが守れないもの、つまり複数のゾーンに届くあらゆる原因についての話だ。そうした原因は平時にも存在する。戦争はそのデモンストレーションを2日間に圧縮しただけだ。

me-central-1で実際に何が起きたか

このイベントは3月1日午前4時51分(PST)、"issues with AWS services in the ME-CENTRAL-1 Region" の調査としてAWS Health Dashboard上で始まり、すぐに単一のアベイラビリティゾーンmec1-az2での "localized power issue" へと絞り込まれた。ダッシュボードのログは異例なほど率直で、午前9時41分(PST)には電源が落ちた理由をこう説明した。"At around 4:30 AM PST, one of our Availability Zones (mec1-az2) was impacted by objects that struck the data center, creating sparks and fire. The fire department shut off power to the facility and generators as they worked to put out the fire." 翌日AWSは原因を名指しした。The Registerが同日報じた更新でだ。中東の紛争の一部としてのドローン攻撃だった。"In the UAE, two of our facilities were directly struck" であり、その攻撃は "caused structural damage, disrupted power delivery to our infrastructure, and in some cases required fire suppression activities that resulted in additional water damage" だった。

初日を通じて、このインシデントは教科書的な単一ゾーンイベントに見え、AWSも同じ午前9時41分の更新でそう述べた。"Customers who were running their applications redundantly across the AZs are not impacted by this event." マルチAZは、その時刻には正しく十分な答えであり、その1時間足らず前の更新には、第1回を読んだなら見覚えのある但し書きが付いていた。影響を受けていないゾーンでの需要増加のため、"customers may experience longer than usual provisioning times"、と。これはAWSが5月のus-east-1イベント、第1回が2週間前に扱ったインシデントの最中に公開することになるのと同じ言い回しだ。カレンダー上では3月が先だったにもかかわらず。生き残ったゾーンへの大量フェイルオーバーは、どこでも、どのリージョンでも、どのインシデントでもサンダリングハードだ。

そして午後10時46分(PST)、最初の攻撃からおよそ18時間後。"a localized power issue has affected another Availability Zone in the ME-CENTRAL-1 Region (mec1-az3) ... At this point it is not possible to launch new instances in the region ... Other AWS Services, such as DynamoDB and S3 are also experiencing significant error rates and latencies." 3つのうち2つのゾーンがダウンし、障害はゾーン層から完全に這い上がっていた。

18時間は同時ではない。そしてそれが要点だ

2つのゾーンは一緒に倒れたのではない。同じ原因に対して、およそ18時間の間隔をおいて倒れた。その区別こそがこの記事の論の全体なので、正確を期す価値がある。ゾーンの独立性は確率の主張だ。AWSはゾーンを別々の電源、別々の冷却、別々の氾濫原、別々のネットワーク経路の上に設計する。ある施設の内部障害、故障したチラー、故障した変圧器、不良なスイッチファブリックが、その内側にとどまり、別の施設の内部障害と同時に起きないようにするためだ。その主張自身の言葉で言えば、3月は何も変えなかった。どちらのゾーンも他方を落としてはいない。共有された変圧器も、連鎖する依存関係もなかった。分離の設計は最後まで機能した。

失敗したのは確率計算の下にある前提だった。ゾーン障害は独立事象である、という前提だ。それらが独立なのは、原因が施設の内側で発生するときだけだ。施設の外側で発生する原因、嵐、送電網の崩壊、山火事、武力紛争は、一度サンプリングされ、その届く範囲のすべてのゾーンに適用される。それらのゾーンは1つの都市圏、1つの送電網、1つの空域、そして1つの戦争を共有していた。相関する障害とは、2つのゾーンが同じ瞬間に死ぬことを意味しない。1つの原因がそれ自身のスケジュールで両方に届くことを意味する。18時間の間隔こそが、ダッシュボード上で相関が実際に見える姿だ。同期したクラッシュではなく、同じ手が2度叩くのだ。

だからこそ戦時の特殊ケースという枠組みは破綻する。ドローンは珍しいが、共有された都市圏インフラは珍しくない。あらゆるマルチAZリージョンは、そのゾーンを互いに1桁ミリ秒の範囲内に集中させており、それは実務上、天候、公共インフラ、政治に対して同じ都市スケールのブラストラジアスを意味する。3月のイベントは、それが起きた都市にちなんで名付けられるほど大きいあらゆるイベントを含む、原因の一族の極端な端だ。InfoQがその月の後半、"War in Iran Damages Multiple AWS Data Centers, Challenging Multi-AZ Assumptions" というタイトルでこのインシデントを分析したとき、それが要約したコミュニティの議論はすでにドローンを通り越して一般的なケースへと移っていた。ゾーンは同じ都市にある建物の集まりであり、挑む価値のある前提とは、都市に届きうるすべてのものに関するものなのだ。

リージョンそのものが障害ドメインになるとき

ログ全体で最も示唆に富む更新は、3月2日午前2時53分(PST)、AWSが2つのゾーンの喪失がS3に何をするかを説明したときに来た。"Amazon S3 is a regional service and designed to withstand the total loss of a single Availability Zone ... As the second AZ became impaired, S3 error rates increased. With two Availability Zones significantly impacted, customers are seeing high failure rates for data ingest and egress."

その文をアーキテクチャ文書として読んでほしい。実際そうなのだから。S3とDynamoDBは、あなたがゾーン障害に備えて設計しないサービスだ。AWSがあなたの代わりにそれをやり、ゾーンを跨いでレプリケートし、1つのゾーンの喪失が見えないようにするからだ。その設計には明示された許容度がある。1つのゾーンだ。2つ目のゾーンがそれを超え、そのリージョンのあらゆる「レジリエントな」アーキテクチャが依存していたサービス、状態のため、バックアップのため、フェイルオーバー自体の調整データのために依存していたサービスが、リージョン全体で読み書きを拒否し始めた。あなたのマルチAZアプリケーションは、インスタンスを失っただけではない。復旧しようと計画していたリージョンの基盤を失った。mec1-az1は健全だったが、それは重要ではなかった。障害を受けたリージョンのコントロールプレーンに接続された健全なゾーンは、配管のない建物の中の、明かりのついた部屋だからだ。これがマルチAZが答えられない部分だ。リージョンサービスはあなたと同じ3つのゾーンの上に構築されており、相関するゾーン喪失に対するその許容度は、あなたが選んだ数ではなくAWSが選んだ数だ。

"Ideally in Europe"

3月2日午前6時22分(PST)までに、AWSのガイダンスは最も直截な一文にたどり着いていた。"We recommend customers enact their disaster recovery plans and recover from remote backups into alternate AWS Regions, ideally in Europe."

その文は、3月に受けたよりもゆっくりとした読みに値する。第一に、そのリージョンの提供者が、顧客にそこを去るよう告げた。ベンダー自身が述べた、リージョン内冗長性の天井だ。復旧計画に含めるべきme-central-1の正しい量がゼロであるようなイベントのクラスが存在し、自分がどのクラスにいるかはインシデントの最中に、ダッシュボードから知ることになる。第二に、"ideally in Europe" は静かに、慎重な仕事をしている。最も近い代替であるバーレーンのme-south-1は、すぐそこにあり、レイテンシの観点からは反射的なDRの選択肢になるところだが、同じ作戦で近隣への攻撃によりそこの施設も影響を受けていた。AWSは顧客に、明言せずに、相関する原因には地理があり、有用な復旧リージョンとはその地理の外にあるものであって、単にリージョンARNの外にあるものではない、と告げていた。プライマリからの距離はコンプライアンスのチェックボックスではない。それは相関する原因がどこまで届くかについての賭けだ。DRリージョンは、両方に妥当に届きうるものは何かを問うて選べ。レプリケーションのレイテンシをきれいに保つものは何か、ではなく。

第三に、その助言はそれに従えた顧客にしか効かない。"Recover from remote backups" はリモートバックアップの存在を前提とする。3月1日より前に作られていたものを。というのも同じ更新ログは、イベントの最中にS3の "data ingest and egress" がリージョン全体で失敗していることを示しているからだ。データをリージョンの外にコピーするのは平時の活動だ。提供者がそれを助言している頃には、始めるための窓はもう閉じている。

数か月

このイベントの最後の更新は4月30日付で、1段落の長さで、物語を終わらせずに終わらせている。リージョンは "has suffered damage as a result of the conflict in the Middle East and is currently unable to reliably support customer applications" であり、顧客は "migrate all accessible resources to other Regions and restore inaccessible resources from remote backups as soon as possible" すべきで、課金業務は停止され、復旧は "is expected to take several months" とされた。

それを標準的なDR文書と突き合わせてみよう。RTOは期間として書かれ、私がレビューしてきたほぼすべてのRTOは、復旧先が今いる場所そのものだと暗黙に前提している。スナップショットをリストアし、フリートを再起動し、同じリージョンで、最悪でも時間単位だ。"Several months" はその数を圧迫するのではない。それが書かれた軸そのものを消し去る。リージョンが今四半期に戻ってこないなら、あなたの実際の復旧時間は、コールドなクロスリージョン再構築にかかる時間そのものであり、誰もリハーサルしなかった部分を含む。うまくいけば手元にあるコードから再生成されるIAMとネットワーキング、うまくいけば作っておいたレプリカから復元されるデータ、切り替えるDNS、他の全員の一斉脱出を同時に吸収する目的地リージョンで見つけ出すキャパシティだ。クロスリージョンレプリケーションがすでに流れているチームにとって、3月は悪い1週間だった。DR計画がリージョン内スナップショットだったチームにとって、それは砲撃によって告知された移行プロジェクトだった。

ラボ: あなたは実際どの物理ゾーンにいるのか?

第1回はラボのセクションを、AWSのインシデントレポートがゾーンをIDで名指しすること、use1-az4、そしてIDから名前へのマッピングがなければそれがあなたのus-east-1aだったのか分からないことを指摘して締めくくった。3月は、それが些末でなくなるインシデントだ。ダッシュボードはmec1-az2、次いでmec1-az3と言った。あなたのワークロードが攻撃されたゾーンにあったのか、生き残ったゾーンにあったのかを知るには、それらのIDをあなたのアカウントに対して、インシデントの最中に解決しなければならなかった。me-central-1aのようなゾーン名はアカウントスコープのエイリアスだからだ。AWSは物理ゾーンに文字をアカウントごとに独立して割り当てるため、2つのアカウントのme-central-1aは通常異なる物理ゾーンだ。「私たちはa、b、cに分散している」は、あなたのアカウントの命名についての言明であって、物理配置についてのものではない。

この回のラボ、02-az-id-truthは、意図的にシリーズで最小のものだ。唯一のAPI呼び出しがDescribeAvailabilityZonesGetCallerIdentityだけの単一の読み取り専用スクリプトで、後者は出力にラベルを付けるためだけのものだ。現在のアカウントとリージョンについて名前からIDへのマッピングを表示する。これは私のあるアカウントでの実際の出力だ。

$ python3 az_ids.py --region us-east-1
Region: us-east-1

ZONE NAME  | ZONE ID  | STATE
---------------------------------
us-east-1a | use1-az1 | available
us-east-1b | use1-az2 | available
us-east-1c | use1-az4 | available
us-east-1d | use1-az6 | available
us-east-1e | use1-az3 | available
us-east-1f | use1-az5 | available
...

このアカウントでは、5月のインシデントレポートのゾーンであるuse1-az4は、us-east-1cだ。ここのエンジニアが5月に「use1-az4」を読み、「us-east-1a」とラベルされた図をちらっと見たら、間違ったゾーンについて安心し、健全なゾーンについて心配していただろう。スクリプトは--compare <profile>も取り、同じリージョンで2つ目のアカウントのマッピングを読み、両者を並べて表示し、名前ごとに同じ物理ゾーンに解決されるかの判定を付け、その後不一致を数える。同じ名前がアカウント間で異なるIDに解決されるのが通常のケースであって、例外ではない。「us-east-1aを退避せよ」と言う共有ランブックは、アカウントによって異なることをする。ランブック、配置の決定、インシデント時の照会はゾーンIDに属する。マッピングをインベントリツールに送り込むための--jsonフラグがあり、終了コードは実行が完了すれば常に0で、まったく実行できない場合、boto3がない、クレデンシャルがない、リージョンがない、未知のプロファイル、あるいはdescribe呼び出し自体の失敗のために2を予約している。

障害モードと注視すべきこと

まず限界について正直になろう。顧客はme-central-1を戦争から設計で除くことはできない。あなたのTerraformの中には相関する原因を防ぐものは何もない。あなたが制御できるのは、それが見つけたときにデータがすでに他所にあるかどうかだ。3月から導かれる注視リストは短い。すべてのゾーンに一度に届く原因を列挙せよ。共有された都市圏、共有された送電網、共有された天候、共有された司法管轄だ。そしてその答えを、あなたの実際のリージョン喪失確率として扱え。それは低いが、ゾーンの計算が静かに前提していたゼロではない。再生成できないものすべてについて、相関する地理の外にあることを基準に選んだリージョンに、クロスリージョンバックアップを保持し、リストアをテストせよ。3月版のそのテストには消防隊が含まれていたのだから。RTOは2度書け。1度はリージョン内復旧のため、もう1度はリージョンが四半期の間なくなると仮定して。そしてその2つ目の数を、リスクを負う者の前に出せ。そしてアカウントごとの物理ゾーンIDのインベントリを保て。次のレポートがゾーンIDを言うとき、マッピングを学ぶ時間はイベントの最中ではないからだ。ゾーン境界は本物であり、第1回はそれが持ちこたえるのを示した。3月はその上にあるものを示した。ゾーンは互いに完全に分離されていても、なお世界からは分離されていない、ということを。

次に読む

AWS、クラウドアーキテクチャ、レジリエンスレビュー、プラットフォーム業務のコンサルティングは、ercanermis.comからどうぞ。

参考資料