復元力を高めるためのカオス エンジニアリングとフォールト挿入

2020年7月27日 に投稿済み

Chief Technology Officer, Microsoft Azure

“この『信頼性を高める』ブログ シリーズを昨年 7 月の投稿でスタートしたときに、進行中のさまざまなイニシアティブを紹介しました。プラットフォームの可用性向上を目的とするこれらのイニシアティブは、信頼できるクラウド サービスを提供するという私たちのお約束の一部として行っているものです。その中で言及した領域の 1 つがフォールト挿入ですが、私たちはこれを、システムが障害発生時にも設計どおりに動作することの検証に使うことが増えています。本日は、この領域のプリンシパル プログラム マネージャー Chris Ashton に "カオス エンジニアリング" という大きな概念について、Azure での例も含めて説明してもらいます。私たちは既にこの手法を、ストレス テストや合成ワークロードと組み合わせて、アプリケーションとサービスの復元力向上を目的として使用しています。” - Mark Russinovich (Azure CTO)


 

大規模な分散型アプリケーションの開発はかつてないほど簡単になりましたが、落とし穴があります。確かに、インフラストラクチャはパブリック クラウドのおかげでものの数分で提供され、言語の選択肢も多く、利用可能なオープンソース コードの量は膨大であり、マーケットプレースには開発の基礎となるコンポーネントやサービスがあふれています。確かに、ソリューション アーキテクチャと設計に手を貸してくれる優れた参照ガイドがあります。その代表が Azure Well-Architected Framework で、ほかにもさまざまなリソースが Azure アーキテクチャ センターにあります。しかし、アプリケーションの開発が簡単になる一方で、依存関係のトラブルによる影響のリスクも増大しています。まれにではありますが、開発者がコントロールできる範囲を越えた機能停止はいつ起きてもおかしくありません。開発したシステムの依存先でインシデントが起きることや、鍵となるサービス/システムの応答が遅くなることもあるでしょう。ある領域での小さなトラブルが、別の領域では拡大したり長期的な副作用を引き起こしたりすることもあります。このようなサービスのトラブルは開発者の生産性を奪い、顧客の信頼に悪影響を及ぼし、ビジネスの損失を招き、さらには組織の業績にも衝撃を与える可能性があります。

モダンなアプリケーションと、その構築の基礎となるクラウド プラットフォームは、障害に備えて設計され、継続的に検証されていることが必要です。開発者は既知と未知の障害条件を考慮する必要があり、アプリケーションとサービスのアーキテクチャは冗長性を持つように設計されることが必要であり、アルゴリズムには再試行とバックオフのメカニズムが必要です。システムは回復性を持つ必要があり、実稼働中の、頻度は低くても避けることができない機能停止やトラブルで引き起こされる状況に対応できることが必要です。本稿は、一般的な障害条件を検証する最善の方法を考えていただくことを目的としており、Microsoft が自身のシステムをどのように検証しているかを示す例も紹介します。

復元力

復元力とは、システムの正常な動作を妨げるような出来事が発生したときに、システムがグレースフルに機能を停止でき、最終的にはその状態から回復できる能力のことです。あるアプリケーション、サービス、またはプラットフォームが復元力を持っていることの検証は、障害に備えた構築と同じように重要です。個々のコンポーネントを分離した状態で信頼性を検証し、システム全体の信頼性も同程度と推論するのは簡単ですが、それが正しいとは限りません。復元力はシステム全体の特性であり、そのコンポーネントの特性ではありません。あるシステムが真の復元力を持っているかどうかを理解する最善の方法は、システム全体の復元力を、そのシステムが稼働する予定の環境で測定して理解することです。しかし、これをどのように行うか、どこから始めるかが問題です。

カオス エンジニアリングとフォールト挿入

カオス エンジニアリングとは、システムが実稼働中に遭遇することになる実際の障害や依存関係のトラブルをそのシステムに体験させることです。フォールト挿入とは、システムの堅牢性とエラー処理の検証を目的として、障害を意図的にそのシステムに注入することです。

