ども、かっぱです。
tl;dr
考察シリーズ第三弾。
上記の記事で紹介されていた「AWS ECS + Docker + Locust による負荷テスト」について、どんな風に実現するんだろうなあとずーっと気になっていたので、自分なりに ECS + Locust な負荷試験環境を考えてみたのでメモ。
メモ
こんな感じになった(ゴール)
ソースコードとか
何をする必要があったのか
- Locust Master と Locust Slave をそれぞれ異なるタスクに分割する
- 同一の ECS クラスタに Master と Slave を個別にデプロイする
- コンテナインスタンスを跨って Locust クラサバ構成を構築する必要があったので etcd や Consul にお出まし頂いた(結局は Consul を採用した)
困った点
- Docker Compose では docker-compose.yml 内に定義されている Service 毎に scale コマンドが発行することが出来たが、ecs-cli compose 経由だと Task 毎にしか scale することが出来ない
- Consul も Docker コンテナで立ち上げているが、Consul コンテナは必ず各コンテナインスタンス上で起動する必要があるので手動でコンテナを起動する必要があった
- Locust の Master ノードコンテナが起動しているコンテナインスタンス IP を保存するだけのみ Consul を動かしておくのはちょっと無駄が大きい(かも)
- Consul クラスタの構成をどうするか(Atlas で Token を発行して
--atlas-join
を利用した)
Demo
- 事前に Locust Master と Locust Slave コンテナをビルドして ECR あたりに push しておく
$ aws --region us-east-1 ecr get-login $ docker login -u AWS -p xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -e none https://xxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com $ git clone https://github.com/inokappa/sample-ecs-locust.git $ cd sample-ecs-locust $ cd docker-locust-master $ docker build $ docker build -f Dockerfile.master -t docker-locust-master . $ docker tag docker-locust-master xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/docker-locust-master $ docker push xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/docker-locust-master $ cd ../docker-locust-slave $ docker build -f Dockerfile.slave -t docker-locust-slave . $ docker tag docker-locust-slave xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/docker-locust-slave $ docker push docker-locust-slave xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/docker-locust-slave
$ ecs-cli up --keypair ${SSH_KEY_NAME} \ --capability-iam \ --size 2 \ --vpc vpc-xxxxxxxx \ --instance-type t2.small \ --subnets subnet-xxxxxxxx,subnet-xxxxxxxx \ --azs ap-northeast-1a,ap-northeast-1c
Consul も利用するので、Consul Server を動かすホスト(コンテナインスタンス)の数は奇数が望ましいけど、今回は検証ということでコンテナインスタンスは 2 台で起動する。
また、ecs-cli でコンテナインスタンスを起動した場合には、セキュリティグループは 0.0.0.0/0 で HTTP ポート(80 番)が開放されたルールのみがアタッチされるが、各コンテナインスタンス間で Consul の通信を許可するルールも追加する必要があるので注意する。
- Consul コンテナの起動(事前に Atlas で token を発行しておくこと)
# # 一台目のコンテナインスタンスで consul server を起動 # - -bootstrap オプションは古いオプションなので基本的には利用しない # $ docker run --net=host -d \ -p 8300:8300 \ -p 8301:8301/tcp \ -p 8302:8302/tcp \ -p 8301:8301/udp \ -p 8302:8302/udp \ -p 8303:8303 \ -p 8400:8400 \ -p 8500:8500 \ -p 8600:8600 \ --name consul-node01 \ gliderlabs/consul-server \ -server \ -bootstrap \ -advertise $(curl -s http://169.254.169.254/latest/meta-data/local-ipv4) \ -atlas=inokappa/demo01 --atlas-join --atlas-token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # # 二台目のコンテナインスタンスで consul server を起動 # $ docker run --net=host -d \ -p 8300:8300 \ -p 8301:8301/tcp \ -p 8302:8302/tcp \ -p 8301:8301/udp \ -p 8302:8302/udp \ -p 8303:8303 \ -p 8400:8400 \ -p 8500:8500 \ -p 8600:8600 \ --name consul-node02 \ gliderlabs/consul-server \ -server \ -advertise $(curl -s http://169.254.169.254/latest/meta-data/local-ipv4) \ -atlas=inokappa/demo01 --atlas-join --atlas-token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # # consul クラスタの確認(consul クラスタ自体は 3 ノード以上で奇数ノードでの構成が望ましいので注意する) # $ docker exec -t -i consul-node02 consul members Node Address Status Type Build Protocol DC ip-10-0-0-164 10.0.0.164:8301 alive server 0.6.3 2 dc1 ip-10-0-1-242 10.0.1.242:8301 alive server 0.6.3 2 dc1
- Locust Master コンテナを起動する
# # environment で TARGET_HOST を指定する # $ vi ecs-compose-master.yml master: image: xxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/docker-locust-master cpu_shares: 100 mem_limit: 268435456 environment: - TARGET_HOST=http://kome.inokara.com # # Task として Locust Master コンテナを起動する # $ ecs-cli compose -f ecs-compose-master.yml up
以下のようにブラウザからアクセスすることが出来る。
また、consul には Locust の Master ノードコンテナが起動しているインスタンスのプライベート IP アドレスが登録されている。
$ curl 127.0.0.1:8500/v1/kv/locust/master/ip?raw
10.0.1.242
- Locust Slave コンテナを起動する
# # environment で TARGET_HOST を指定する # $ vi ecs-compose-slave.yml slave: image: xxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/docker-locust-slave cpu_shares: 100 mem_limit: 268435456 environment: - TARGET_HOST=http://example.inokara.com # # Task として Locust Slave コンテナを起動する # $ ecs-cli compose -f ecs-compose-slave.yml up
以下のように Slave が追加されたことを確認する。
- 負荷試験を開始する
- Locust Slave をスケールアウトする
# # 最初の Slave 1 台から 3 台に増やす # $ ecs-cli compose -f ecs-compose-slave.yml scale 3
以下のように出力される。
INFO[0000] Starting container... container=79377890-bf38-483c-a516-e865c8951372/slave INFO[0000] Starting container... container=9137b17d-fb67-4d7f-9e16-92281beab362/slave INFO[0000] Describe ECS container status container=79377890-bf38-483c-a516-e865c8951372/slave desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-docker-locust-slave:3 INFO[0000] Describe ECS container status container=9137b17d-fb67-4d7f-9e16-92281beab362/slave desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-docker-locust-slave:3 INFO[0006] Started container... container=79377890-bf38-483c-a516-e865c8951372/slave desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-docker-locust-slave:3 INFO[0006] Started container... container=9137b17d-fb67-4d7f-9e16-92281beab362/slave desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-docker-locust-slave:3
3 台にスケールさせるということで、2 台のコンテナが追加される。どのコンテナインスタンスに追加されるかは ECS 次第となる。
- Locust Slave をスケールインする
# # 最初の Slave 1 台から 1 台に減らす # $ ecs-cli compose -f ecs-compose-slave.yml scale 1
以下のように出力される。
INFO[0000] Stopping container... container=79377890-bf38-483c-a516-e865c8951372/slave INFO[0000] Stopping container... container=9137b17d-fb67-4d7f-9e16-92281beab362/slave INFO[0000] Describe ECS container status container=79377890-bf38-483c-a516-e865c8951372/slave desiredStatus=STOPPED lastStatus=RUNNING taskDefinition=ecscompose-docker-locust-slave:3 INFO[0000] Describe ECS container status container=9137b17d-fb67-4d7f-9e16-92281beab362/slave desiredStatus=STOPPED lastStatus=RUNNING taskDefinition=ecscompose-docker-locust-slave:3 INFO[0006] Stopped container... container=79377890-bf38-483c-a516-e865c8951372/slave desiredStatus=STOPPED lastStatus=STOPPED taskDefinition=ecscompose-docker-locust-slave:3 INFO[0006] Stopped container... container=9137b17d-fb67-4d7f-9e16-92281beab362/slave desiredStatus=STOPPED lastStatus=STOPPED taskDefinition=ecscompose-docker-locust-slave:3
1 台にスケールダウンさせるということで、2 台のコンテナが削除される。
最後に
課題
- コンテナインスタンスの Auto Scaling をどうする?
- たまに Master / Slave コンテナが正常に終了しない
ということで...
- Quipper さんでは ECS + Locust をどのように実装し、活用しているのかめっちゃ気になる次第。機会があれば、是非お話しを伺いたい次第。