Gremlinを使って障害を注入してみる

こんにちは、森です。

昨年のAWS re:Invent 2018でも紹介されたカオスエンジニアリングツールの Gremlin というサービスを使って障害を注入し、 使用感を確かめたいと思います。

Gremlinとは

"Gremlin provides a hosted service for you to safely, securely, and simply run Chaos Experiments to prevent outages."

システムに障害を注入するためのホスティングサービスです。

以下の3つの原則をもとに、我々にChaos Experimentsを提供してくれます。

Safety

正確な故障テストで影響範囲を最小化。

安全に停止し、すぐに安定した状態にロールバックします。

Security

ルートアクセスを必要とせず、SSOとMFAを提供し、

定期的なサードパーティのセキュリティ監査を受けます。

Simplicity

数分で攻撃をインストールして実行します。ホストまたはコンテナで動作します。

インフラストラクチャ、アプリケーション両方に障害を注入できます。

システムの弱点を特定、問題になる前に修正することにより実際の障害時の被害を最小限に留める準備ができます。

Gremlinの使い方

公式ページに書かれているのは以下。

実験の計画をする

何がおかしいか仮説を立てる。

最小の範囲で実行する

簡単なテストを実行し、システムがどんな反応をするか確認する。

拡大縮小してから押しつぶす

テストを拡大、縮小しながら問題を特定し、そのあとそれを潰す

では、実際にチュートリアルを参考にし、使ってみようと思います。 今回はDockerを使います。

環境

mac OS Mojave 10.14.6
Docker 19.03.2, build 6a30dfc
Gremlin Free Plan

料金に関してはこちらを参照。

インストール

公式手順を参考にインストールしていきます。

※ Dockerのインストールは割愛。

1. 測定用のコンテナを用意

vim Dockerfile

で以下の内容を保存します。

FROM alpine:latest
RUN apk add --update htop && rm -rf /var/cache/apk/*
ENTRYPOINT ["htop"]

Dockerfileを保存したディレクトリで以下を実行します。

docker build -t htop .

ビルドが完了したら

docker run -it --rm --pid=host htop

でコンテナを起動します。

docker_run

このような画面になれば起動完了です。

終了させるときは qキーを押せば良いです。

2. テスト対象となるnginxのコンテナを用意

nginxで表示させるページを作成します。

mkdir -p ./docker-nginx/html
cd ./docker-nginx/html
vim index.html

以下の内容をペーストします。

<html>
  <head>
    <title>Docker nginx tutorial</title>
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
      integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <div class="container">
      <h1>Hello it is your container speaking</h1>
      <p>This nginx page was created by your Docker container.</p>
      <p>Now it’s time to create a Gremlin attack.</p>
    </div>
  </body>
</html>

コンテナを作成します。

cd ../

docker run -l service=nginx --name docker-nginx -p 80:80 -d -v ${PWD}/docker-nginx/html:/usr/share/nginx/html nginx
docker ps -a

を実行すると

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS N
AMES
4bd5dfa89e3a nginx "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp docker-nginx

のように表示されるはずです。

3. Gremlinをコンテナにインストールする

  • Gremlinのアカウントを作成(サインアップ)
  • Gremlin Daemonのcredentialsを取得

する必要があります。

サインイン後、チーム設定の画面に遷移してください。

Gremlin_team

Team ID, Secret Keyが必要なため、控えておきます。

export GREMLIN_TEAM_ID={Team ID}
export GREMLIN_TEAM_SECRET={Secret Key}

を実行し、環境変数に登録します。

公式のGremrin docker imageを使ってコンテナを起動します。

docker run -d --net=host \
--cap-add=NET_ADMIN --cap-add=SYS_BOOT --cap-add=SYS_TIME \
--cap-add=KILL \
-v $PWD/var/lib/gremlin:/var/lib/gremlin \
-v $PWD/var/log/gremlin:/var/log/gremlin \
-e GREMLIN_TEAM_ID="$GREMLIN_TEAM_ID" \
-e GREMLIN_TEAM_SECRET="$GREMLIN_TEAM_SECRET" \
gremlin/gremlin daemon

docker ps で確認し、gremlinコンテナが起動したか確認します。

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7528d9390e4 gremlin/gremlin "/entrypoint.sh daem…" 2 minutes ago Up 2 minutes friendly_benz

4bd5dfa89e3a nginx "nginx -g 'daemon of…" 3 hours ago Up 3 hours 0.0.0.0:80->80/tcp docker-nginx

gremlinのコンテナにログインし、コマンドが使える確認します。

※ CONTAINER IDは各自のものに置き換えてください。

docker exec -it c7528d9390e4 /bin/bash

# コンテナ内で
gremlin help attack-container
# 以下のようにコンテナに攻撃種類がリストされます
Type "gremlin help attack-container TYPE" for more details:

blackhole # An attack which drops all matching network traffic
cpu # An attack which consumes CPU resources
io # An attack which consumes IO resources
latency # An attack which adds latency to all matching network traffic
memory # An attack which consumes memory
packet_loss # An attack which introduces packet loss to all matching network traffic
shutdown # An attack which forces the target to shutdown
dns # An attack which blocks access to DNS servers
time_travel # An attack which changes the system time.
disk # An attack which consumes disk resources
process_killer # An attack which kills the specified process

exit

4. Gremlin CLIを使用して、Nginxコンテナに対してGremlinコンテナからCPU攻撃をする

Nginxコンテナのリソース状況を確認してみます。

※ CONTAINER IDは各自のものに置き換えてください

docker run -it --rm --pid=container:4bd5dfa89e3a htop

no_cpu_attack

まだ攻撃を加えていないのでスカスカです。

では、以下のコマンドで攻撃を加えてみます。 ※ CONTAINER IDは各自のものに置き換えてください

1コアのデフォルト設定を使用して60秒間CPUを消費します。

docker run -d -it \
--cap-add=NET_ADMIN \
-e GREMLIN_TEAM_ID="${GREMLIN_TEAM_ID}" \
-e GREMLIN_TEAM_SECRET="${GREMLIN_TEAM_SECRET}" \
-v /var/run/docker.sock:/var/run/docker.sock \
gremlin/gremlin attack-container 4bd5dfa89e3a cpu

攻撃中のコンテナのリソースを確認してみます。

docker run -it --rm --pid=container:4bd5dfa89e3a htop

cpu_attack

ご覧の通りgremlinからのcpu attackでCPUを消費していることがわかります。

gremlinの画面から確認してみると、以下のようにactiveな攻撃、終了済みの攻撃の履歴が見れます。

gremlin_list

最後に

今回はgremlin cliを利用し、dockerコンテナにcpu攻撃を仕掛け、リソース状況を確認しました。 比較的簡単にできるかと思うので、カオスエンジニアリングのツールを検証している方がいればぜひやってみてください。

単体のコンテナに対して攻撃を仕掛けたのですが、次回以降は複数のコンテナ、また、分散システムなどにも攻撃をかける検証をしていきたいと思っております。

以上です

参考