第 11 回:Chaos Toolkit でAWSのデータセンタ障害を疑似してみる【押忍!ソフト道場】
今回は趣向を変えてAWS×カオスエンジニアリングです
ソフト道場の「SIerが目利きする。今日から使えるAWSレシピ」
- 2020年07月31日公開
はじめに
こんにちは。NTT テクノクロスの渡邉です。
今回は趣向を変えて、カオスエンジニアリング用のツール(Chaos Toolkit)を使ってAWS環境のEC2障害を疑似してみた!という検証内容を共有します。
What's カオスエンジニアリング?
さらっと書きましたが、カオスエンジニアリングとは?と言うところを軽く触れておきましょう。
システムが予期せぬ故障に耐えられるかを検証するため、あえて本番環境で意図的に故障を起こし、結果としてサービス継続性や復旧能力などを検証し続ける。というのがカオスエンジニアリングの基本的な考え方です。Netflix社さんの事例は有名ですね。
勿論この考え方をそのまま採用できるプロジェクトは多くないでしょうし、特にお客様から預かっているシステムでの安易な採用は現実的ではないと思われます。
とはいえ、昨今のパブリッククラウドやコンテナ型仮想化の台頭により、AutoScalingやデータセンタの冗長化を適切に出来ているのか?という試験観点は今後重要になる一方かと思われます。この分野で得られるノウハウはきっとSIerにとっても役に立つはず!と信じて、今回はカオスエンジニアリングを実現するツールの一つであるChaosToolkitを利用してみたいと思います。
幸運なことに、今回は社内研修の「テーマは自分で決める、自学自習の1日」という1日を使って自由に技術検証を勤しむ機会を頂けたので、その模様を共有いたします。
実施内容と目的
ちなみにChaos Toolkitとは、Open APIを定義して、Chaos Engineeringの実験を表現するツールとのこと。
Open APIを介して任意のシステムに対して自由に拡張可能らしく、対象スコープは例えば下記の様子。幅広いですね。
- AWS
- GCP
- Azure
- Cloud Foundry
- Humio
- Prometheus
- Gremlin
※画像は公式からの引用です。
今回の目標は「Chaos Toolkitを用いてAmazon EC2が突然、機能を停止した場合」という試験シナリオが実施できるよう、お試しできるところまでが目標です。
やってみた
というわけで実際の模様を公開します。日本語情報がほとんどなく、試行錯誤の中での検証でした……
1.導入は上手くいく
-
AWSのリソースを対象に試験がしたい
-
調べると、追加でパッケージ(chaostoolkit-aws)を入れる必要がありそう。
# イメージはこんな感じ cat Dockerfile FROM chaostoolkit/chaostoolkit USER 1001 RUN pip install -U chaostoolkit-aws #イメージビルド docker build . -t chaos-aws #実行 docker run --rm chaos-aws
- ここまでは順調です!
2.で、どう動かせばいいんだ?
-
aws版のパッケージを読むが、サンプルのテンプレートは断片的にしか見つからず。「とりあえずコピペでチュートリアル!」的なシナリオは無いのがつらい……頑張って公式ドキュメントを熟読しましょう。
-
ちなみにサンプルは下記。
-
us-west-1リージョン(北カリフォルニア)のEC2のうち、どれか1のデータセンター(Availability Zone、以下AZ)を狙ってランダムでstopさせる?と読めます。
{ "name": "stop-an-ec2-instance-in-az-at-random", "provider": { "type": "python", "module": "chaosaws.ec2.actions", "func": "stop_instance", "arguments": { "az": "us-west-1" } } }
- まずは試してみますか……
3. 検証1:ランダムなAZのEC2を停止させる
- 各AZにEC2を2台ずつ建てる
-
手順は割愛。(AWS マネジメントコンソールから手動で作ってしまいました。)
-
確認
# ※aws-cliの設定は略 # 起動中(running)のEC2は2台 ×2 AZ = 4台 aws ec2 describe-instances --query "Reservations[].Instances[].State[].Name" [ "running", "running", "running", "running" ] # ちゃんと各リージョン2台ずつありますね。 aws ec2 describe-instances --query "Reservations[].Instances[].Placement[].AvailabilityZone" [ "us-west-1a", "us-west-1a", "us-west-1c", "us-west-1c" ]
- chaos-toolkitで停止
ここが一番ハマりました。ありのままに書くと大体が恥ずかしいので割愛しますが、 サンプルの「"az": "us-west-1"」をそのまま書くとNGになってたのが一番気づくのに時間かかりましたね。us-west-1はAZではなくリージョン。……うん、これも十分恥ずかしいな。
気を取り直して動くサンプルを。(これを期待していた読者の方もいるかも?)
- 定義ファイル(chaos01.json)
{ "version": "1.0.0", "title": "test01", "description": "instance stop random az", "configuration": { "aws_region": "us-west-1" }, "method": [ { "type": "action", "name": "stop-an-ec2-instance-in-az-at-random", "provider": { "type": "python", "module": "chaosaws.ec2.actions", "func": "stop_instance", "arguments": { "az": "us-west-1a" } } } ] }
- 実行
# 実行! chaos run chaos01.json [2020-07-17 06:17:12 INFO] Validating the experiment\'s syntax [2020-07-17 06:17:12 INFO] Experiment looks valid [2020-07-17 06:17:12 INFO] Running experiment: test01 [2020-07-17 06:17:12 INFO] No steady state hypothesis defined. That\'s ok, just exploring. [2020-07-17 06:17:12 INFO] Action: stop-an-ec2-instance-in-az-at-random [2020-07-17 06:17:12 WARNING] Based on configuration provided I am going to stop a random instance in AZ us-west-1a! [2020-07-17 06:17:14 INFO] No steady state hypothesis defined. That\'s ok, just exploring. [2020-07-17 06:17:14 INFO] Let\'s rollback... [2020-07-17 06:17:14 INFO] No declared rollbacks, let\'s move on. [2020-07-17 06:17:14 INFO] Experiment ended with status: completed
- 確認
# 起動中のEC2は3台。ランダムに1台を止められている! aws ec2 describe-instances --query "Reservations[].Instances[].State[].Name" [ "running", "stopped", "running", "running" ] # ちゃんと1aが1台止まっています! [ec2-user@ip-10-0-2-250 ~]$ aws ec2 describe-instances --query "Reservations[].Instances[].Placement[].AvailabilityZone" [ "us-west-1a", "us-west-1a", "us-west-1c", "us-west-1c" ]
- その後何台か試しましたが、ほんとにランダムに1aを止めている様子!
4. 検証2:特定AZのEC2を全て停止させる
ようやく軌道に乗ったため、他のテストも調べることに。
研修の残り時間は少なくなってきたのですが、さきほど動かした「stop_instance」とよく似た「stop_instances」は、どうやら特定AZのインスタンス全て停止する挙動の模様。さながらChaos Kongのようですね。これも試してみましょう。
-
定義ファイル(chaos02.json)
-
ちなみに先ほどとの違いはfuncのみ
{ "version": "1.0.0", "title": "test02", "description": "instance stop random az", "configuration": { "aws_region": "us-west-1" }, "method": [ { "type": "action", "name": "stop-an-ec2-instance-in-az-at-random", "provider": { "type": "python", "module": "chaosaws.ec2.actions", "func": "stop_instances", "arguments": { "az": "us-west-1a" } } } ] }
- 準備&実行
# 同リージョンにもう一つVPC作って、AZ-Aに+2台建てちゃいました。 aws ec2 describe-instances --query "Reservations[].Instances[].State[].Name" [ "running", "running", "running", "running", "running", "running" ] aws ec2 describe-instances --query "Reservations[].Instances[].Placement[].AvailabilityZone" [ "us-west-1a", "us-west-1a", "us-west-1a", "us-west-1a", "us-west-1c", "us-west-1c" ] # さあ実行! [2020-07-17 06:42:06 INFO] Validating the experiment\'s syntax [2020-07-17 06:42:07 INFO] Experiment looks valid [2020-07-17 06:42:07 INFO] Running experiment: test01 [2020-07-17 06:42:07 INFO] No steady state hypothesis defined. That\'s ok, just exploring. [2020-07-17 06:42:07 INFO] Action: stop-an-ec2-instance-in-az-at-random [2020-07-17 06:42:07 WARNING] Based on configuration provided I am going to stop all instances in AZ us-west-1a! [2020-07-17 06:42:09 INFO] No steady state hypothesis defined. That\'s ok, just exploring. [2020-07-17 06:42:09 INFO] Let\'s rollback... [2020-07-17 06:42:09 INFO] No declared rollbacks, let\'s move on. [2020-07-17 06:42:09 INFO] Experiment ended with status: completed #「 I am going to stop all instances in AZ us-west-1a! 」いい感じですね。 # 見ると確かにaz-aのインスタンスを全部停止できています! aws ec2 describe-instances --query "Reservations[].Instances[].Placement[].AvailabilityZone" [ "us-west-1a", "us-west-1a", "us-west-1a", "us-west-1a", "us-west-1c", "us-west-1c" ] aws ec2 describe-instances --query "Reservations[].Instances[].State[].Name" [ "stopped", "stopped", "stopped", "stopped", "running", "running" ]
というところで、研修はタイムアップ。お疲れ様でした。
まとめ
-
今回の目標だった「Chaos Toolkitを用いてAmazon EC2が突然、機能を停止した場合」はある程度達成できました。
-
しいて言うと突然のインスタンス削除(Terminate)までは到達できなかったので、100点満点で言うと60~70点といったところでしょうか。
-
次に検証できる機会があれば、今回試せなかったEC2系のイベントをもっと掘り下げたいですね。上で挙げたterminate~以外にも例えば「restart_instances」や「detach_random_volume」など。
-
EC2以外にもRDS, Lambda, ALB, ECS, EKSと幅を広げてくのも興味深いですね!それではまた。