

# AWS での高可用性分散システムの設計
<a name="designing-highly-available-distributed-systems-on-aws"></a>

 これまでのセクションでは、主にワークロードの理論的な可用性と、それによって実現できることについて説明しました。これらは、分散システムを構築する際に覚えておくべき重要な概念です。依存関係の選択プロセスや冗長性の実装方法を知るのに役立ちます。

 これまで、MTTD、MTTR、MTBF と可用性の関係について説明しました。このセクションでは、これまでの理論に基づいた実践的なガイダンスを紹介します。つまり、高可用性を実現するためのエンジニアリングワークロードは、MTBF を増やし、MTTR と MTTD を減らすことを目的としています。

 障害をすべて無くすことが理想的ですが、これは現実的ではありません。依存関係が深く積み重なっている大規模な分散システムでは、障害が発生することがあります。「壊れないものはない」(Amazon.com 最高技術責任者、Werner Vogels、「[Amazon Web Services の 10 年間の経験から得た 10 の教訓](https://www.allthingsdistributed.com/2016/03/10-lessons-from-10-years-of-aws.html)」を参照)、「障害を法律で規定することはできません。だから迅速な検出と対応に重点を置くべきです」 ([ARC335 Amazon EC2 チーム創設メンバーの Chris Pinkham 氏、「障害に備える設計:AWS での耐障害性の高いシステムの設計](https://d1.awsstatic.com/events/reinvent/2019/REPEAT_1_Designing_for_failure_Architecting_resilient_systems_on_AWS_ARC335-R1.pdf)」を参照) 

 障害が発生するかどうかを制御できないことは頻繁にあります。制御できるのは、障害をどれだけ早く検出して対処するかです。そのため、MTBF の増加は依然として高可用性の重要な要素ですが、MTTD と MTTR の削減は、カスタマーが制御できる最も大きな変更です。

**Topics**
+ [MTTD の削減](reducing-mttd.md)
+ [MTTR の削減](reducing-mttr.md)
+ [MTBF の増加](increasing-mtbf.md)

# MTTD の削減
<a name="reducing-mttd"></a>

 障害のある MTTD を減らすことで、障害を可能な限り早期発見することができます MTTD の短縮は、可観測性、つまりワークロードの状態を把握するためにどのように計測したかに基づいています。カスタマーは、問題がいつ発生したかを事前に特定する方法として、ワークロードの重要なサブシステムで*カスタマーエクスペリエンス*指標をモニタリングする必要があります (これらの指標の詳細については、「[付録1 — MTTD と MTTR の重要なメトリクス](appendix-1-mttd-and-mttr-critical-metrics.md)」を参照)。カスタマーは [Amazon CloudWatch Synthetics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries.html) を使用して API やコンソールを監視する *canary* を作成して、ユーザーエクスペリエンスを積極的に測定できます。[Elastic Load Balancing (ELB) ヘルスチェック](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-add-elb-healthcheck.html)や [Amazon Route 53 ヘルスチェック](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/health-checks-types.html)など、MTTD を最小限に抑えるために使用できるヘルスチェックメカニズムは他にも多数あります。(「[Amazon Builders' Library — ヘルスチェックの実装](https://aws.amazon.com/builders-library/implementing-health-checks/)」を参照。) 

 また、モニタリングでは、システム全体と個々のサブシステムの両方の部分的な障害を検出できる必要があります。可用性、障害、レイテンシーのメトリックスでは、障害分離の境界の次元性を [CloudWatch メトリクスディメンション](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Dimension)として使用する必要があります。例えば、us-east-1 リージョンの use1-az1 AZ にある、セルベースアーキテクチャの一部である単一の EC2 インスタンスが、コントロールプレーンサブシステムの一部であるワークロードの更新 API の一部であるとします。サーバーがメトリクスをプッシュすると、インスタンス ID、AZ、リージョン、API 名、サブシステム名をディメンションとして使用できます。これにより、可観測性を確保し、これらの各ディメンションにわたってアラームを設定して障害を検出できます。

# MTTR の削減
<a name="reducing-mttr"></a>

 障害が発見された後、残りの MTTR 時間では実際の修理または影響の軽減を実施します。障害を修復または軽減するには、何が問題なのかを知る必要があります。このフェーズの重要なメトリクスには、1/ *影響評価*メトリクスと 2/ *運用健全性*メトリクスの 2 つの主要なグループがあります。最初のグループは、障害発生時の影響の範囲を示し、影響を受けたカスタマー、リソース、またはワークロードの数または割合を測定します。2 番目のグループは、影響がある*理由*を特定するのに役立ちます。理由が明らかになると、オペレーターとオートメーションは障害に対応し、解決できます。これらのメトリクスの詳細については、「[付録 1 — MTTD と MTTR の重要なメトリクス](appendix-1-mttd-and-mttr-critical-metrics.md)」を参照してください。

**ルール 9**  
MTTD と MTTR を減らすには、可観測性と計測が不可欠です。

## 障害回避ルート
<a name="route-around-failure"></a>

 影響を軽減する最速のアプローチは、障害を回避するフェイルファストサブシステムを使用することです。このアプローチでは、冗長性を利用して、障害が発生したサブシステムの処理をスペアにすばやく移行することで MTTR を削減します。冗長性は、ソフトウェアプロセスから EC2 インスタンス、複数の AZ、複数のリージョンまで多岐にわたります。

 スペアのサブシステムでは、MTTR をほぼゼロまで下げることができます。復旧時間は、スタンバイのスペアに処理を再ルーティングするのにかかる時間だけです。多くの場合、これは最小限のレイテンシーで行われ、定義された SLA の範囲内で作業を完了でき、システムの可用性を維持できます。これによっ発生するMTTR は、わずか、または気づかない程度の遅延であり、長期間利用できなくなるということはありません。

 例えば、サービスが Application Load Balancer (ALB) の背後にある EC2 インスタンスを利用している場合、ヘルスチェックを 5 秒程度の短い間隔で設定し、ターゲットが異常とマークされるまでに必要なヘルスチェックの失敗は 2 回のみです。つまり、10 秒以内に障害を検出し、問題のあるホストへのトラフィックの送信を停止できます。この場合、障害が検出されるとすぐに軽減が行われるため、MTTR は MTTD と実質的に同じになります。

 これこそが、*高可用性*または*連続可用性*のワークロードが達成しようとしていることです。障害が発生したサブシステムをすばやく検出して障害としてマークし、そのサブシステムへのトラフィックの送信を停止して、代わりに冗長サブシステムにトラフィックを送信することで、ワークロードの障害を迅速に回避することが理想です。

 ただし、この種のフェイルファストメカニズムを使用すると、ワークロードが一時的なエラーに対して非常に敏感になるため注意が必要です。この例では、ロードバランサーのヘルスチェックが、依存関係またはワークフローのテスト (*ディープ*ヘルスチェックと呼ばれることが多い) ではなく、インスタンスのみの*シャロー*または[https://aws.amazon.com/builders-library/implementing-health-checks/](https://aws.amazon.com/builders-library/implementing-health-checks/)ヘルスチェックを実行していることを確認します。これにより、ワークロードに影響する一時的なエラーが発生したときに、インスタンスの不要な置き換えを防ぐことができます。

 障害を回避するルーティングを成功させるには、可観測性とサブシステムの障害を検出する能力が不可欠です。また、影響の範囲を把握することで、影響を受けるリソースに異常または障害のマークを付けてサービスを停止し、回避できるようになります。例えば、1 つの AZ で部分的なサービス障害が発生した場合、計測により AZ にローカライズされた問題があることを特定し、復旧するまでその AZ のすべてのリソースを回避できる必要があります。

 障害を回避するため、環境によっては追加のツールが必要になる場合もあります。前の ALB の背後にある EC2 インスタンスの例で、ある AZ のインスタンスがローカルヘルスチェックに合格しているのに、特定された AZ の障害が原因で別の AZ のデータベースに接続できなくなっているとします。この場合、負荷分散ヘルスチェックによってそれらのインスタンスがサービス停止になることはありません。[ロードバランサーから AZ を削除したり](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-subnets.html)、インスタンスのヘルスチェックを強制的に不合格するには、別の自動化メカニズムが必要になります。これは、影響の範囲が AZ であるかどうかを特定することに依存します。ロードバランサーを使用していないワークロードでは、特定の AZ のリソースが作業単位を受け付けたり、AZ から容量を完全に削除するのを防ぐために、同様の方法が必要になります。

 場合によっては、冗長なサブシステムへの作業の移行を自動化できないこともあります。例えば、テクノロジーが独自のリーダーの選択を行わない場合のプライマリデータベースからセカンダリデータベースへのフェイルオーバーなどです。これは、[AWSマルチリージョンアーキテクチャ](https://aws.amazon.com/blogs/architecture/disaster-recovery-dr-architecture-on-aws-part-i-strategies-for-recovery-in-the-cloud/)では一般的なシナリオです。この種のフェイルオーバーでは、完了するまでにある程度のダウンタイムが必要で、すぐに元に戻すことができず、一定期間ワークロードは冗長にならないままです。そのため、意思決定プロセスに人が存在することが重要です。

 厳密性の低い整合性モデルを採用できるワークロードでは、マルチリージョンのフェイルオーバーオートメーションを使用して障害を回避することで、MTTR を短縮できます。[Amazon S3 クロスリージョンレプリケーション](https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication.html)または [Amazon DynamoDB グローバルテーブル](https://aws.amazon.com/dynamodb/global-tables/)などの機能は、結果的に整合性のあるレプリケーションを通じてマルチリージョン機能を提供します。さらに、CAP 定理を考えるときには、緩和された整合性モデルを使用することが有益です。ステートフルサブシステムへの接続に影響するネットワーク障害が発生しても、ワークロードが整合性よりも可用性を優先した場合でも、障害を回避するルーティングの別の方法として、エラー以外のレスポンスを提供できます。

 障害を回避するルーティングは、2 つの異なる方法で実装できます。最初の戦略は、障害が発生したサブシステムのすべての負荷を処理するのに十分なリソースを事前にプロビジョニングして、静的安定性を実装することです。これは、単一の EC2 インスタンスでも、AZ 全体の容量でもかまいません。障害発生時に新しいリソースをプロビジョニングしようとすると、MTTR が増加し、復旧パスのコントロールプレーンに依存関係が追加されます。ただし、追加料金が発生します。

 2 つ目の戦略は、障害が発生したサブシステムから他のサブシステムへトラフィックの一部をルーティングし、残りの容量では処理できない[余分なトラフィックを負荷分散](https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload)することです。このパフォーマンスが低下している間、障害が発生した容量を補うために新しいリソースをスケールアップできます。この方法では MTTR が長くなり、コントロールプレーンへの依存が発生しますが、スタンバイ容量および予備容量のコストは低下します。

## 既知の正常な状態に戻す
<a name="return-to-a-known-good-state"></a>

 修復中に軽減するためのもう 1 つの一般的な方法は、ワークロードを以前の既知の正常な状態に回復させることです。最近の変更が原因で障害が発生した可能性がある場合は、その変更をロールバックすることが前の状態に戻す方法の 1 つです。

 また、一時的な状態が原因で障害が発生した場合は、ワークロードを再起動することで影響が軽減される可能性があります。これらの 2 つのシナリオをについて検証してみましょう。

 デプロイ時に MTTD と MTTR を最小限に抑えるには、可観測性と自動化が必要です。デプロイプロセスでは、エラー率の増加、レイテンシーの増加、または異常が発生していないか、ワークロードを継続的にモニタリングする必要があります。これらが認識されると、デプロイプロセスが停止されます。

 インプレースデプロイ、ブルー/グリーンデプロイ、ローリングデプロイなど、さまざまな[デプロイ戦略](https://docs.aws.amazon.com/whitepapers/latest/overview-deployment-options/deployment-strategies.html)があります。これらはそれぞれ、既知の正常な状態に戻るために異なるメカニズムを使用する場合があります。自動的に前の状態にロールバックしたり、トラフィックをブルー環境に戻したり、手動で操作することができます。

 CloudFormation には、[AWS CodeDeploy](https://docs.aws.amazon.com/codedeploy/latest/userguide/deployments-rollback-and-redeploy.html#deployments-rollback-and-redeploy-automatic-rollbacks) と同様に、スタックの作成および更新オペレーションの一部として[自動的にロールバックする機能](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-rollback-triggers.html)があります。CodeDeploy は、ブルー/グリーンデプロイとローリングデプロイもサポートしています。

 これらの機能を活用して MTTR を最小限に抑えるには、すべてのインフラストラクチャとコードのデプロイをこれらのサービスを使って自動化することを検討してください。これらのサービスを使用できないシナリオでは、AWS Step Functions での [saga パターンの実装](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/implement-the-serverless-saga-pattern-by-using-aws-step-functions.html)により、失敗したデプロイをロールバックすることを検討してください。

 *再起動*を検討する場合、いくつかの異なるアプローチがあります。これらは、作業時間が最長であるサーバーの再起動から、最短のスレッドの再起動まで多岐にわたります。次の表は、一部の再起動方法とおおよその完了までの時間をまとめたものです (桁違いを表記するためであり、これらは正確ではありません)。

 


|  障害復旧メカニズム  |  推定 MTTR  | 
| --- | --- | 
|  新しい仮想サーバーの起動と設定  |  15 分  | 
|  ソフトウェアの再デプロイ  |  10 分  | 
|  サーバーの再起動  |  5 分  | 
|  コンテナの再起動または起動  |  2 秒  | 
|  新しいサーバーレス関数の呼び出し  |  100 ミリ秒  | 
|  プロセスの再起動  |  10 ミリ秒  | 
|  スレッドの再起動  |  10 μs  | 

 表を見直してみると、コンテナやサーバーレス関数 ([AWS Lambda](https://aws.amazon.com/lambda/) など) を使うことは、MTTR にとって明確な利点がいくつか存在します。これらの MTTR は、仮想マシンを再起動したり、新しいマシンを起動するよりも桁違いに速いです。ただし、ソフトウェアのモジュール化による障害の分離も有益です。障害を単一のプロセスまたはスレッドに抑えることができると、その障害からの復旧は、コンテナまたはサーバーを再起動するよりもはるかに高速です。

 復旧の一般的なアプローチとしては、下から上へ、つまり 1/再起動、2/リブート、3/再イメージ化/再デプロイ、4/置換という順序で進めることができます。ただし、再起動の手順に入ると、障害を回避するルーティングの方が通常は迅速です (通常、最長で 3 ～ 4 分かかります)。そのため、再起動を試みた後で影響を最も早く軽減するには、障害を回避するルーティングをし、バックグラウンドで復旧プロセスを続行して容量をワークロードに戻します。

**ルール 10**  
 問題解決ではなく、影響の軽減に焦点を当てる。最速の方法で通常のオペレーションに戻す。

## 障害の診断
<a name="failure-diagnosis"></a>

 検出後の復旧プロセスの一部には、診断期間があります。これは、オペレーターが問題が何かについて判断を試みる期間です。このプロセスには、ログのクエリ実行、運用健全性メトリクスの確認、トラブルシューティングのためのホストへのログインが含まれる場合があります。これらのアクションはすべて時間がかかるため、迅速化するためのツールやランブックを作成すると、MTTR の短縮にも役立ちます。

## ランブックと自動化
<a name="runbooks-and-automation"></a>

 同様に、問題が何か、そしてどのような一連の作業によりワークロードを修復できるかについて判断したら、オペレーターは通常、そのために一連のステップを実行する必要があります。例えば、障害発生後、ワークロードを修復する最速の方法は、再起動かもしれません。これには、順序付けられた複数のステップが必要になることがあります。これらのステップを自動化したり、またはオペレーターに特定の指示を与えるランブックを利用すると、プロセスが迅速になり、不注意による作業ミスのリスクが軽減されます。

# MTBF の増加
<a name="increasing-mtbf"></a>

 可用性を向上させる最後の要素は、MTBF の増加です。これは、ソフトウェアとその実行に使用される AWS サービスの両方に当てはまります。

## 分散システムの MTBF の増加
<a name="increasing-distributed-system-mtbf"></a>

 MTBF を増やす方法の 1 つは、ソフトウェアの欠陥を減らすことです。この方法には、いくつかあります。カスタマーは [Amazon CodeGuru Reviewer](https://aws.amazon.com/codeguru/) などのツールを使用して、一般的なエラーを見つけて修正できます。また、ソフトウェアを本番環境にデプロイする前に、包括的なピアコードレビュー、ユニットテスト、統合テスト、リグレッションテスト、および負荷テストを実行する必要があります。テストのコードカバレッジを増やすと、一般的でないコード実行パスでも確実にテストできるようになります。

 小さな変更をデプロイすることは、変更の複雑さが軽減され、予期しない結果を防ぐのにも役立ちます。それぞれのアクティビティは、障害が発生する前に欠陥を特定して修正する機会を提供します。

 障害を防ぐもう 1 つの方法は、[定期的なテスト](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/test-reliability.html)です。カオスエンジニアリングプログラムを実装すると、ワークロードがどのように障害を起こすかをテストしたり、復旧手順を検証したり、本番環境で障害が発生する前に障害モードを見つけて修正するのに役立ちます。カスタマーは、カオスエンジニアリング実験ツールセットの一部として [AWS Fault Injection Simulator](https://aws.amazon.com/fis/) を使用できます。

 分散システムで障害を防ぐもう 1 つの方法は、耐障害性です。フェイルファストモジュール、エクスポネンシャルバックオフとジッターによる再試行、トランザクション、冪等性はすべて、ワークロードの耐障害性に役立つ手法です。

 トランザクションは、ACID プロパティに準拠したオペレーションのグループです。その内容は次のとおりです。
+  **不可分性** — すべてのアクションが実行されるか、まったく実行されないかのどちらかです。
+  **整合性** — 各トランザクションは、ワークロードを有効な状態のままにします。
+  **分離性** — トランザクションを並行して実行すると、ワークロードは連続して実行された場合と同じ状態になります。
+  **耐久性** — トランザクションがコミットされると、ワークロードに障害が発生した場合でもその影響はすべて維持されます。

 [エクスポネンシャルバックオフとジッターによる再試行](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/)を行うと、ハイゼンバグ、過負荷、またはその他の条件によって引き起こされる一時的な障害を克服できるようになります。トランザクションが冪等性の場合は、複数回再試行でき、それによる悪影響はありません。

 耐障害性のあるハードウェア構成にハイゼンバグが及ぼす影響については、ハイゼンバグがプライマリサブシステムと冗長サブシステムの両方に発生する確率はごくわずかであるため、ほとんど心配する必要はないでしょう。(Jim Gray の「[Why Do Computers Stop and What Can Be Done About It? (コンピューターはなぜ停止するのか、そしてそれに対して何ができるのか？)](https://pages.cs.wisc.edu/~remzi/Classes/739/Fall2018/Papers/gray85-easy.pdf)」(1985 年 6 月、Tandem Technical Report 85.7 を参照)。分散システムでは、ソフトウェアで同じ結果を達成することが必要です。

 ハイゼンバグが発生したとき、ソフトウェアが不正な操作やエラーをすばやく検出して、再試行できるようにすることが不可欠です。これは、防御的なプログラミングと、入力、中間結果、および出力の検証によって実現されます。また、プロセスは分離されており、他のプロセスと状態を共有しません。

 このモジュラー型アプローチを取ることで、障害発生時の影響範囲が限定されます。プロセスの失敗は独立して発生します。プロセスが失敗したとき、ソフトウェアは「プロセスペア」を使用して作業を再試行する必要があります。これにより、失敗したプロセスの処理を新しいプロセスに引き継ぐことができます。ワークロードの信頼性と完全性を維持するには、各オペレーションを ACID トランザクションとして扱う必要があります。

 これにより、トランザクションを中止し、加えられた変更をロールバックすることで、ワークロードの状態を損なうことなくプロセスを失敗させることができます。これにより、復旧プロセスは既知の正常な状態からトランザクションを再試行し、正常に再起動できます。このようにして、ソフトウェアはハイゼンバグに対して耐障害性を持たせることができます。

 ただし、ボーアバグに対してソフトウェアに耐障害性を持たせることは、現実的ではありません。どのレベルの冗長性でも正しい結果を達成することはできないため、これらの欠陥はワークロードが本番環境に入る前に発見して取り除く必要があります。(Jim Gray の「[Why Do Computers Stop and What Can Be Done About It? (コンピューターはなぜ停止するのか、そしてそれに対して何ができるのか？)](https://www.hpl.hp.com/techreports/tandem/TR-85.7.pdf)」(1985 年 6 月、Tandem Technical Report 85.7 を参照)。

 MTBF を増やす最後の方法は、障害による影響の範囲を狭めることです。そのための主な方法は、「*耐障害性と障害分離*」で前述したように、モジュール化による[障害分離](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/use-fault-isolation-to-protect-your-workload.html)を使用して障害コンテナを作成することです。障害発生率を下げると、可用性が向上します。AWS はサービスのコントロールプレーンとデータプレーンへの分割、[アベイラビリティーゾーン独立性](https://aws.amazon.com/builders-library/static-stability-using-availability-zones) (AZI)、[リージョナル分離](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/)、[セルベースアーキテクチャ](https://www.youtube.com/watch?v=swQbA4zub20)、障害を分離するための[シャッフルシャーディング](https://aws.amazon.com/builders-library/workload-isolation-using-shuffle-sharding)などの手法を使用します。これらは AWS カスタマーも使用できるパターンです。

 例えば、ワークロードによってカスタマーがインフラストラクチャの異なる障害コンテナに配置され、全カスタマーの 5% にサービスが提供されているシナリオについて検討してみましょう。これらの障害コンテナの 1 つで、リクエストの 10% でクライアントのタイムアウトを超えるレイテンシーが増加するイベントが発生しました。このイベントでは、95% のカスタマーがサービスを 100% 利用できました。残りの 5% については、サービスは 90% 利用可能だったようです。この結果、可用性は、100% の顧客に対してリクエストの 10% が失敗するのではなく (90% の可用性)、1 − (5% *o**f* *c**u**s**t**o**m**e**r**s*×10% *o**f* *t**h**e**i**r* *r**e**q**u**e**s**t**s*) = 99.5% となります。

**ルール 11**  
障害を分離すると、全体的な障害発生率が低下するため、影響範囲が狭まり、ワークロードの MTBF が増加します。

## 依存関係の MTBF の増加
<a name="increasing-dependency-mtbf"></a>

 AWS 依存関係の MTBF を増やす最初の方法は、[障害分離](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/use-fault-isolation-to-protect-your-workload.html)を使用することです。多くの AWS サービスは、AZ であるレベルの分離を提供しています。つまり、ある AZ で障害が発生しても、別の AZ のサービスには影響しません。

 複数の AZ で冗長 EC2 インスタンスを使用すると、サブシステムの可用性が向上します。AZI は 1 つのリージョン内でスペアリング機能を提供するため、AZI サービスの可用性を高めることができます。

 ただし、すべての AWS サービスが AZ レベルで動作するわけではありません。他の多くはリージョンでの分離を提供します。このようなケースでは、リージョンサービスの可用性がワークロードに必要な全体的な可用性をサポートしていない場合、マルチリージョンのアプローチを検討してみましょう。各リージョンでは、スペアリングと同等のサービスの分離インスタンス化を提供しています 

 マルチリージョンサービスの構築を容易にするさまざまなサービスがあります。例: 
+  [Amazon Aurora Global Database](https://aws.amazon.com/rds/aurora/global-database/) 
+  [Amazon DynamoDB グローバルテーブル](https://aws.amazon.com/dynamodb/global-tables/) 
+  [Amazon ElastiCache (Redis OSS) — グローバルデータストア](https://aws.amazon.com/elasticache/redis/global-datastore/) 
+  [AWS Global Accelerator](https://aws.amazon.com/global-accelerator/) 
+  [Amazon S3 クロスリージョンレプリケーション](https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication.html) 
+  [Amazon Route 53 Application Recovery Controller](https://aws.amazon.com/route53/application-recovery-controller/) 

 このドキュメントでは、マルチリージョンワークロードを構築する戦略について詳しく説明しませんが、マルチリージョンアーキテクチャの可用性のメリットと、希望する可用性目標を達成するために必要な追加コスト、複雑さ、運用慣行について比較検討する必要があります。

 依存関係の MTBF を増やす次の方法は、ワークロードを静的に安定させるように設計することです。例えば、製品情報を提供するワークロードがあるとします。カスタマーが製品をリクエストすると、サービスは外部のメタデータサービスに製品詳細の取得をリクエストします。その後、ワークロードはその情報をすべてユーザーに返します。

 ただし、メタデータサービスが利用できない場合、カスタマーからのリクエストは失敗します。代わりに、メタデータをサービスのローカルに非同期でプルまたはプッシュして、リクエストへのレスポンスに使用できます。これにより、重要なパスからメタデータサービスへの同期呼び出しが不要になります。

 さらに、メタデータサービスが利用できなくてもサービスは利用できるため、可用性計算の依存関係としてそれを削除できます。この例は、メタデータは頻繁に変更されず、古いメタデータを提供する方がリクエストが失敗するよりも良いという前提に基づいています。別の同様の例として、DNS の [serve-stale](https://www.rfc-editor.org/rfc/rfc8767) があります。これは、TTL の有効期限が過ぎてもデータをキャッシュに保持し、更新された回答がすぐに利用できない場合のレスポンスに使用できます。

 MTBF を増やす最後の方法は、依存関係の MTBF を増やして障害による影響の範囲を狭めることです。前述のとおり、失敗は二者択一のイベントではありません。障害には程度があります。これがモジュール化の効果です。障害は、そのコンテナによって処理されているリクエストまたはユーザーだけに抑えられます。

 その結果、イベント中の障害が減り、影響の範囲が制限されるため、最終的にはワークロード全体の可用性が向上します。

## 一般的な影響の原因の削減
<a name="reducing-common-sources-of-impact"></a>

 1985年、Jim Gray は、Tandem Computers での研究中に、障害は主にソフトウェアとオペレーションの 2 つの要因によって引き起こされていることを発見しました。(Jim Gray の「[Why Do Computers Stop and What Can Be Done About It? (コンピューターはなぜ停止するのか、そしてそれに対して何ができるのか？)](https://www.hpl.hp.com/techreports/tandem/TR-85.7.pdf)」(1985 年 6 月、Tandem Technical Report 85.7 を参照)。それから 36 年経った今でも、これは真実です。テクノロジーの進歩にもかかわらず、これらの問題に対する簡単な解決策はなく、主な障害の原因は変わっていません。このセクションの冒頭では、ソフトウェアの障害への対処について説明しました。ここではオペレーションと障害の発生頻度の削減に焦点を当てます。

### 機能と比較した安定性
<a name="stability-compared-with-features"></a>

 [分散システムの可用性](distributed-system-availability.md) セクションのソフトウェアとハードウェアの障害発生率のグラフをもう一度見てみると、各ソフトウェアリリースに不具合が追加されていることがわかります。つまり、ワークロードに何らかの変更を加えると、障害のリスクが高まります。これらの変更は通常、当然の結果をもたらす新機能のようなものです。可用性の高いワークロードでは、新機能よりも安定性が優先されます。したがって、可用性を向上させる最も簡単な方法の 1 つは、デプロイの頻度を減らすか、提供する機能を減らすことです。デプロイの頻度が高いワークロードは、そうではないワークロードよりも本質的に可用性が低くなります。ただし、機能を追加できないワークロードはカスタマーの需要に追いついておらず、時間が経つにつれて有用性が低下する可能性があります。

 では、どうすればイノベーションを続け、安全に機能をリリースできるのでしょうか。その答えは標準化です。正しいデプロイの方法は何ですか。どのようにデプロイを発注しますか。テストの基準は何ですか。ある段階から別の段階までの待機時間はどれくらいですか。ユニットテストはソフトウェアコードを十分にカバーしていますか。これらの疑問は標準化によって解消されます。また、負荷テストを実施しなかったり、デプロイ段階をスキップしたり、あまりにも多くのホストに早期に展開しすぎることによって引き起こされる問題を防止できます。

 標準化を実装する方法は自動化です。これにより、人為的なミスの可能性が減り、コンピューターは得意なこと、つまり毎回同じことを同じ方法で繰り返すことが可能になります。標準化と自動化を両立させるには、目標を設定します。目標は、手動による変更なし、条件付き認証システムのみによるホストアクセス、すべての API の負荷テストの記述などです。運用上の優秀性は文化的規範であり、これには大規模な変更が必要になる場合があります。目標に対するパフォーマンスを確立して追跡することは、ワークロードの可用性に幅広い影響を与える文化的な変化を促進します。[AWS Well-Architected 運用上の優秀性の柱](https://docs.aws.amazon.com/wellarchitected/latest/operational-excellence-pillar/welcome.html)は、運用上の優秀性を達成するための包括的なベストプラクティスを提供します。

### オペレーターの安全
<a name="operator-safety"></a>

 障害を引き起こす運用上のイベントのその他の主な原因は人です。人間は間違いを犯します。間違った認証情報を使用したり、間違ったコマンドを入力したり、Enter キーを押すのが早すぎたり、重要な手順を見逃したりする可能性があります。手動によるアクションを継続的に実行すると、エラーが発生し、障害につながります。

 オペレーターのエラーの主な原因の 1 つは、わかりにくい、直感的でない、または整合性のないユーザーインターフェイスです。Jim Gray は 1985 年の研究で、「オペレーターに情報を求めたり、何らかの機能の実行を求めたりするインターフェースは、シンプルで整合性があり、オペレーターに対する耐障害性がなければならない」とも述べています。(Jim Gray の「[Why Do Computers Stop and What Can Be Done About It? (コンピューターはなぜ停止するのか、そしてそれに対して何ができるのか？)](https://www.hpl.hp.com/techreports/tandem/TR-85.7.pdf)」(1985 年 6 月、Tandem Technical Report 85.7 を参照)。この洞察は今でも真実です。わかりづらい、または複雑なユーザーインターフェイス、確認や指示の欠如、あるいは単に不親切な人による言葉が原因で、オペレーターが間違ったことをする原因となった例は、過去 30 年間にわたり業界全体で数多く存在します。

**ルール 12**  
オペレーターが正しいことを簡単に行えるようにします。

### 過負荷の防止
<a name="preventing-overload"></a>

 最後に影響に寄与する一般的な因子は、カスタマー、つまりワークロードの実際のユーザーです。正常なワークロードは使用されるようになりますが、その使用量がワークロードのスケールする能力を上回ることもあります。ディスクがいっぱいになり、スレッドプールが使い果たされ、ネットワーク帯域幅が飽和状態になり、データベース接続の制限に達するなど、さまざまなことが起こり得ます。

 これらを解消する確実な方法はありませんが、運用健全性メトリクスを通じて容量と使用率を積極的に監視することで、障害が発生する可能性がある場合、早期に警告を発することができます。[負荷分散](https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload)、[回路ブレーカー](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/design-interactions-in-a-distributed-system-to-mitigate-or-withstand-failures.html)、[エクスポネンシャルバックオフとジッターによる再試行](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/)などの手法は、影響を最小限に抑えて成功率を高めるのに役立ちますが、このような状況では障害はまだ解消されていません。運用健全性メトリクスに基づく自動スケーリングは、過負荷による障害の頻度を減らすのに役立ちますが、使用率の変化に対して十分迅速に対応できない場合があります。

 カスタマーが継続的に利用可能な容量を確保する必要がある場合は、可用性とコストのバランスを取る必要があります。容量不足が可用性の低下につながらないようにする 1 つの方法として、各カスタマーにクォータを設定し、割り当てられたクォータの 100% を提供するようにワークロードの容量をスケーリングすることです。カスタマーがクォータを超えるとスロットリングされますが、これは障害ではなく、可用性にも影響しません。また、十分な容量を確保するためには、カスタマーベースを綿密に追跡し、将来の使用率を予測する必要があります。これにより、カスタマーによる過剰消費によって、ワークロードで障害が発生するような状況を回避できます。
+  [Amazon Builders' Library — 負荷分散による過負荷の回避](https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload/) 
+  [Amazon Builders' Library — マルチテナントシステムの公平性](https://aws.amazon.com/builders-library/fairness-in-multi-tenant-systems) 

例えば、ストレージサービスを提供するワークロードについて検証してみましょう。ワークロード内の各サーバーは 1 秒あたり 100 回のダウンロードをサポートでき、カスタマーには 1 秒あたり 200 回のダウンロードというクォータが提供され、500 人のカスタマーがいます。この数のカスタマーをサポートするには、サービスは 1 秒あたり 100,000 ダウンロードの容量を提供する必要があり、それには 1,000 台のサーバーが必要です。いずれかのカスタマーがクォータを超えると、そのカスタマーはスロットリングされ、他のすべてのカスタマーに十分な容量が確保されます。これは、作業単位を拒否せずに過負荷を回避する 1 つの方法の簡単な例です。