AWS Fault Injection Simulatorを使った障害試験を試してみる（その２：色々なアクション実行）

# はじめに
前回は`AWS FIS`でどのようなアクションが指定できるかの説明と簡単な実験テンプレートを作成して実行してみました。

前回はお試しでEC2インスタンスの停止を行ってみたため、今回はEC2インスタンスの操作を行うアクション以外のアクションをいくつか試してみて、どのような動作となるか確認してみたいと思います。

- 【前】[AWS Fault Injection Simulatorを使った障害試験を試してみる（その１：アクション概要とおためし実行）](https://qiita.com/sakai00kou/items/9908c1ec1c44c1799c11)

# 試験シナリオ
さすがに全てのアクションを試すのは手間なので、以下のような試験シナリオを想定し、2つほど試してみたいと思います。

- [EBSへのIOを停止させVolumeIdleTimeが40を下回った場合に試験を停止させる](#ebsへのioを停止させvolumeidletimeが40を下回った場合に試験を停止させる)
- [CPU使用率100%のアクションを実行した後１分後にメモリ使用率100%のアクションを実行する](#cpu使用率100のアクションを実行した後１分後にメモリ使用率100のアクションを実行する)

## EBSへのIOを停止させVolumeIdleTimeが40を下回った場合に試験を停止させる 
`aws:ebs:pause-volume-io`のアクションを実行した際の動作と、実験テンプレートの機能である「**停止条件**」で指定した`CloudWatch`アラームが異常となった場合にアクションが停止されるかを確認してみようと思います。

`CloudWatch`アラームは該当のEC2インスタンスにアタッチされているEBSボリュームの`VolumeIdleTime`を監視し、40を下回った場合に異常と判断するような定義をあらかじめ設定しております。

### 実験テンプレートの設定
抜粋となりますがそれぞれの実験テンプレートの設定は以下で行いました。

`Duration`は停止条件に引っかかる前に終了しないようMAXの12時間で指定しています。

- **アクション**

|項目名|設定|
|:--|:--|
|アクションタイプ|aws:ebs:pause-volume-io|
|ターゲット|Volumes-Target-1|
|Duration|12時間|

- **ターゲット**

|項目名|設定|
|:--|:--|
|名前|Volumes-Target-1|
|リソースタイプ|aws:ec2:ebs-volume|
|ターゲットメソッド|リソースID|
|リソースID|※EC2インスタンスにアタッチされているIDを指定|

- **停止条件**

|項目名|設定|
|:--|:--|
|停止条件|※あらかじめ設定したCloudWatchアラーム|

### 実験結果
結果としては想定通り`CloudWatch`アラームが異常となったタイミングで「**停止条件**」が動作し、アクションが停止されました。

何度か同じ試験を実施したのでグラフはガタガタしていますが、きちんと下回ったタイミングで停止処理が行われました。

![Monosnap_20230212_172759.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/260124d1-ce91-9b7f-e6c2-922d6bf6fc7f.png)

![Monosnap_20230212_172915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/bf299ac7-1e2f-7688-d779-b41ab8442017.png)

また、少しだけ想定外だったのは、アクション実行中、対象のEC2インスタンスから以下のように`vmstat`コマンドでファイル出力させつつ別ウィンドウで`tail`確認したところ、出力が止まることもなくどちらのウィンドウでもログの内容が確認できており、さらに別ウィンドウでSSH接続もできました。

```bash:vmstatの実行
vmstat 1 3600 | tee /root/vmstat.log
```

```bash:tailでのファイル内容確認
tail -f /root/vmstat.log
```

どうやらEBSへのIOが完全に停止するわけではなく、ある程度のIOは許容されているようでした。

その状態でも`CloudWatch`の`VolumeIdleTime`は上記グラフのように推移するので、しばらく経てば「**停止条件**」で停止されます。

ただし、その状態でさらに以下のような操作を行ってみたところ、アクションが停止されるまで全ウィンドウ完全に停止して、SSH接続も行えなくなりました。

```bash:IO処理の実行
dd if=/dev/zero of=/root/testfile bs=1024k count=1000
```

そのことから、ある程度IOバッファがあるようなので、今回と同じように試験を実施する場合にはある程度IO処理を発生させるようにしましょう。

## CPU使用率100%のアクションを実行した後１分後にメモリ使用率100%のアクションを実行する
以下3つのアクションを続けて実行してみようと思います。

順序としては以下の通りで、CPU使用率100%のアクションを実行した後、`aws:fis:wait`アクションで１分待機してからメモリ使用率100%のアクションを実行する流れとなります。

- AWSFIS-Run-CPU-Stress
- aws:fis:wait
- AWSFIS-Run-Memory-Stress

### 実験テンプレートの設定
今回は順番に実行していくため、「**次のあと開始**」を使って繋げていきます。

また、CPU・メモリ使用率のストレス試験は定義済みの`Systems Manager`ドキュメントを使用するため、一部パラメータは`JSON`形式で指定する必要があります。

指定可能なパラメータは以下を参照。

- [Use Systems Manager SSM documents with AWS FIS](https://docs.aws.amazon.com/fis/latest/userguide/actions-ssm-agent.html)

以下今回設定した抜粋版の内容。

- **アクション1**

|項目名|設定|
|:--|:--|
|名前|Wait|
|アクションタイプ|aws:ssm:send-command/AWSFIS-Run-CPU-Stress|
|次のあと開始|空欄|
|ターゲット|Instance-Target-1|
|Document ARN|arn:aws:ssm:ap-northeast-1::document/AWSFIS-Run-CPU-Stress|
|Document Parameters|{"DurationSeconds":"60", "LoadPercent":"100", "InstallDependencies":"True"}|
|Document Version|空欄|
|Duration|1分|

- **アクション2**

|項目名|設定|
|:--|:--|
|名前|CPU_Stress|
|アクションタイプ|aws:fis:wait|
|次のあと開始|CPU_Stress|
|Duration|1分|

- **アクション3**

|項目名|設定|
|:--|:--|
|名前|Wait|
|アクションタイプ|aws:ssm:send-command/AWSFIS-Run-Memory-Stress|
|次のあと開始|Wait|
|ターゲット|Instance-Target-1|
|Document ARN|arn:aws:ssm:ap-northeast-1::document/AWSFIS-Run-Memory-Stress|
|Document Parameters|{"DurationSeconds":"60", "Percent":"100", "InstallDependencies":"True"}|
|Document Version|空欄|
|Duration|1分|

- **ターゲット**

|項目名|設定|
|:--|:--|
|名前|Instances-Target-1|
|リソースタイプ|aws:ec2:instance|
|ターゲットメソッド|リソースID|
|リソースID|※EC2インスタンスのIDを指定|

ややこしいですが、「**Document Parameters**」で指定している`DurationSeconds`は対象のEC2インスタンスでストレスツールを実行する時間で、「**Duration**」はSSMコマンドを監視する時間だそうです。

つまり、「**Duration**」が`Systems Manager Run Command`でSSMコマンドを実行する時間となるので、`DurationSeconds`は「**Duration**」で指定する期間と同じか短くする必要があります。（仮に`DurationSeconds`を長くしても「**Duration**」で指定した期間が経過したらSSMコマンドが打ち切られます）

また、前回の「[AWS Fault Injection Simulatorを使った障害試験を試してみる（その１：アクション概要とおためし実行）]」でも書きましたが、前回の一覧表のアクション種別で言うところの「**SSM documents**」については、各種試験ツールをターゲットインスタンスにインストールしてからアクションが実行されるので、インストールパッケージを細かく管理しているシステムでは気をつけるようにしましょう。

### 実験結果
実行中、`vmstat`コマンドの結果を見ながら試験実施しておりましたが以下のような結果となりました。

かなり雑な抜粋ですが、開始後`cpu`の`us`が100%に張り付き、１分後に元に戻った後、さらに１分後に`memory`の`free`が下がり、さらに１分後に試験終了してメモリが解放されていることが確認できるかと思います。

```bash:vmstatの結果抜粋
【試験開始】（CPUストレスツールアクション開始）

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 101844   1052 715640    0    0     0     0   52   75  0  0 99  0  0
 0  0      0 101844   1052 715640    0    0     0     0   39   61  0  0 100  0  0
 0  1      0  92252   1052 722372    0    0  6872    12  287  476  0  0 97  2  0
 1  0      0  86940   1052 705988    0    0 23576     0 1595 2369 13  4 45 17 21
 0  1      0  76440   1052 709688    0    0 23920    80 1731 2786 29  4 54 12  2
 0  1      0  72524   1052 689972    0    0 29056   469 2120 2690 24  3 50 23  0
 2  0      0  87580   1052 663180    0    0  5836  1024 1695 2501 36  9 43 11  0
 3  0      0 116748   1052 666116    0    0   160     0  866 1357 98  2  0  0  0
 3  0      0  87824   1052 556656    0    0     0     0  510  169 100  1  0  0  0
 3  0      0  87848   1052 556656    0    0     0     0  538 7114 99  1  0  0  0
 2  0      0 248744   1052 556704    0    0     0     0  515   49 100  0  0  0  0
 2  0      0 248744   1052 556704    0    0     0     0  517   52 100  0  0  0  0
 2  0      0 248512   1052 556852    0    0     0     0  515   74 100  0  0  0  0
 2  0      0 248560   1052 556892    0    0     0     0  528   75 100  0  0  0  0

【1分後】（CPUストレスツールアクション終了＆待機アクション開始）

 2  0      0 248496   1052 556892    0    0     0     0  511   57 100  0  0  0  0
 2  0      0 248496   1052 556896    0    0     0     0  516   82 100  0  0  0  0
 0  0      0 262068   1052 554484    0    0    12    20  214  332  3  0 97  0  0
 0  0      0 262068   1052 554484    0    0     0     0  130  233  0  0 100  0  0
 0  0      0 262068   1052 554488    0    0     0    12  131  208  1  0 100  0  0
 0  0      0 262068   1052 554488    0    0     0     0  138  188  0  0 100  0  0
 0  0      0 262068   1052 554488    0    0     0     0   49   74  0  0 100  0  0
 0  0      0 262068   1052 554488    0    0     0     0   53   70  0  0 100  0  0
 0  0      0 262068   1052 554488    0    0     0     0   45   70  0  0 100  0  0
 0  0      0 262068   1052 554488    0    0     0     8   39   55  0  0 100  0  0
 0  0      0 262068   1052 554488    0    0     0     0   72   92  0  1 100  0  0
 0  0      0 262068   1052 554488    0    0     0     0   35   53  0  0 100  0  0

【1分後】（待機アクション終了＆メモリストレスツールアクション開始）

 0  0      0 262068   1052 554492    0    0     0     0   53   73  0  1 100  0  0
 0  0      0 262068   1052 554492    0    0     0     0   41   63  0  0 100  0  0
 1  0      0 146152   1052 659964    0    0   132    29  667  832  5  4 77  0 14
 1  0      0  81144    976 724076    0    0     0   327  629  493 31  5 44  0 20
 1  0      0 257244    976 548344    0    0     0     0  428  295 31 20 50  0  0
 1  0      0  81200    976 724000    0    0     0     0  347  163 38 13 50  0  0
 1  0      0  81200    976 724100    0    0     0     0  347   52 22  7 44  0 27
 1  0      0  82952    976 723308    0    0     0     0  508  157 27  7 47  0 18
 1  0      0 255348    976 551208    0    0     0     0  274   46 40 11 50  0  0
 1  0      0  82960    976 723256    0    0     0     0  306   81 29 22 50  0  0
 1  0      0  72276    976 701368    0    0     0     0  277   40 43  7 50  0  0
 1  0      0  72276    976 701368    0    0     0     0  275   20 50  0 50  0  0
 1  0      0 104016    976 701120    0    0     0     0  328   79 44  7 50  0  0
 1  0      0 105276    976 701120    0    0     0     8  276   47 42  8 50  0  0
 1  0      0 105276    976 701120    0    0     0     0  262   27 50  0 50  0  0
 1  0      0 105276    976 701120    0    0     0     0  300   38 50  0 50  0  0
 1  0      0 105276    976 701120    0    0     0     0  282   24 50  0 50  0  0

【1分後】（メモリストレスツールアクション終了）

 1  0      0 104076    976 701316    0    0     0     0  320   72 50  0 50  0  0
 1  0      0 104076    976 701316    0    0     0     0  314   68 50  0 50  0  0
 1  0      0 369156    976 446568    0    0     0     8  354  255 36  2 63  0  0
 0  0      0 369180    976 446496    0    0     0     0  149  227  0  0 100  0  0
 0  0      0 369180    976 446500    0    0     0     0   73  145  0  0 100  0  0
 0  0      0 369180    976 446500    0    0     0     0   85  148  0  0 100  0  0
 0  0      0 369180    976 446500    0    0     0     0   57   82  0  0 100  0  0
 0  0      0 369228    976 446500    0    0     0     0   69  104  0  0 100  0  0
 0  0      0 369228    976 446500    0    0     0     0  113  157  0  0 100  0  0
 0  0      0 369228    976 446500    0    0     0     0   49   68  0  0 100  0  0
 0  0      0 369228    976 446500    0    0     0   112   72  128  0  0 100  0  1
```

今回は３つのアクションをそれぞれ１分ずつ実行するようにしたので、「**タイムライン**」タブを見ると以下のようにきれいに１分ずつ実行されていることがわかります。

![Monosnap_20230212_190905.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f8b29b38-7997-7ee0-ffae-76c5cd345e98.png)

# おわりに
今回は２つのシナリオを通して`AWS FIS`を使った障害試験を試してみました。

予めテンプレートを作成しておくことで、何度でも同じ手順で障害を起こせるため、常に同じ品質で試験ができること、テンプレートをエクスポート＆インポートも簡単にできるため、同じような構成の試験シナリオも簡単に作成できることなど、試験の実施もさることながら試験の準備にかかる時間も大幅に短縮できる可能性があると感じました。

私も今後の案件で使用できそうな機会があれば積極的に使っていきたいと思います。