Cloud Foundry Advent Calender 2018 の24日目
先進的な企業・サービスで導入されているカオスエンジニアリングを実施してみる。Cloud FoundryやKubernetesなど、BOSHで構築された環境であれば、本記事の方式で比較的簡単に導入できる。
なお、本記事では、BOSH環境でのカオスエンジニアリングの導入・動作確認までを範囲としており、実サービスでの使用事例等は含みませんのでご了承ください。
前提環境
こちらで構築したBOSH環境で試験する。
TurbuleneをBOSHデプロイする
カオスエンジニアリングツールとしては、BOSH用に作られているTurbulenceを使用する。
TurbulenceのクライアントをUAAに登録する
事前準備としてBOSH DirectorのUAAにTurbulenceのクライアントを登録しておく。
$ vi uaac-login.sh bosh int creds.yml --path /uaa_ssl/ca > uaa_ca_cert uaac target https://$BOSH_ENVIRONMENT:8443 --ca-cert uaa_ca_cert uaac token client get uaa_admin -s `bosh int creds.yml --path /uaa_admin_client_secret` $ vi uaac-turbulence.sh uaac client add turbulence \ --name turbulence \ --secret turbulence-secret \ --authorized_grant_types client_credentials,refresh_token \ --authorities bosh.admin $ ./uaac-login.sh Target: https://192.168.1.222:8443 Context: uaa_admin, from client uaa_admin Successfully fetched token via client credentials grant. Target: https://192.168.1.222:8443 Context: uaa_admin, from client uaa_admin $ ./uaac-turbulence.sh scope: uaa.none client_id: turbulence resource_ids: none authorized_grant_types: refresh_token client_credentials autoapprove: authorities: bosh.admin name: turbulence required_user_groups: lastmodified: 1545644889344 id: turbulence
Turbulence APIサーバをデプロイする
git submodule add https://github.com/cppforlife/turbulence-release
Releaseファイルはここから取得する。
https://bosh.io/releases/github.com/cppforlife/turbulence-release?all=1
ops-files/turbulence-options.yml
- type: replace path: /releases/name=turbulence value: name: "turbulence" version: "0.10.0" url: "https://bosh.io/d/github.com/cppforlife/turbulence-release?v=0.10.0" sha1: "259344312796e23500b2836a15140f8f09ad99ee"
BOSH DirectorのCA Certが必要となるためファイルに書き出しておく。
bosh int ./creds.yml --path /director_ssl/ca > director_ca_cert
deploy-turbulence.sh
bosh deploy -d turbulence turbulence-release/manifests/example.yml \ -o ops-files/turbulence-options.yml \ -v turbulence_api_ip=10.244.0.101 \ -v director_ip=$BOSH_ENVIRONMENT \ --var-file director_ssl.ca=director_ca_cert \ -v director_client=turbulence \ -l turbulence_secret.yml
デプロイが完了したら、CredHubから認証情報を取得してWebGUIにアクセス確認する。
$ vi credhub-login.sh bosh int ./creds.yml --path /credhub_ca/ca > credhub_ca_cert credhub login -s $BOSH_ENVIRONMENT:8844 \ --ca-cert credhub_ca_cert \ --ca-cert uaa_ca_cert \ --client-name credhub-admin \ --client-secret `bosh int ./creds.yml --path /credhub_admin_client_secret` $ ./credhub-login.sh Setting the target url: https://192.168.1.222:8844 Login Successful $ credhub get -n /bosh-lite/turbulence/turbulence_api_password id: b954b174-f705-4b2b-96aa-89cf324122a3 name: /bosh-lite/turbulence/turbulence_api_password type: password value: x8LTqZBRzBFTlOtF9llfYg9bPIQ6Es version_created_at: "2018-12-24T10:00:56Z"
https://<Turbulence IP>:8080
にWebブラウザでアクセスする。turbulence/xxx(credhub getの結果)
でログインする。
まだIncidentを登録していないので何も表示されない。
Turbulence Agentを各VMにインストールする
TurbulenceはAgentを介してAPIサーバと各VMで処理をする。
BOSH VMへのAgentインストールは、共通的に適用できるようにRuntime Configを使用するとよい。
Director Runtime Config - Cloud Foundry BOSH
今回はサンプルとしてnginxのみに適用するが、include句の指定次第で環境全体にも適用できる。
$ vi ./turbulence-runtime.yml --- releases: - name: "turbulence" version: "0.10.0" url: "https://bosh.io/d/github.com/cppforlife/turbulence-release?v=0.10.0" sha1: "259344312796e23500b2836a15140f8f09ad99ee" addons: - name: turbulence_agent include: jobs: - name: nginx release: nginx jobs: - name: turbulence_agent release: turbulence consumes: api: {from: api, deployment: turbulence} properties: debug: false
$ vi ./deploy-turbulence-runtime.sh bosh update-runtime-config turbulence-runtime.yml \ --name=turbulence_agent \ --no-redact
$ ./deploy-turbulence-runtime.sh Using environment '192.168.1.222' as client 'admin' + releases: + - name: turbulence + sha1: 259344312796e23500b2836a15140f8f09ad99ee + url: https://bosh.io/d/github.com/cppforlife/turbulence-release?v=0.10.0 + version: 0.10.0 + addons: + - include: + - name: nginx + release: nginx + jobs: + - consumes: + api: + deployment: turbulence + from: api + name: turbulence_agent + properties: + debug: false + release: turbulence + name: turbulence_agent Release 'turbulence/0.10.0' already exists. Continue? [yN]: y Succeeded
Runtime Configを設定したら、既存のDeploymentを再デプロイする。
$ ./deploy-nginx.sh Using environment '192.168.1.222' as client 'admin' Using deployment 'nginx' releases: + - name: turbulence + sha1: 259344312796e23500b2836a15140f8f09ad99ee + url: https://bosh.io/d/github.com/cppforlife/turbulence-release?v=0.10.0 + version: 0.10.0 + addons: + - include: + jobs: + - name: nginx + release: nginx + jobs: + - consumes: + api: + deployment: turbulence + from: api + name: turbulence_agent + properties: + debug: "<redacted>" + release: turbulence + name: turbulence_agent Continue? [yN]: y Task 31 Task 31 | 10:32:26 | Preparing deployment: Preparing deployment (00:00:02) Task 31 | 10:32:29 | Preparing package compilation: Finding packages to compile (00:00:00) Task 31 | 10:32:29 | Compiling packages: stress/6b00034151fd5be78893a537bd38818ad2a36bef (00:00:19) Task 31 | 10:32:49 | Updating instance nginx: nginx/811fb685-b437-4994-b355-b36d7a58313d (0) (canary) (00:00:26) Task 31 | 10:33:15 | Updating instance nginx: nginx/4de7506b-7a80-407e-9154-91dc98388385 (2) (00:00:26) Task 31 | 10:33:41 | Updating instance nginx: nginx/d0684cd6-93f6-4fc0-b03c-d5380fdd87d2 (1) (00:00:25) Task 31 Started Mon Dec 24 10:32:26 UTC 2018 Task 31 Finished Mon Dec 24 10:34:06 UTC 2018 Task 31 Duration 00:01:40 Task 31 done Succeeded
Processが追加された。
$ bosh -d nginx instances --ps Using environment '192.168.1.222' as client 'admin' Task 32. Done Deployment 'nginx' Instance Process Process State AZ IPs nginx/4de7506b-7a80-407e-9154-91dc98388385 - running z1 10.244.0.3 ~ nginx running - - ~ turbulence_agent running - - nginx/811fb685-b437-4994-b355-b36d7a58313d - running z1 10.244.0.2 ~ nginx running - - ~ turbulence_agent running - - nginx/d0684cd6-93f6-4fc0-b03c-d5380fdd87d2 - running z1 10.244.0.4 ~ nginx running - - ~ turbulence_agent running - - 3 instances Succeeded
Taskを登録する
$ cat turbulence-release/docs/kill-scheduled.sh > turbulence-tasks/scheduled-kill-nginx.sh
nginxを2分毎に1〜2台殺してもらう。(※Limitの動作が期待通りにならない気がする...)
$ cat turbulence-tasks/scheduled-kill-nginx.sh #!/bin/bash body=' { "Schedule": "@every 2m", "Incident": { "Tasks": [{ "Type": "Kill" }], "Selector": { "Deployment": { "Name": "nginx" }, "Group": { "Name": "nginx" }, "ID": { "Limit": "1-2" } } } } ' echo $body | curl -vvv -k -X POST https://turbulence:x8LTqZBRzBFTlOtF9llfYg9bPIQ6Es@10.244.0.101:8080/api/v1/scheduled_incidents -H 'Accept: application/json' -d @- echo
$ ./turbulence-tasks/scheduled-kill-nginx.sh
所定の時間が経過すると、Taskが実行される。
各Incidentを開くと、どのインスタンスに対して処理を実行したかが確認できる。
ちなみに、原因は調査していないが、以下のように00s
を付けた書き方だとうまく動かなかった。
body=' { "Schedule": "@every 2m 00s",
サービス継続確認
最低限のcurlでのアクセス確認をする。DNSラウンドロビンでアクセスしているが、OSの機能で障害VMを避けてアクセスできている。
20:02:31〜20:03:48あたりで.4がダウンしていることが分かる。BOSH Releaseに問題がなければ、障害VMはBOSHのHealth Monitorにより自動的に復旧される。
$ while true; do sleep 5; date "+%H:%M:%S"|tr '\n ' ' '; curl http://nginx.bosh.local -m 1; done 20:01:51 10.244.0.2 20:01:56 10.244.0.3 20:02:01 10.244.0.4 20:02:06 10.244.0.2 20:02:11 10.244.0.3 20:02:16 10.244.0.4 20:02:21 10.244.0.2 20:02:26 10.244.0.3 20:02:31 10.244.0.2 20:02:37 10.244.0.2 20:02:42 10.244.0.3 20:02:47 10.244.0.2 20:02:52 10.244.0.2 20:02:57 10.244.0.3 20:03:02 10.244.0.2 20:03:08 10.244.0.2 20:03:13 10.244.0.3 20:03:18 10.244.0.2 20:03:23 10.244.0.2 20:03:28 10.244.0.3 20:03:33 10.244.0.2 20:03:38 10.244.0.2 20:03:43 10.244.0.3 20:03:48 10.244.0.4 20:03:53 10.244.0.2 20:03:58 10.244.0.3 20:04:03 10.244.0.4 ...
設定可能Incident
設定可能なIncidentはこちらに記載されている通り。
turbulence-release/api.md at master · cppforlife/turbulence-release · GitHub
Kill
はbosh delete-vm VMCID
で、実際のVM障害とは異なったりするので、要確認。
運用スクリプト
Indicentを取得する。
$ cat turbulence-tasks/get_incidents.sh curl -k https://turbulence:x8LTqZBRzBFTlOtF9llfYg9bPIQ6Es@10.244.0.101:8080/api/v1/scheduled_incidents
IDを引数としてDeleteする。
$ cat turbulence-tasks/delete-incidents.sh #!/bin/sh if [ $# -ne 1 ]; then exit 1 fi curl -k -XDELETE https://turbulence:x8LTqZBRzBFTlOtF9llfYg9bPIQ6Es@10.244.0.101:8080/api/v1/scheduled_incidents/$1
まとめ - TurbulenceでBOSH環境にカオスエンジニアリングを導入する
Turbulenceにより、BOSH環境でランダムにインスタンスに障害を発生させるカオスエンジニアリングの導入を検証した。
本番リリース前の障害試験として実施することにより、想定外の障害動作を摘出することが期待できる。さらには本番環境に適用し、自動回復機能の常時試験も可能となる。