Chaos Meshで何ができるのか見てみた

# はじめに
最近ではAWSでもカオスエンジニアリングを実行するフルマネージドサービスである [AWS Fault Injection Simulator](https://aws.amazon.com/jp/fis/)がリリースされるなど、**カオスエンジニアリング**という言葉をよく目にするようになりました。

カオスエンジニアリングとは、**分散システムにおいてシステムが不安定な状態に耐えることのできる環境を構築するための検証の規律**、ということらしいです。
> カオスエンジニアリングの原則
> https://principlesofchaos.org/ja/

カオスエンジニアリングを実践しているNetflixでは、[chaos monkey](https://github.com/Netflix/chaosmonkey)というツールを開発し、実際に本番環境に対して障害を発生させてシステム障害の安定性を高める取り組みを行なっているようです。

個人的見解ですが、カオスエンジニアリングは障害が発生してもサービスを継続して提供できるような環境を作るための取り組み、といったものだと思っています。

そんなカオスエンジニアリングを実施するためのツールとして、kubernetes上でカオスエンジニアリング [Chaos Mesh](https://github.com/chaos-mesh/chaos-mesh) があるとの知見を得ましたので、実際にApple Siliconが搭載されているmacbook Proで動かしながら何ができるのかを見てみました。

# Chaos Meshとは
Chaos Meshは[Chaos Mesh公式ページ](https://chaos-mesh.org/)によると**kubernets用のカオスエンジニアリングプラットフォーム**、と説明されています。

特徴としては以下の点が挙げられます。

- **使いやすさ**
    - アプリケーションのデプロイのロジックを変更することなく、実際に動作している環境で試験を行える。
    - 試験の動作を簡単に調整でき、試験を行う人は試験状態をリアルタイムで観察できるようになっており素早くロールバックできる。
    - ダッシュボードが豊富で、手書きの定義をすることなく数クリックで試験を実施できる。
- **Kubernetes用に設計されている**
    - CRD(Custom Resource Definition)に則って試験の定義をする。
    - CRDに乗っ取ることでKubernetesの機能を自然に統合できる。
- **さまざまな種類の障害を発生させることができる**
    - Chaos Meshは分散システムの観点から始まり、分散システムで起こりうる障害を十分に考慮しているため、分散システムで起こりうる様々な障害を発生できるようにしている。
- **コントローラブル**
    - Chaos MeshはRBAC(role-based access control)を提供するため、実験を行う人の権限を設定できる。
    - namespaceのブラックリスト、ホワイトリストを設定でき、実験の被害範囲を細かく制御できる。


個人としてはコントローラブルであることから**障害を発生させる範囲が限定的にできる**のと、**ロールバックがすぐにできる**ところが良い点だと思いました。

# 注入できる障害
公式ドキュメントの基本的な機能が公式ドキュメントにまとめられていましたので、どのようなものがあるのかを見てみました。
具体的には以下のような障害の注入に対応しているようです。

中でもAWSやGCPの障害をシミュレートできるのは非常に興味深く、突然Worker Nodeが再起動をする場合も想定できるのは非常に役立ちそうですね。

## 基本的なリソースの障害
- PodChaos
    - Podの再起動やPodの永続的な使用不能状態、特定のPodのコンテナの障害など、Podの障害のシミュレート
- NetworkChaos
    - ネットワークの遅延、パケットの損失や障害、ネットワークパーティションなどの障害のシミュレート
- DNSChaos
    - DNSの名前解決失敗や、誤ったIPアドレスが返却される障害のシミュレート
- HTTPChaos
    - HTTP通信の待ち時間や失敗をシミュレート
- StressChaos
    - CPUやメモリの負荷をシミュレート
- IOChaos
    - I/Oの遅延や読み書きの失敗、アプリケーションファイルのI/Oの失敗をシミュレート
- TimeChaos
    - タイムジャンプ例外のシミュレート
- KernelChaos
    - アプリケーションのメモリ割り当ての例外など、カーネルの障害をシミュレートする

## プラットフォームの障害
- AWSChaos
    - AWSノードの再起動など、AWSの障害をシミュレート
- GCPChaos
    - GCPノードの再起動など、GCPの障害をシミュレート

## アプリケーションの障害
- JVMChaos
    - 関数呼び出しの遅延など、JVMアプリケーションの障害をシミュレート

# 実際に障害を注入してみる

ローカルPCにkubernetes環境を用意し、ダッシュボードを操作しながら`nginx-b`の`nginx`コンテナで障害を発生させてみたいと思います。

## ローカルPCのセットアップ
ローカルPCとkubernetes環境は以下のものを用意しました。

- PC
    - macbook Pro M1 Pro
        - 8core 16GB
        - macOS Monterey(12.0.1)
- Kubernetes環境
    - minikube(v1.24.0)
- kubectl
    - Client Version: v1.21.7
    - Server Version: v1.22.3
- Chaos Mesh
    - v2.1.0

## テスト用のnginxのデプロイ
Chaos Meshの障害注入対象として、nginxのPodを2つデプロイしたいと思います。
[m-e-n-d/test-nginx-deployment](https://github.com/m-e-n-d/test-nginx-deployment)
こちらのmanifestをapplyし、`nginx-a`のPodと`nginx-b`のPodを事前にChaos Meshをデプロイするクラスターと同じクラスターに配置しておきます。



## Chaos Meshのインストール
ローカルPCにChaos Meshをインストールします。
こちらはminikubeでインストールをする際のコマンドですが、`kind`や`k3s`、`Microk8s`を使用する際は[Quick Start](https://chaos-mesh.org/docs/quick-start/)を参考にそれぞれにあったものを入れてください。

**注意**
こちらを実行する際には現在設定しているkubeconfigのcontextを設定しているクラスターに対してインストールが実行されます。
インストールを実施する際には現在設定しているcontextを意図したクラスターに向けるようにしておきましょう。

```shell
curl -sSL https://mirrors.chaos-mesh.org/v2.1.0/install.sh | bash
```

インストールが完了しましたらクラスターの`chaos-testing`のnamespaceにPodが配置されていますので確認してみましょう。

```shell
$ kubectl get po -n chaos-testing
NAME                                        READY   STATUS    RESTARTS   AGE
chaos-controller-manager-7d86885d5f-2zrtf   1/1     Running   0          5m41s
chaos-controller-manager-7d86885d5f-6gx2v   1/1     Running   0          5m41s
chaos-controller-manager-7d86885d5f-hlzlq   1/1     Running   0          5m41s
chaos-daemon-x2g7c                          1/1     Running   0          5m41s
chaos-dashboard-b8c66f994-mls8x             1/1     Running   0          5m41s
```

## ダッシュボードを見てみる
ダッシュボードのPodが立ち上がっているので、ダッシュボードがどのようなものか見てみます。

serviceを見てみると以下のようにdashboardのserviceが作成されているので、`kubectl port-forward`でローカルIPからアクセスできるようにしてみます。

```shell
$ kubectl get service -n chaos-testing
NAME                            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                                 AGE
chaos-daemon                    ClusterIP   None           <none>        31767/TCP,31766/TCP                     8m33s
chaos-dashboard                 NodePort    10.99.50.123   <none>        2333:30978/TCP                          8m33s
chaos-mesh-controller-manager   ClusterIP   10.99.140.46   <none>        443/TCP,10081/TCP,10082/TCP,10080/TCP   8m33s
```

http://localhost:2333 でアクセスできるようにします。

```shell
$ kubectl port-forward -n chaos-testing svc/chaos-dashboard 2333:2333
Forwarding from 127.0.0.1:2333 -> 2333
Forwarding from [::1]:2333 -> 2333
.....
```

ここまでできたら以下の画像のようなダッシュボードが見れるはずですのでアクセスしてみましょう。
http://localhost:2333

![スクリーンショット 2021-12-04 19.09.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/7bfb60f2-f36d-7f45-5423-47b8eb3961f9.png)

おお....

## 障害を注入する
ダッシュボード左のメニューから[Experiments](http://localhost:2333/experiments)を開き、「NEW EXPERIMENT」を開きます。

![スクリーンショット 2021-12-04 21.16.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/f85db780-a72e-7f83-d47d-4d7fd390887f.png)

以下のように設定を行い「SUBMIT」をクリックします。

![スクリーンショット 2021-12-04 21.19.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/f63bf738-3e96-6512-cf30-6b32f851c5e9.png)

さらに下部にある Experiment Infoは以下のように設定しました。
![スクリーンショット 2021-12-04 21.21.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/afb751f3-b29e-92df-ae38-0f0bafdafccb.png)

ここで「SUBMIT」をクリックし、`nginx-b`の`nginx`コンテナを`KILL`してみたいと思います。

```shell
$ kubectl get po -n test-nginx
NAME                            READY   STATUS    RESTARTS      AGE
test-nginx-a-6bd7d4685b-mjjrv   1/1     Running   0             4m32s
test-nginx-b-6745d55ffc-zc6fv   1/1     Running   1 (69s ago)   4m31s
```

するとこのようにPodがコンテナが終了したことで再起動され、`nginx-b`のPodの`RESTARTS`が`1`になっていました。
`events`の方を確認してみると、以下のようになっておりました。
![スクリーンショット 2021-12-04 21.36.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/860a3b7d-94fd-71d4-40b2-a7a753a30a6f.png)

これはChaos Meshが正常にPodの終了ができたというログが出ているみたいですね。

Chaos Meshのダッシュボードにも実験が終了したときのログが残っていました。
![スクリーンショット 2021-12-04 21.39.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/cb67ba65-9cc3-452a-0476-aff9ba338ee4.png)

設定と一緒に、設定内容のYAMLまで出力されるみたいです。
ファイル管理ができるようになるのは非常にありがたいですね。

# まとめ
Chaos MeshではGUIだけで障害を発生させることができ、範囲も細かく設定することで想定外の障害を発生させないためのつくりになっていることがわかりました。
これにより、カオスエンジニアリングを行ううえで、比較的安心して障害を注入することができそうですね。

まだまだ発展途中のツールなので、今後のアップデートにも期待できます。

あと今回の内容はあくまでクイックスタートの内容ですので、しっかりと始めたい場合は[Chaos Meshの公式ドキュメント](https://chaos-mesh.org/docs/)を見ることをお勧めします。