障害注入の自動化を目指してGremlin APIを使ってみた

みなさま、自動化はお好きでしょうか?カオスエンジニアリングにおいても自動化は重要なトピックの1つです。
2020.07.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。AWS事業本部のKyoです。

みなさま、自動化はお好きでしょうか?カオスエンジニアリングにおいても自動化は重要なトピックの1つです。

今回はGetting started with Gremlin’s APIを元にAPIから障害注入を行ってみました。APIから障害注入を行うことでCI/CDとの統合が可能になり、障害注入の自動化が可能になります。

概要

今回は以下の2つを行っています。

  • GUIから簡単にAPIの実行コマンドを取得する
  • CLIから障害注入をやってみる

準備

  • Gremlinアカウント(CompanyName, Team ID, Secret Keyが必要)
  • Gremlin agentがインストールされたEC2インスタンス x1

各種情報の取得方法やGremlin agentのインストール、GUIからの障害注入のは方法などは以下のブログをご覧ください。

15分で始めるGremlinによるカオス実験

GUIから簡単にAPIの実行コマンドを取得する

curlを利用してAPIを叩くことは多いと思いますが、パラメータの設定等に手間取ることは少なくないのではないでしょうか。Gremlinのコンソールをポチポチするだけで、APIの実行コマンドが簡単に生成できます。

API実行コマンドの取得

まず、Gremlinのコンソールにログインし、左カラムよりAttacksを選択します。

通常の攻撃と同様に対象と注入する障害を選択します。 Choose Hosts to targetから準備していたインスタンスを選択し、Choose a GremlinからCPU攻撃を120秒としました。

通常ならば、ここでUnleash Gremlinのボタンをクリックするところですが、今回はその右側のGremlin API Examplesをクリックします。

すると、以下の画面が表示されるので、CURL Exampleの右のCopy to clipboadをクリックします。

以下のコマンドがクリップボードにコピーできました。 これを実行することで、先ほど選択した内容の障害注入を実施できます。パラメータにもCPU120という文字列が確認できます。

 curl -i -X POST 'https://api.gremlin.com/v1/attacks/new?teamId=<your team id>' \
 -H 'Content-Type: application/json;charset=utf-8' \
 -H 'Authorization: <your bearer>' \
 -d '{"target":{"hosts":{"ids":["10.0.1.82"]},"type":"Exact"},"command":{"type":"cpu","commandType":"CPU","args":["-l","120","-c","1"]}}'

同様の方法で、CPU攻撃以外についてもGUIからAPIの実行コマンドを生成することが可能です。

障害注入の実施と確認

障害注入を実行し、確認します。 Activeとして表示されています。

詳細を表示します。

念のため、対象のEC2にもログインしtopコマンドを実行してみました。 gremlinによってCPUリソースが消費されていることが確認できました。

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 2637 gremlin   20   0   23400   5872   5500 S 99.3  0.6   1:00.27 gremlin
    1 root      20   0  159820   8928   6568 S  0.0  0.9   0:02.77 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 rcu_gp
    4 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 rcu_par_gp
    5 root      20   0       0      0      0 I  0.0  0.0   0:00.07 kworker/0:0-eve
〜〜以下略〜〜

CLIから障害注入をやってみる

自動化のためには一連の動作がCLIで完結する必要があります。

認証

以下のコマンドでBearerを取得します。

curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'email=gremlin@gremlin.com' \
    --data-urlencode 'password=P@ssw0rd1!' \
    --data-urlencode 'companyName=Chaos' \
    'https://api.gremlin.com/v1/users/auth'

コンソールへのログインにMFAを利用している場合は、下記のように-data-urlencodeが必要です。

curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'email=gremlin@gremlin.com' \
    --data-urlencode 'password=changeit' \
    --data-urlencode 'token=000000' \
    'https://api.gremlin.com/v1/users/auth/mfa/auth?getCompanySession=true'

レスポンスとして以下のようなJSONが返ってきます(一部の結果はダミーです)。

[
  {
    "company_id": "<company_id>",
    "company_is_alfi_enabled": true,
    "expires_at": "2020-07-17T01:58:15.357Z",
    "header": "Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "identifier": "<email>",
    "org_id": "<org_id>",
    "org_name": "<org_name>",
    "renew_token": "<renew_token>",
    "token": "<token>",
    "tier": "Enterprise",
    "roles": [
      "<role1>",
      "<role2>"
    ],
    "privileges": [
      "<privileges1>",
      "<privileges2>"
    ],
    "company_name": "<company_name>",
    "last_login": "2020-06-21T09:28:53.820Z"
  }
]

所属している組織の数だけの情報が含まれます。 bearerを利用するため、headerの値を取得し、変数化しておきます。

export bearertoken="Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

障害注入

先ほどと同様にCPU攻撃を120秒行います。今回ターゲットはランダムにしてあります。

curl -X POST \
    --header "Content-Type: application/json" \
    --header "Authorization: $bearertoken" \
    https://api.gremlin.com/v1/attacks/new?teamId=<your team id> \
    --data '
    {
        "command": { "type": "cpu", "args": ["-c", "1", "--length", "120"] },
        "target": { "type": "Random" }
    }'

上記を実行すると実行IDが返されます。これをもとに、障害注入状態の確認を行えます。

障害注入状態の確認

以下のコマンドで障害注入の状態を確認することが可能です。

curl -X GET "https://api.gremlin.com/v1/attacks/<実行ID>?teamId=<your team id>" \
    --header "Authorization: $bearertoken" \
     -H "accept: application/json"

以下のようなJSONが返されます(一部の結果はダミーです)。

{
  "total_clients": 1,
  "infra_target": {
    "resolvedHosts": [
      "ip-192-168-9-36.ap-northeast-1.compute.internal"
    ],
    "targetType": "Host",
    "strategy": {
      "allHosts": false,
      "count": 1,
      "type": "RandomCount",
      "allContainers": false
    },
    "strategyType": "Random"
  },
  "client_metrics_enabled_count": 1,
  "target_type": "Host",
  "version": 9,
  "targets": [
    "ip-192-168-9-36.ap-northeast-1.compute.internal"
  ],
  "org_id": "<org_id>",
  "args": [
    "cpu",
    "-c",
    "1",
    "--length",
    "120"
  ],
  "created_at": "2020-07-16T14:26:27.210Z",
  "create_source": "Api",
  "stage": "Successful",
  "execution_stage_summary": {
    "Successful": 1
  },
  "infra_command": {
    "commandType": "CPU",
    "commandArgs": {
      "allCores": false,
      "cores": 1,
      "length": 120,
      "percent": 100
    }
  },
  "stage_lifecycle": "Complete",
  "guid": "<実行ID>",
  "create_user": "<email>",
  "start_time": "2020-07-16T14:26:27.210Z",
  "end_time": "2020-07-16T14:28:40.105Z",
  "updated_at": "2020-07-16T14:28:40.105Z",
  "kind": "Api"

念のため、コンソールも見てみます。

こちらでも障害注入の成功が確認できました!

Appendix

APIリファレンスは以下にあります。

Gremlin APIリファレンス

おわりに

今回はGremlin APIを利用して、GUIから簡単にAPIの実行コマンドを取得し、CLIから障害注入を実施してみました。

カオスエンジニアリングの原則の詳細原則の1つ、「継続的に実行する検証の自動化」 に一歩近づけたのではないでしょうか。

手作業による検証は、手間がかかり、最終的には長続きしません。実験を自動化し、継続して実行します。カオスエンジニアリングは、オーケストレーションと分析の両方を行うためにシステムを自動化します。

以上、何かのお役に立てれば幸いです。