OSDI 2020
## Abstract
大規模なクラウドサービスでは、毎日何百もの設定変更が本番システムに適用されます。このような速度では、設定変更が本番環境の障害の主な原因となることは避けられません。既存の誤設定検出技術や設定検証技術は、設定値をチェックするだけです。これらの技術では、コードの失敗や隠れた制約の違反など、一般的に失敗の原因となるタイプの構成変更を検出できません。
ctestsは、失敗を誘発する設定変更を検出し、本番環境の失敗を防ぐための新しいタイプのテストです。ctestsの背景にある考え方はシンプルで、本番環境システムの構成をソフトウェアのテストに接続することで、構成の変更を、その変更の影響を受けるコードのコンテキストでテストできるようにしています。そのため、ctestは、眠っているソフトウェア・バグや多様な誤設定を引き起こす構成変更を検出することができます。
本研究では、成熟したシステムに存在する多くのテストを変換してctestを生成する方法を示します。ここでの主な課題は、ctestで再利用可能なテスト・ロジックやオラクルを自動的に特定することです。我々は、5つのクラウドシステムの既存のテストから何千ものctestを生成しました。
その結果、ctestは、障害を引き起こす設定変更を展開前に検出するのに有効であることがわかった。我々は、実世界の障害を誘発する設定変更、注入された誤設定、および公開されたDockerイメージからデプロイされた設定ファイルについてctestを評価した。ctestsは、実世界の障害を誘発する設定変更や、デプロイされたファイルの誤設定を効果的に検出します。
## 1 Introduction
### 1.1 Motivation
大規模なクラウドサービスやインターネットサービスは急速に進化し、毎日数百から数千の構成変更を本番システムに展開しています[35, 38, 53, 55]。例えば,Facebook では,コード変更の頻度を上回る数千の構成変更が毎日コミットされています [55].また,Google や Azure などの他のクラウドサービスでも,頻繁に設定変更が行われています [9, 10, 38].
構成変更の速度が速いため、構成に起因する障害が発生する可能性があります。例えば,Google の主要な本番サービスでは,欠陥のある設定がサービス中断の第 2 の原因となっています [5].Facebookでは,大規模な停止を含むサービスレベルのインシデントの16%が設定変更によって引き起こされています[54].他のクラウドシステムでも,構成に起因する障害の深刻さと有病率は同様のレベルで発生しています [19, 34, 40, 42, 74].
何百もの構成起因のインシデントを分析した我々の経験によると,障害を引き起こす構成変更は,些細なミス(例:タイプミス)によって引き起こされることはほとんどありません.この稀なケースは、変更のレビューと検証を強制するDevOpsプラクティスに起因しています[6, 27, 55]。その結果、構成に起因する障害の根本原因は些細なものではなく、変更された構成ではなく、プログラムに存在することが多いのです。一般的に障害が発生するのは、有効な設定変更が眠っていたソフトウェアのバグを露呈させた場合[55]と、設定変更が文書化されていない隠れた設定制約に違反した場合です。前者の根本原因はプログラムにありますが、後者は多くの場合、構成の設計または実装の欠陥が原因です[69]。構成変更のレビューと検証だけでは,これらの根本原因に起因する障害を検出することは困難です.
研究者たちは、いくつかの構成の検証および誤構成の検出技術を提案しています[70]。これらの技術には、バリデータを実装するための新しい言語やフレームワーク [6, 27, 55]、機械学習や文書分析を使用して構成値の正しさのルールを推論する検出技術 [38, 43, 44, 49, 50, 59, 61, 75, 77]、およびタイプチェッカーや制約チェッカー [48, 67]などがあります。これらの技術は成功していますが、制限があります。
- 既存の技術は設定値をチェックするだけなので、コードの失敗の原因となる設定変更を検出できません。
- 既存の技術では、構文的にも意味的にも有効な値を持っているにもかかわらず、予期せぬ動作を引き起こす「合法的な設定ミス」[71]を検出できる技術はほとんどありません。
- 人間が書いたルールや機械が学習したルールでは、しばしば微妙でバージョン固有の[78]、矛盾した[69]構成要件をチェックするのはコストがかかり、困難です。
### 1.2 Contributions
ここでは、本番環境での障害を防止するために、障害を引き起こす設定変更を検出する新しいタイプのテストであるctestsを紹介します。
Ctestsは、ソフトウェアのテストと本番システムの構成を結びつけるという、シンプルで効果的なアプローチをとっています。このようにして、ctest は構成の変更を、その変更の影響を受けるコードのコンテキストでテストすることができます。テストのパラメータは、システム構成のパラメータのセットによって決まります。ctest を実行すると、各入力パラメータに本番環境の設定値または本番環境にデプロイされる設定値がインスタンス化されます。通常のソフトウェアテストと同様に、ctestはシステムコードを実行し、プログラムの動作が特定の特性(正しさ、パフォーマンス、セキュリティなど)を満たすことを保証します。テストには、ユニットテスト、統合テスト、システムテストなどがあります。
既存のソフトウェアテスト技法は、テストと実際の生産システムの構成を結びつけるものではない。むしろ、既存のテスト技術は、構成値の組み合わせの膨大な空間を系統的またはランダムに探索することで、可能な構成をサンプリングしています[37]。系統的な探索は,組合せ爆発のために法外なコストがかかることがあり[39],ランダムな探索では,生産障害の原因となる問題のある値をすべてカバーできる確率が低くなります.Ctestsは、系統的な探索のコストとランダムな探索のカバー率の低さの両方を持っていません。テストを本番システムの構成に結びつけることで、ctestは障害を引き起こす構成を効果的に検出できます。
テストは、システム全体の構成をテストすることも、構成ファイルの "差分 "という形で構成を少しずつ変更することもできます。当社のctestインフラストラクチャ(§3参照)は、すべてのctestを再実行するのではなく、設定変更に関連するctestのみを選択的に実行することをサポートしています。選択的にctestを実行することで、テスト時間を短縮することができます。実際の設定変更では、わずか数個の設定値しか変更されません[55]。
本論文では、成熟したソフトウェアプロジェクトにおいて、既存のテストや豊富なテストを変換してctestを生成する方法を紹介しています。主な課題は、ctest に変換可能なテスト・ロジックとオラクルを自動的に特定することです。既存のテスト・ロジックは、特定の設定値を前提としている場合があります。このような仮定は、暗黙的なもの(デフォルト値を仮定)と明示的なもの(特定の値をハードコーディング)があります。そのため、素朴なパラメータ設定では、必ずしも有効なctestを生成できません。
この変換では、特定の設定値を前提としたテストを除外する意図を識別し、尊重します。まず、テストコードで明示的に値が再割り当てされている構成パラメータは、テストの入力パラメータセットから除外します。次に、候補となるテストで使用されるパラメータの値を変化させて、対応するテスト出力を観察します。テストの中で値がハードコードされているパラメータは、有効な値であっても異なる値ではテストが失敗するため、除外します。テストからctestへの変換はツールチェーンで機械化されており、5つのクラウドシステムの既存のテストスイートを変換して7,974個のctestを生成することに成功しました。
Ctests は、既存の設定検証および誤設定検出技術の以下のような制限に対応しています。
- Ctests は、障害の根本原因がコードにある場合に、障害を誘発する設定変更を検出することができます。
- Ctests は、予期せぬシステムの動作を捕捉することで、合法的な設定ミスを検出することができます。
- Ctestsは既存のテストから生成することができ、ルールの学習やコード化に高いコストをかける必要がありません。
我々の結果は、ctestsが、障害を引き起こす設定変更を本番環境に展開する前に効果的に検出できることを示している。我々は、64の実世界の構成に起因する障害、エラー・インジェクション・ルールによって生成された1,055の多様な誤設定、および公開されているDockerイメージからデプロイされた92の構成ファイルを用いてctestsを評価しました。
Ctestsは、実世界で発生した障害の96.9%において、障害を誘発する設定を検出しました。これらの実世界の障害を検出したctestは、障害が報告されたシステムの古いバージョンのテストから変換されたものでした。つまり、ctests はこれらの障害をより早い時期に検出することができたのである。また、テストでは、7つのデプロイされたファイルから10個の設定ミスを検出しました。さらに,テストの生成過程では,私たちが報告した後にユーザが気づいたバグを含め,14個の未知のバグを発見しました[24].開発者は,この14個のバグのうち12個を確認し,10個を修正した.
要約すると、本稿は以下のような貢献をしている。
- Ctestsは、障害を引き起こす設定変更を検出するためのシンプルで効果的なアプローチです。
- 成熟したシステムに存在する多くのテストを変換してctestを生成する方法を紹介します。
- ctestは、テスト中に、実世界の構成に起因する障害を効果的に早期に検出できることを示す。ここでは、本番環境での障害を防止するために、障害を引き起こす設定変更を検出する新しいタイプのテストであるctestsを紹介します。
Ctestsは、ソフトウェアのテストと本番システムの構成を結びつけるという、シンプルで効果的なアプローチをとっています。このようにして、ctest は構成の変更を、その変更の影響を受けるコードのコンテキストでテストすることができます。テストのパラメータは、システム構成のパラメータのセットによって決まります。ctest を実行すると、各入力パラメータに本番環境の設定値または本番環境にデプロイされる設定値がインスタンス化されます。通常のソフトウェアテストと同様に、ctestはシステムコードを実行し、プログラムの動作が特定の特性(正しさ、パフォーマンス、セキュリティなど)を満たすことを保証します。テストには、ユニットテスト、統合テスト、システムテストなどがあります。
既存のソフトウェアテスト技法は、テストと実際の生産システムの構成を結びつけるものではない。むしろ、既存のテスト技術は、構成値の組み合わせの膨大な空間を系統的またはランダムに探索することで、可能な構成をサンプリングしています[37]。系統的な探索は,組合せ爆発のために法外なコストがかかることがあり[39],ランダムな探索では,生産障害の原因となる問題のある値をすべてカバーできる確率が低くなります.Ctestsは、系統的な探索のコストとランダムな探索のカバー率の低さの両方を持っていません。テストを本番システムの構成に結びつけることで、ctestは障害を引き起こす構成を効果的に検出できます。
テストは、システム全体の構成をテストすることも、構成ファイルの "差分 "という形で構成を少しずつ変更することもできます。当社のctestインフラストラクチャ(§3参照)は、すべてのctestを再実行するのではなく、設定変更に関連するctestのみを選択的に実行することをサポートしています。選択的にctestを実行することで、テスト時間を短縮することができます。実際の設定変更では、わずか数個の設定値しか変更されません[55]。
本論文では、成熟したソフトウェアプロジェクトにおいて、既存のテストや豊富なテストを変換してctestを生成する方法を紹介しています。主な課題は、ctest に変換可能なテスト・ロジックとオラクルを自動的に特定することです。既存のテスト・ロジックは、特定の設定値を前提としている場合があります。このような仮定は、暗黙的なもの(デフォルト値を仮定)と明示的なもの(特定の値をハードコーディング)があります。そのため、素朴なパラメータ設定では、必ずしも有効なctestを生成できません。
この変換では、特定の設定値を前提としたテストを除外する意図を識別し、尊重します。まず、テストコードで明示的に値が再割り当てされている構成パラメータは、テストの入力パラメータセットから除外します。次に、候補となるテストで使用されるパラメータの値を変化させて、対応するテスト出力を観察します。テストの中で値がハードコードされているパラメータは、有効な値であっても異なる値ではテストが失敗するため、除外します。テストからctestへの変換はツールチェーンで機械化されており、5つのクラウドシステムの既存のテストスイートを変換して7,974個のctestを生成することに成功しました。
Ctests は、既存の設定検証および誤設定検出技術の以下のような制限に対応しています。
- Ctests は、障害の根本原因がコードにある場合に、障害を誘発する設定変更を検出することができます。
- Ctests は、予期せぬシステムの動作を捕捉することで、合法的な設定ミスを検出することができます。
- Ctestsは既存のテストから生成することができ、ルールの学習やコード化に高いコストをかける必要がありません。
我々の結果は、ctestsが、障害を引き起こす設定変更を本番環境に展開する前に効果的に検出できることを示している。我々は、64の実世界の構成に起因する障害、エラー・インジェクション・ルールによって生成された1,055の多様な誤設定、および公開されているDockerイメージからデプロイされた92の構成ファイルを用いてctestsを評価しました。
Ctestsは、実世界で発生した障害の96.9%において、障害を誘発する設定を検出しました。これらの実世界の障害を検出したctestは、障害が報告されたシステムの古いバージョンのテストから変換されたものでした。つまり、ctests はこれらの障害をより早い時期に検出することができたのである。また、テストでは、7つのデプロイされたファイルから10個の設定ミスを検出しました。さらに,テストの生成過程では,私たちが報告した後にユーザが気づいたバグを含め,14個の未知のバグを発見しました[24].開発者は,この14個のバグのうち12個を確認し,10個を修正した.
要約すると、本稿は以下のような貢献をしている。
- Ctestsは、障害を引き起こす設定変更を検出するためのシンプルで効果的なアプローチです。
- 成熟したシステムに存在する多くのテストを変換してctestを生成する方法を紹介します。
- ctestは、テスト中に、実世界の構成に起因する障害を効果的に早期に検出できることを示す。
## 2 Background and Examples
ここでは、コンフィグレーションの値を検証する既存の技術 [6, 27, 48, 55, 67]や、特定のタイプの誤設定を検出する技術 [38, 43, 44, 49, 50, 59, 61, 62, 75, 77]の限界を、ctest がどのように解決するかについて説明します。
プログラムの動作に基づいて構成をチェックします。ctest の主な機能は、実際の構成値がプログラムの動作にどのような影響を与えるかを確認することです。この機能は、コードの不具合を引き起こしたり、眠っているバグを暴露したりするような設定変更を検出するために不可欠です。私たちの経験では、プログラムの動作をチェックすることは、(通常は不完全な)ルールに照らし合わせて設定値をチェックするよりも、障害を引き起こす設定変更を捕捉するのに有効です。
図1では、HBase [21]で実際に発生した問題を用いて、ctestの機能を説明しています。ここでは、パフォーマンスを低下させるような設定ミス(「ハンドラーが多すぎると逆効果になる[56]」)をctestが検出します。このテストは、報告されたHBaseのバージョンにある既存のテストから生成されます。このテストでは、計算されたスケジュールに対して、「ハンドラの数は設定変更の影響を受けない」という期待通りの動作をしています。問題となる値は「legal」[71]ですが、報告されたバージョンには、期待される動作を確認する検証コードがありませんでした。
![[Pasted image 20210607210757.png]]
## 8 Related Work
設定に起因する障害の深刻さと普及率の高さ [18, 19, 34, 35, 40, 42, 55, 74] により、設定ミスのトラブルシューティングとデバッグのための新しい技術が開発されました [3, 4, 46, 61-63, 73]。また,生産現場での障害を診断するための高度な技術も開発されています [10,13,30,79].Ctestsは、故障の原因となる設定変更をプロアクティブに検出し、本番での故障を未然に防ぎます。
Ctestsは、我々の先行研究であるPCheck [67]を補完するものです。PCheckはデプロイ後の技術であるにもかかわらず、ctestsとPCheck [67]を§6.1.2で比較しました。PCheckは、各設定値のデータ・フロー・パス上の記述のみを考慮するため、設定ミスしか検出できないことに注意してください。一方、ctestは、障害を誘発する一般的なタイプの設定変更である、コードのバグを暴露する有効な設定変更を検出することができます[55]。デプロイメント前とポストデプロイメントのために設計された技術には、根本的に異なる機会と課題があります。私たちの経験では,自動生成された検査コードでは,実世界の高度な設定ミスに対処することは困難です(不可能ではありません).これが、コードと設定を一緒に実行できるctestの主な動機です。しかし、PCheckのようなポストデプロイメント技術では、テスト環境と本番環境のミスマッチによる問題が発生しません。
3.2節で、ソフトウェア・テストが静的なバグ検出ツールを補完するのと同様に、ctestは構成の検証や誤構成の検出を補完するものであると述べた[6, 27, 38, 43, 44, 49, 50, 55, 59, 61, 62, 66, 67, 75, 77]。Ctests は、既存の技術では検出が困難な、障害を引き起こす設定変更を検出することができます。例えば、バグを露出させる有効な設定変更などです。自動化された検出技術の多くは、特定のタイプのミスコンにのみ焦点を当てています。例えば、Rex[38]は、ソースコードファイルと設定ファイルの間の依存関係を検出し、それらは一緒に更新されるべきです。Ctestsは、設定ミスやソフトウェアのバグに特化したものではなく、結果として生じるプログラムの動作に基づいて、障害を引き起こす設定変更を検出します。既存の検証・保護技術では、検証ルールや学習データが必要となりますが、これらは存在しないか(評価対象のシステムには存在しない)、利用できません(オンラインでルールセットや学習データが見つからない)。これに対してctestは、外部のルールセットやトレーニングデータに頼らず、既存の豊富なテストケースを活用しています。
テストはソフトウェアやシステムのテストを補完するものである。つまり、ctestは既存のテスト手法を強化し、実際に運用されている構成や、これから導入される構成に焦点を当てて、すべての可能な構成をテストすることは不可能です。テストとは、パラメータ化されたテストのことです。しかし、ctest は、従来のパラメータ化ユニットテスト (PUT) [57, 58] とは、目的、パラメータソース、生成方法が異なります。PUTの目的は、開発者が同じテストを異なる入力に対して再実行し、より多くのプログラムパスをカバーできるようにすることである。ctests の目的は、生産システムの構成をソフトウェアテストに結び付け、障害を誘発する構成の変更を見つけ ることである。PUTの入力は、開発者が指定するか、シンボリック実行によって自動的に生成されますが、ctestsの入力は、システム構成ファイルや差分から読み込まれます。