複数EC2インスタンスを立ち上げてvegetaで負荷試験する

aws

vegetaで負荷をかける。

インスタンスを立ち上げるスクリプト

コードはここ。 sambaiz/loadtest

まずキーペアを作成し、EC2インスタンスを立ち上げて、全てのインスタンスが使えるようになるまで待つ。

aws ec2 create-key-pair --key-name LoadTestKeyPare --query 'KeyMaterial' --output text > LoadTestKeyPare.pem
chmod 400 LoadTestKeyPare.pem
aws ec2 run-instances --image-id $AMI_ID --count $INSTANCE_NUM --instance-type t2.micro --key-name LoadTestKeyPare --security-group-ids $SECURITY_GROUP_IDS --subnet-id $SUBNET_ID
...
aws ec2 wait instance-status-ok --instance-ids $INSTANCE_IDS

このAMIは事前にPackerでつくったもの。vegetaをインストールしてファイルディスクリプタの上限を増やしている。

{
  "variables": {
    "aws_access_key": "",
    "aws_secret_key": ""
  },
  "builders": [{
    "type": "amazon-ebs",
    "access_key": "{{user `aws_access_key`}}",
    "secret_key": "{{user `aws_secret_key`}}",
    "region": "ap-northeast-1",
    "source_ami": "ami-0c11b26d",
    "instance_type": "t2.micro",
    "ssh_username": "ec2-user",
    "ami_name": "loadtest {{timestamp}}"
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "wget https://github.com/tsenart/vegeta/releases/download/v6.1.1/vegeta-v6.1.1-linux-amd64.tar.gz",
      "sudo tar xzf vegeta-v6.1.1-linux-amd64.tar.gz -C /usr/local/bin/",
      "sudo sh -c \"echo '* hard nofile 65536' >> /etc/security/limits.conf\"",
      "sudo sh -c \"echo '* soft nofile 65536' >> /etc/security/limits.conf\""
    ]
  }]
}

立ち上がったインスタンスに対してpdshで 各マシンでvegetaを実行させ($VEGETA_CMD)、結果のファイルを集めてreportのinputsで指定すると まとめてレポートを出力してくれる。

pdsh -l ec2-user -w `echo "$PUBLIC_DNS_NAMES" |  paste -d, -s -` "$VEGETA_CMD > result.bin"

for machine in $PUBLIC_DNS_NAMES; do
  scp -i ./LoadTestKeyPare.pem -oStrictHostKeyChecking=no ec2-user@$machine:~/result.bin $machine
done

vegeta report -inputs=`echo $PUBLIC_DNS_NAMES |  paste -d, -s -`

終わったら後片付けをする。trapでCtrl+C等での終了時もインスタンスが残らないようにする。

cleanup() {
  echo "---- Clean up ----"
  aws ec2 terminate-instances --instance-ids $INSTANCE_IDS
  aws ec2 delete-key-pair --key-name LoadTestKeyPare
  rm -f LoadTestKeyPare.pem
  rm $PUBLIC_DNS_NAMES
}
trap cleanup EXIT SIGHUP SIGINT SIGQUIT SIGTERM

実行する

$ brew install awscli pdsh jq vegeta packer
$ aws configure

こんな感じのスクリプト(sample/sample.sh)から実行する。

#!/bin/bash

export INSTANCE_NUM=3

export AMI_ID=ami-*****
export SECURITY_GROUP_IDS=sg-*****
export SUBNET_ID=subnet-*****

export RESOURCES_DIR=res

# https://github.com/tsenart/vegeta#attack
export VEGETA_CMD='vegeta attack -targets=res/targets.txt -rate=1000 -duration=10s'

sh run.sh

sample/res/targets.txt

GET http://example.com/

POST http://example.com/
@res/post.json

結果

何も指定しないとこんな感じ(-reporter=text)。

Requests      [total, rate]            10000, 1000.10
Duration      [total, attack, wait]    10.011642793s, 9.998999835s, 12.642958ms
Latencies     [mean, 50, 95, 99, max]  14.781775ms, 4.262304ms, 68.475899ms, 97.492882ms, 1.096072997s
Bytes In      [total, mean]            15285000, 1528.50
Bytes Out     [total, mean]            110000, 11.00
Success       [ratio]                  100.00%
Status Codes  [code:count]             200:10000  
Error Set:

他にもjsonだったり、plotを指定するとレイテンシのグラフのhtmlが出力される。