フォールト挿入の使用とカオス エンジニアリングの全体的な適用を通して、アーキテクチャの設計者はその設計に確信を持つことができ、開発者は自分のアプリケーションの復元力を測定し、理解し、向上させることができます。同様に、サイト信頼性エンジニア (SRE) と、この領域においてチームとして説明責任を負う人は誰でも、自分のサービス レベル目標がねらいどおりであることを確実にするとともに、実稼働でのシステム正常性を監視することができます。オペレーション チームも、新しいハードウェアとデータセンターを顧客用にロールアウトする前に検証することができます。カオス手法をリリース検証に取り入れることによって、管理職を含む全員が、その組織で構築しているシステムに確信を持つことができます。

既にそうされていると思いますが、開発プロセス全体を通じて、テストは早い段階で行い、頻繁に行います。開発するアプリケーションまたはサービスを本稼働に移す準備をするときに、通常のテスト手法に従い、単体、機能、ストレス、統合の各テストを追加して実施します。必要に応じて、障害のケースに対応するテスト カバレッジを追加し、フォールト挿入を使用してエラー処理とアルゴリズムの動作を確認します。さらに大きな衝撃を与えるには、そしてここがカオス エンジニアリングが真価を発揮するところなのですが、エンドツーエンドのワークロード (たとえばストレス テスト、パフォーマンス ベンチマーク、または合成ワークロード) をフォールト挿入で増強します。本稼働の環境で実験する前に本稼働前テスト環境を用意し、開発したソリューションがどのように動作するかを安全な環境で、合成ワークロードを使って理解します。これは、実際の顧客トラフィックに影響が及ぶのを避けるためです。

検証プロセスでのフォールト挿入の健全な使用法としては、次のようなものが考えられます。

  • 新機能の検証をテスト環境で随時行う:
    テスト仮想マシン (VM) を立てて、新しいコードを隔離して実行します。既存の機能テストまたはストレス テストを実行するときに、フォールトを挿入してリモートの依存要素 (たとえば SQL Server) へのネットワーク アクセスを遮断します。これで、新しいコードがこのシナリオを正しく処理していることを証明できます。
  • CI/CD パイプライン内のフォールト挿入カバレッジ自動化 (デプロイまたは回復性ゲートを含む):
    既存のエンドツーエンドのシナリオのテスト (たとえば統合テストまたはストレス テスト) にフォールト挿入を追加します。通常の実行の後に新しいステップを 1 つ挿入して、何らかの障害を適用した状態で実行を継続するか、再度実行します。この障害追加によって、通常のテストでは見つからない問題を見つけることができ、いずれ見つかる問題についても、その発見までの時間を短縮できます。
  • インシデント修正検証とインシデント回帰テスト:
    フォールト挿入をワークロードまたは手動実行と組み合わせて、あるインシデントを引き起こすのと同じ条件を誘発します。特定のインシデント修正の検証や、インシデント シナリオでの回帰テストが可能になります。
  • 実稼働前環境での BCDR 訓練:
    データベースのフェールオーバーを引き起こす、あるいはストレージをオフラインにするような障害を BCDR 訓練で使用すると、その障害が発生したときにシステムが適切に動作することと、フェールオーバー テストのときにデータが一切失われていないことを検証できます。
  • 実稼働での Game Day:
    "Game Day" とは、機能停止またはインシデントのシミュレーションを組織的に行うものであり、その目的はシステムがその出来事を正しく処理できることの検証です。これには一般的に、監視システムの検証が含まれ、さらにインシデント中に行われる人的プロセスも検証されます。Game Day を実施するチームは、フォールト挿入ツールを利用すると、1 つの仮説シナリオを表す一連の障害を、制御された方法で発生させることができます。

一般的なリリース パイプライン

次の図は、一般的なリリース パイプラインと、フォールト挿入を使用する機会を示しています。

リリース パイプラインのカオスの機会

 

