カオスエンジニアリングツールGremlinでECS上のPHPアプリケーションにCPU負荷を注入してみた

2020.11.25

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

カオスエンジニアリングという言葉自体は知っているが、実際に試したことがある方は少ないのではないでしょうか。

今回は、カオスエンジニアリングを簡単に実施できるGremlinというツールでECS上のアプリケーションに障害を注入していきたいと思います。

なお、こちらは公式ブログを参考にしています。

構成図

せっかちな人へ

GitHubにソースコードを上げているのでそちらをご確認ください。

gremlin-ecs-php-sample-app

PHPサンプルアプリケーションの作成

Laravelチュートリアル – 掲示板を作成してみようを参考にしました。

laravel new laravel-bbslaravel-bbs 配下に適当なアプリケーションを作成しています。

$ tree laravel-bbs -L 1
laravel-bbs
├── app
├── artisan
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── package.json
├── phpunit.xml
├── public
├── README.md
├── resources
├── routes
├── server.php
├── storage
├── tests
├── vendor
└── webpack.mix.js

本題と逸れるため説明は割愛します。

出来上がったのはこんな感じのサイト。 書き込みはできないリードオンリーのサイトです。

Dockerfileの作成

docker配下にnginxphp用のDockerfileをそれぞれ作成します。

$ tree docker -L 2
docker
├── nginx
│   ├── default.conf
│   └── dockerfile
└── php
    ├── dockerfile
    └── php.ini

また、docker-compose upで起動できるようdocker-compose.ymlも作成しておきます。

それぞれの設定はソースコードを確認してください。

ローカルでGremlinを試してみる

先ほど作成したアプリケーションをdocker-compose upで起動します

$ docker-compose up
Starting php ... done
Starting nginx ... done
Attaching to php, nginx
...

次に、こちらを参考Gremlinコンテナをサイドカーとして起動します。

  • 環境変数をセット
export GREMLIN_TEAM_ID=<your-team-id>
export GREMLIN_TEAM_SECRET=<your-team-secret>
  • Gremlinコンテナの起動

※ 少し改良しています

$ docker run -d --rm --net=host \
    --name gremlin-deamon \
    --cap-add=NET_ADMIN --cap-add=SYS_BOOT --cap-add=SYS_TIME \
    --cap-add=KILL \
    -v /tmp/gremlin/var/lib/gremlin:/var/lib/gremlin \
    -v /tmp/gremlin/var/log/gremlin:/var/log/gremlin \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -e GREMLIN_TEAM_ID="$GREMLIN_TEAM_ID" \
    -e GREMLIN_TEAM_SECRET="$GREMLIN_TEAM_SECRET" \
    gremlin/gremlin daemon

Gremlinの管理画面で、先ほど起動したPHPアプリケーションがターゲットに登録されているのが確認してみます。

ためしにホストの1コアに対してCPU利用率を100%まで上げてみます。

htopコマンドで見るとちゃんと動いていることが確認できます。

ECS用のCloudFormationの作成

実際にECS上で動かすため、CloudFormationのテンプレートを作成していきます。

$ tree cloudformation -L 2
cloudformation
├── template-for-ecr.yml
└── template.yml

template-for-ecr.yml がECR用、template.ymlがその他もろもろの設定です。

長くなるので、最終的なテンプレートはソースコードを確認してください。

インフラとアプリケーションのデプロイ

まずは、template-for-ecr.ymlをデプロイします。

aws cloudformation deploy \
  --template-file cloudformation/template-for-ecr.yml \
  --stack-name php-repo-stack

つづいて、DockerイメージをビルドしてECRにPUSHします。

ACCOUNT_ID=$(aws sts get-caller-identity --output text --query 'Account')
aws ecr get-login-password | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
docker-compose build nginx php
docker tag arai-nginx:latest ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/php-app-repo/nginx:latest
docker tag arai-php:latest ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/php-app-repo/php:latest
docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/php-app-repo/nginx:latest
docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/php-app-repo/php:latest

さいごに、template.ymlをデプロイします。

aws cloudformation deploy \
  --template-file cloudformation/template.yml \
  --stack-name php-app-stack \
  --parameter-overrides \
    GremlinTeamId=${GREMLIN_TEAM_ID} \
    GremlinTeamSecret=${GREMLIN_TEAM_SECRET} \
  --capabilities CAPABILITY_NAMED_IAM

ALBのDNS名からサイトが表示されるか確認します。

Gremlinで攻撃する

Auto Scaling Groupsの設定でCPU利用率が50%以上を超えるとスケールアップするように設定しているので、CPU負荷をかけてちゃんと動作するのか試していきます。

しばらくするとCPU利用率が99%ぐらいになっているのが確認できます。

その後、ECSインスタンスが増えて、新しいタスクが起動しているのが確認できます。

おわりに

クラスメソッドではGremlinの導入支援を行っています。

気になった方はぜひ次回のウェビナーにご参加ください。

【12/9(水)ウェビナー】はじめてのカオスエンジニアリング:Gremlin