Azure Chaos Studio で始めるカオスエンジニアリング

## はじめに

この記事は、[Microsoft Azure Tech Advent Calendar 2021](https://qiita.com/advent-calendar/2021/microsoft-azure-tech) の 3 日目の記事です。

Microsoft Ignite 2021 において、Azure Chaos Studio というサービスがパブリックプレビューとなることが発表されました。（参考: [Public preview: Azure Chaos Studio - Systematically improve resilience with controlled chaos](https://azure.microsoft.com/en-us/updates/public-preview-azure-chaos-studio-systematically-improve-resilience-with-controlled-chaos/)）

しかし、この発表において「カオスエンジニアリング」という言葉を初めて聞いたという方も少なくないのではないでしょうか。

本記事では、カオスエンジニアリングの概要や必要な背景、進め方をご紹介したのち、Azure Chaos Studio を使って実際にカオスエンジニアリングを進めてみます。

※本記事の内容は、2021 年 12 月 3 日時点の情報をもとに作成されています。

## カオスエンジニアリングとは

カオスエンジニアリングとは、正常に稼働している本番環境が、障害など不安定な状況にも耐えることができるという自信をつけるための方法論のことです。意図的に障害を発生させて、自動回復システムの動作を確認し、より高い障害復旧性を持つシステムを構築します。

例えば、仮想マシンのシャットダウンや通信制限、強制フェイルオーバーを発生させ、アプリケーションがエラーを適切に処理できるかを確認します。

## カオスエンジニアリングはなぜ必要なのか

クラウドを活用した分散システムには、変化し続けるという特性があります。

例えば、クライアントからサーバに対してリクエストを送り、レスポンスが返ってくるという一連の流れにおいても、クラウド上では、クライアントコンポーネントとサーバコンポーネントとの間で通信が発生します。

システムが複雑化すればするほど、システムがとりうる振る舞いの全てのパターンを事前に予測し、テストすることは困難になってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/da5213b2-3053-f436-b5a5-1fcf1258467e.png)

## システムにおける複雑性

そもそもシステムにおける「複雑性」とは何を指すのでしょうか？

フレデリック・ブルックスの論文『[No Silver Bullet - essence and accidents of software engineering](http://worrydream.com/refs/Brooks-NoSilverBullet.pdf)』には、「ソフトウェアにおける本質的なもの（Essential）であって、偶有的なもの（Accidental）ではない」と示されています。ここから、「複雑性」とは、ソフトウェアそのものから取り除くことはできない性質であることが読み取れます。

また、上記の論文のなかで、ブルックスは、以下のように「本質的な複雑性」 (essential complexity) と「偶有的な複雑性」 (accidental complexity) を区別しています。

| 複雑性 | 説明 |
| :--- | :--- |
| 偶有的な複雑性 | ソフトウェア開発者が発生させている、解決可能な複雑さ。わかりづらい変数名や、誤った IF 文の設計など。 |
| 本質的な複雑性 | ソフトウェアが解決したい課題自体が持っている、取り除くことはできない複雑さ。入り組んだワークフロー、複雑なデータ構造など。 |

学術的な議論はここでは行いませんが、こうした複雑性の解消をするための取り組みの一つとして、「テスト」があります。

## テストとカオスエンジニアリングの違い

テストとカオスエンジニアリングの違いを、以下の表にまとめました。

| | テスト | カオスエンジニアリング |
| :--- | :--- | :--- |
| 目的 | システムにおける既知の振る舞いを確認する。 | システムにおける未知の振る舞いを確認し、課題を確認しながら、様々な問題が起こりうる本番環境において、システムを安定的に稼働し続けることができるという自信を構築する。 |
| 進め方 | 【単体テストの場合】 <br> 1. 対象のモジュールを選択 <br> 2. 特定のインプット、またはその組み合わせを入力 <br> 3. 期待された振る舞いを定義 <br> 4. 現在の実装が期待通りに動くことを確認 <br> 【結合テストの場合】 <br> 1. 全ての単体テストが終了していることを確認 <br> 2. 各モジュールを結合 <br> 3. 実装が期待通りに動くことを確認 <br> | 1. 定常状態の定義 <br> 2. 仮説の構築 <br> 3. 変数を導入し、実験 <br> 4. 対照群と実験群との間で差異があるかを確認し、文書化 <br> 5. 結果を特定し、改善

## カオスエンジニアリングの進め方

ここでは、[カオスエンジニアリングの原則](https://principlesofchaos.org/ja/)を参考に、以下のように進め方を定義します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/cd17ac7a-9789-976e-a80d-5bb7be2db99a.png)

>定常状態を乱すことが困難になればなるほど、システムの挙動がより確実になります。脆弱性が発見された場合、そのシステムの動作が顕著に現れる前に、改善の目標を立てます。

（引用: [カオスエンジニアリングの原則](https://principlesofchaos.org/ja/)）

### 1. 定常状態の定義

まずは、通常の動作を示すシステムの測定可能な指標として「定常状態」を定義します。ここで重要なのは、<b>ビジネス KPI やそれに関連する値</b>を設定することです。

例えば、Netflix 社では、「顧客がビデオストリーミングデバイスの再生ボタンを押す速度」を定常状態としています（[引用: Chaos Engineering](https://www.oreilly.com/library/view/chaos-engineering/9781492043850/)）。

定常状態の定義を考慮するときに重要なのは、『「今顧客を失っていないか？」という質問に答えられるようなビジネスに関わるメトリクスであること』です（[引用: Chaos Engineering](https://www.oreilly.com/library/view/chaos-engineering/9781492043850/)）。ただ、ビジネスに応じて定義する「顧客」は様々なため、一概にこの指針がよいとは言えないと筆者は考えています。

また、システム内部の指標（CPU 使用率など）を「定常状態」として定義するのは好ましくありません。なぜなら、ユーザーにとってシステム内部の指標は全く関心がないためです。定常状態には、<b>顧客体験に関係する指標</b>を定義するのがよいです。

### 2. 仮説の構築

次に、実験が開始された後も定常状態が継続する仮説を立てます。テストのように、あらかじめ全ての障害パターンを洗い出すことは不可能なため、仮説を構築する、というわけです。

ここで立てた仮説は、「システムに障害が発生しても、顧客にサービス提供が継続できる」ことを意味します。例えば、<b>「東日本リージョンの仮想マシンが停止した状況でも、お客様は快適にサービス利用を継続できる」</b>といったものです。こうした仮説については、<b>関係者とあらかじめ十分に協議することが大切</b>とされています。

詳細は後述しますが、ここで構築する仮説については、文書化しておいた方がよいと筆者は考えます。文書化するにあたり、様々な関係者を巻き込むことができるので、カオスエンジニアリングについて社内に周知するという面においても、ドキュメントを作成するのがよいでしょう。

また、「明文化されていないものの、通常の運用時に見つかっている問題点」や、「顕在化しているシステム上の問題点」については、これ以降の手順を進めず、改善を行う必要があります。

### 3. 変数を導入し、実験

ここから、変数を導入し、実験を行います。ここでいう「変数」とは、<b>現実世界を反映する事象</b>を指します。

例えば、サーバーダウンのようなハードウェア障害、不正な応答のようなソフトウェア障害、トラフィックやスケーリングイベントの急増などのイベントなど、定常状態を破壊し得る事象のことです。

また、システムを対照群と実験群に分け、実験群にのみ変数を導入します。対照群と実験群に分ける際には、Infrastructure as Code (IaC) ツールを使って同一の環境を簡単に再現することが可能です。Azure では、ARM Template や Terraform などを駆使することができます。IaC に関する詳細は、[Docs: コードとしてのインフラストラクチャ](https://docs.microsoft.com/ja-jp/dotnet/architecture/cloud-native/infrastructure-as-code) を参照してください。

### 4. 対照群と実験群との間で差異があるかを確認し、文書化 / 5. 結果を特定し、改善

実験結果について、対照群と実験群との間で定常状態に差異があるかを確認し、仮説の検証を行います。

仮説が成り立たなかった（お客様のサービス利用継続に支障が出る）場合、「学び」をもとにシステム改善を計画します。一方、仮説が成り立った（お客様のサービス利用継続に問題がない）場合、システムの安定性に対する自信が生まれます。

このように、成り立たない仮説を減らしていくことで、システムの安定性に対する自信をつけていく取り組みが、カオスエンジニアリングです。

## Azure Chaos Studio

Azure Chaos Studio は、Azure で構成されるワークロードに対して意図的に障害をインジェクションして回復性などの確認を行うことが出来る、マネージドサービスです。2021 年 12 月 3 日現在、パブリックプレビューのサービスとなっています。

Azure Chaos Studio を使って引き起こすことができる障害一覧は、[Docs: Chaos Studio の障害およびアクション ライブラリ](https://docs.microsoft.com/ja-jp/azure/chaos-studio/chaos-studio-fault-library) にまとまっています。

## 実験

ここまでの流れを実践するため、 Azure Chaos Studio を使って簡単な実験を行ってみます。

### 検証環境

今回は、以下のような検証環境とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/717304d1-c5fe-a480-7294-5c73337d3859.png)

アプリケーションゲートウェイを配置し、バックエンドで Nginx をデプロイした仮想マシンを 2 台稼働させます。ここでは、検証用として、各仮想マシンの区別がつくように、Nginx のトップページに仮想マシン名を付与しています。例えば、【nginx-001】で稼働する Nginx のトップページには『Welcome to nginx on nginx-001』と表示させています。
また、仮想マシンには Private IP アドレスのみを割り当て、 Nginx のインストール時は Azure Bastion を踏み台サーバとして使用します。
クライアントからのアクセスを想定し、Azure Functions の関数に、【アプリケーションゲートウェイに対して毎秒アクセスを行う関数】を 作成します。
管理者は、Azure Monitor を通じて Application Gateway のパフォーマンスを監視します。

実験においては、対照群と実験群のリソースをそれぞれ作成する必要があります。上述の通り、同一構成のリソースを手軽に用意するためには、 Infrastructure as Code (IaC) の活用が欠かせません。今回は、Azure リソースのデプロイに ARM Template を活用します。

今回使用する ARM Templateは [GitHub](https://github.com/kohei3110/Chaos-Studio-Hands-on-Lab) にあげています。

同一の環境を使って検証される場合は、リソースのデプロイ完了後、以下 2 つの作業を実施してください。


#### A) NGINX のインストール

Azure Bastion 経由で仮想マシンに接続し、NGINX をインストールしてください。
NGINX は、下記コマンドでインストール可能です。

```shell
sudo apt update
sudo apt install nginx -y
```

#### B) Application Gateway バックエンドプール追加

Application Gateway のバックエンドプールに、NGINX をインストールした仮想マシンを指定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/e80c483d-b0bd-e7a5-fb9a-d6ae02b72c1d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/64f6ea02-0015-4eef-55ad-bb69114ff400.png)


### 実験計画

ここでは、各フェーズにおいて以下のような計画を立てます。

※なお、今回は非常にざっくりとした計画になっていますが、実運用する際は、関係者を巻き込んで、より精緻な計画を立てることを推奨します。

### 1. 定常状態の定義

まずは、通常の動作を示すシステムの測定可能な指標として「定常状態」を定義します。今回は、ビジネス要件に関連する値の例として、<b>Nginx のトップページを閲覧可能な割合が、全リクエストの 95 % 以上である</b>と定義します。

### 2. 仮説の構築

次に、「システムに障害が発生しても、顧客にサービス提供が継続できる」という仮説を構築します。ここでは、<b>仮想マシン【nginx-001】が停止した場合も、クライアントからのリクエストは仮想マシン【nginx-002】にルーティングされ、定常状態を維持できる</b>という仮説を立てます。

### 3. 変数を導入し、実験

いよいよ Azure Chaos Studio の登場です。ここでの「変数」は、<b>仮想マシン【nginx-001】の停止</b>になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/df695997-c711-5c73-aaba-dcfecffd18dd.png)


#### 3-1. ターゲットのオンボーディング

Azure Chaos Studio では、実験を作成する前に、実験を行うリソースを<b>ターゲット</b>としてオンボーディングする必要があります。

Azure Chaos Studio では、以下の 2 種類の<b>ターゲット</b>が定義されています。

| ターゲット | 説明 |
| :--- | :--- |
| 1. サービス直接ターゲット | Azure リソースに対して直接障害が実行される対象リソース。エージェントのインストールは不要。 |
| 2. エージェントベースのターゲット | Chaos Studio エージェントを仮想マシンまたは仮想マシンスケールセットにインストールする必要がある障害が実行される対象リソース。 |

（参考: [Docs: Azure Chaos Studio でのターゲットと機能](https://docs.microsoft.com/ja-jp/azure/chaos-studio/chaos-studio-targets-capabilities)）

今回は、仮想マシン【nginx-001】に対して、サービス直接ターゲットを有効化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/56c7f93a-f0e1-ecd9-1818-e089c3959cd5.png)

#### 3-2. 実験作成、実施

いよいよ実験の作成から実施に入ります。ここからの流れを一枚絵に表したのが下図となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/1fb48a15-e621-c5ae-3eb0-6de9beca0a1e.png)

以下では、図内の番号に沿って、手順を解説していきます。

##### 3-2-1. 実験の作成

実験は、Azure Portal または Azure CLI 経由で作成することができます。今回は、Azure Portal から行います。以下画面ショットに従って実験を追加してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/c07bfdca-7da9-f9ac-3957-32963cc36250.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/7c9cbaff-6b22-9955-1d95-7dcd76e13804.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/ea4a75f0-118f-9a1c-70c6-224ec77eb4c5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/61a58b9b-752d-a509-b96b-91fd25535b65.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/e1f9a19d-4c25-58d3-7f54-81668f46681d.png)

##### 3-2-2. / 3-2-3. システム割り当てマネージド ID に対して権限を付与

実験を作成すると、実験に対応したシステム割り当てマネージド ID が発行されます。このマネージド ID に対し、Azure リソースに対する操作を許可する権限を付与する必要があります。

今回は、操作対象となる仮想マシン【nginx-001】のアクセス制御（IAM）ページから、システム割り当てマネージド ID に対して、以下の図のように、「仮想マシン共同作成者」権限を付与します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/ceaa35d8-2a29-11f3-5fa3-01a51d648eab.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/37267fd4-b192-7e56-ae87-cf685997b64f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/538ab683-a8ea-172f-9057-c84ad7b2b8ae.png)


##### 3-2-4. 実験実行

実験群に対し、上記で作成した実験を実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/fbd83985-f697-b377-15b8-773e0f765e5a.png)

### 4. 対照群と実験群との間で差異があるかを確認し、文書化 / 5. 結果を特定し、改善

実験を行ったところ、対照群と比べて、実験群は、【nginx-001】停止後、クライアントによってはしばらくアクセスができない状態が続いてしまう場合があることが判明しました。

![Animation_En.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/db3fa048-ad43-b72c-53d1-c4cd8f7b3042.gif)


原因を調べたところ、意図せず Application Gateway でのセッションアフィニティが有効化されていたことがわかりました。
※補足として、セッションアフィニティの無効化を推奨しているわけではなく、あくまで今回の要件ではセッションアフィニティの設定を意図せず有効化していた、という設定です。

#### 再実験

そこで、セッションアフィニティを無効化し、再度対照群と実験群との間で差異があるかを確認しました。
すると、以下のように、【nginx-001】に割り振られていたリクエストは全て【nginx-002】に再ルーティングされていることがわかります。

![Animation_Dis2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/5d0b5401-b19a-7ec7-8625-fd129cf603f5.gif)

これにより、意図しないダウンタイムの可能性を発見し、課題を解決することができました。

こうした実験を繰り返すことで、システムの安定性に対する自信を深めていく取り組みが、カオスエンジニアリングです。

## まとめ

本記事では、カオスエンジニアリングの概要や必要な背景、進め方をご紹介し、Azure Chaos Studio を使って実際にカオスエンジニアリングを行ってみました。

Azure Chaos Studio は、2021 年 12 月 3 日時点でパブリックプレビューです。サポートされている障害については、[Docs: Chaos Studio の障害およびアクション ライブラリ](https://docs.microsoft.com/ja-jp/azure/chaos-studio/chaos-studio-fault-library) に記載されています。

本記事が、カオスエンジニアリングに対して少しでも理解を深めるきっかけになれば幸いです。

## 参考

- [Chaos Engineering (O'Reilly Media, Inc.)](https://www.oreilly.com/library/view/chaos-engineering/9781492043850/)
- [PRINCIPLES OF CHAOS ENGINEERING](https://principlesofchaos.org/)
- [Docs: カオス エンジニアリング](https://docs.microsoft.com/ja-jp/azure/architecture/framework/resiliency/chaos-engineering)