フォールト挿入への投資がより大きな成功を収めるには、次のようなコンポーネントを基礎として構築されていることが必要です。

  • 協調型デプロイ パイプライン。
  • 自動化 ARM デプロイ。
  • 合成ランナーと合成エンドツーエンド ワークロード。
  • 監視、アラート生成、ライブサイト ダッシュボード。

これらのものがそろっていれば、フォールト挿入をデプロイ プロセスに統合するときのオーバーヘッドをごく小さく抑えることができます。また、コード フローを本稼働に進めるかどうかをゲートで制御できます。

局所的なラック電力供給停止や機器の障害は、単一障害点となることが過去のインシデントの根本原因分析で判明しています。あるサービスが、本稼働環境でこのような障害の影響を受けていること、そして復元力がないことを、オンコール エンジニアは限られた時間の中で調べる必要があり、このプロセスは困難で、コストもかかります。フォールト挿入は、このような障害に対する復元力を検証するためにリリース パイプライン全体のさまざまな場面で、制御された環境と時間枠の中で使用することができます。また、明らかになった問題の調査をコード作成者が先導する機会も増えることになります。開発者がコードを変更したときや、新しいコードを追加するときは、テスト環境を作成してそのコードをデプロイし、随時実験を行います。このときに機能テストとツールを使い、障害を発生させて、依存要素をオフラインにする処理をシミュレーションします。たとえば、VM を強制終了する、サービスへのアクセスを遮断する、あるいは単にアクセス許可を変更するという方法があります。ステージング環境では、同様の障害の挿入を自動化エンドツーエンド/統合テストやその他の合成ワークロードに追加できます。そのテスト結果とテレメトリを使用して、エラーの影響を特定し、ベースライン パフォーマンスと比較して、必要に応じてコード フローをブロックします。

本稼働前の、いわゆるカナリア環境では、自動化ランナーとともに障害を使用します。この場合も、依存要素へのアクセスをブロックする、またはその要素をオフラインにするような障害です。その機能停止が観察されたかどうかを、監視、アラート生成、ライブサイト ダッシュボードを使用して検証するとともに、システムがその問題に反応して問題の影響を解消したか、つまり復元力を示したかどうかを検証します。この同じ環境で、SRE やオペレーション チームが事業継続/ディザスター リカバリー (BCDR) 訓練を行うこともできます。フォールト挿入を使用してストレージまたはデータベースをオフラインにしますが、ここでもシステムのメトリックを監視して復元力とデータ整合性を検証します。これと同様のカナリア アクティビティを、実際の顧客トラフィックがある運用環境で実行することもできますが、顧客に影響が及ぶ可能性が高くなるため、このことを行う場合はあらかじめ、パイプライン内の早い段階でフォールト挿入を利用して検証しておくことをお勧めします。このような習慣を確立してフォールト挿入をデプロイ パイプラインに取り入れると、体系的かつコントロールされた復元力検証が可能になり、その結果として問題の軽減とアプリケーションの信頼性向上を、顧客に影響を与えることなく実現できるようになります。

Microsoft でのフォールト挿入

Microsoft では、いくつかのチームが検証パイプラインと自動テスト パスの早い段階でフォールト挿入を採用しています。さまざまなチームが、ストレス テスト、パフォーマンス ベンチマーク、または合成ワークロードを自動化検証ゲートで通常どおりに実施してベースラインを確立しています。そのワークロードをもう一度実行し、今度は障害を適用します。たとえば、CPU への過負荷、ディスク IO のジッター、ネットワーク待機時間です。ワークロードの結果を監視し、テレメトリをスキャンし、クラッシュ ダンプをチェックし、サービス レベル インジケーター (SLI) をサービス レベル目標 (SLO) と比較して影響を測定します。結果が不合格と判定された場合は、コード フローをパイプライン内の次のステージに進めることはできません。

Microsoft ではその他にも、フォールト挿入が通常の事業継続/ディザスター リカバリー (BCDR) 訓練や、Game Day で使用されています。チームによっては、毎月、四半期ごと、または半年ごとに BCDR 訓練を実施しており、フォールト挿入を使用して大規模災害 ("ディザスター") を発生させて回復プロセスを検証するとともに、アラート生成、監視、ライブ サイトのプロセスを検証しています。これは多くの場合、実際の顧客のトラフィックに対してではなく、実稼働前のカナリア環境で行われます。Game Day を実行するチームもあります。これは、仮説シナリオを 1 つ取り上げて (たとえば、過去のインシデントの再現)、フォールト挿入を利用して実施します。この場合の障害は、破壊性が高いこともあります。たとえば VM をクラッシュさせる、ネットワーク アクセスを停止させる、データベース フェールオーバーを発生させるといったものであり、さらにはデータセンター全体をオフラインにすることのシミュレーションなども行っています。ここでも、通常のライブ サイト監視とアラート生成が使用され、DevOps とインシデント管理のプロセスも検証されます。関係者全員の負担を考慮して、これらのアクティビティは一般的に、夜間や週末ではなく通常の業務時間内に実行されます。

Microsoft のオペレーション チームも、フォールト挿入を使用して新しいハードウェアを検証し、その後でお客様用にデプロイしています。訓練を実施するときは、特定のラックまたはデータセンターへの電力供給を停止し、監視とバックアップのシステムが期待どおりに動作しているかどうかを観察します。

Microsoft がカオス エンジニアリングの原則とフォールト挿入の手法を使用しているのは、私たちが送り出す製品の復元力、そして信頼を高めるためです。これらを使用して、お客様に届けるアプリケーションを検証し、開発者の皆様に公開しているサービスを検証しています。これらは、基礎となる Azure プラットフォーム自体の検証にも、新しいハードウェアをデプロイする前のテストにも使用されています。個別に、そして一体となって、これらは Azure プラットフォームの全体的な信頼性に寄与するとともに、Microsoft のサービスすべての品質を高めています。

意図しない結果

フォールト挿入は強力なツールであり、使うときは注意が必要です。テストまたは実稼働前の環境に取り入れた障害が本稼働にも影響することがないように、セーフガードを用意する必要があります。他のコンポーネントやエンド カスタマーへの影響を最小限に抑えるために、障害シナリオの影響が及ぶ範囲 ("爆発半径") を限定してください。障害を挿入する機能へのアクセスも制限してください。これは事故を防ぐためであり、悪意のある目的でハッカーに使用されるのを防ぐためでもあります。フォールト挿入を実稼働環境で使用することもできますが、慎重に計画し、まず実稼働前環境でテストし、爆発半径を限定するとともに、実験を必要に応じてすぐに停止できるようにフェールセーフ機構を設けてください。1986 年のチェルノブイリ原発事故は、フォールト挿入訓練を誤るとどうなるかを示す、身の引き締まる思いのする例の一つです。システムを意図しない結果から絶縁するよう注意してください。

サービスとしてのカオス?

Mark Russinovich がこのブログ記事で述べているように、私たちのゴールはネイティブのフォールト挿入サービスをお客様やパートナーの皆様が利用できるようにすることです。これで、同じ検証をご自身のアプリケーションやサービスに対して実施できるようになるからです。これは大きな可能性を秘めた領域であり、クラウド サービスの信頼性を向上させるとともに、まれではあるものの避けられないトラブルの影響を軽減することができます。この領域では多数のチームが、さまざまな興味深いことを行っており、私たちはこれらの独立したツールとフォールトをまとめて提供する最善の方法を探っているところです。これが実現すれば、社内で Azure のサービスや、Azure 上に構築されるサービス (たとえば Microsoft 365、Microsoft Teams、Dynamics) を開発する作業が楽になり、そしていずれはお客様とパートナーの皆様が同じツールを使って、ご自身のアプリケーションやソリューションに大打撃を与える (そして最終的にその復元力を高める) ことができるようになるでしょう。