Кроме горячо любимых Apache Bench и JMeter имеется интересная утилита Yandex Tank.
Ей давно пользуются наши QA, пришло время и мне его потрогать для проверки одной проблемы с Kubernetes, о которой поговорим в следующем посте.
В этом — посмотрим на базовые возможности Yandex.Tank.
Из особенно приятного — в отличии от Apache Bench выводит статистику по кодам ответов, и проще в настройке и запуске, чем JMeter, плюс гибкая настройка автостопа на случай, если «Что-то пошло не так» (с)
Содержание
Компоненты
См. Modules.
Сам Yandex Tank написан Python.
Для выполнения тестов имеется несколько модулей Load generators, по-умолчанию используется Phantom на С++.
Telegraf — для мониторинга тестируемого хоста — подключается по SSH, запускает свой агент и снимает метрики CPU/mem/etc.
Overloader — используется для загрузки полученных данных в Yandex Overloader или InfluxDB, но мы им не воспользуемся. См. Artifact uploaders.
Кроме того, в примерах ниже не рассматривается создание отдельных «патронов» (ammo), т.к. мы не QA, и мне пока достаточно будет простых GET на какие-нибудь URI. Still, см. документацию по ним в Preparing requests.
Запуск
Создадим минимальный конфиг для запуска Phantom:
phantom:
address: rtfm.co.ua:443
header_http: "1.1"
headers:
- "[Host: rtfm.co.ua]"
uris:
- /
load_profile:
load_type: rps
schedule: const(1,30s)
ssl: true
console:
enabled: true
telegraf:
enabled: false
Тут:
phantom:address: адрес и порт тестируемого хостаheader_http: версия HTTP для тестов, зададим 1.1, что бы использовать одно соединение на запросы, а не открывать новое каждый раз (см. HTTP persistent connection)headers: заголовки, передаваемые на тестируемый серверuris: список URI, к которым выполняем запросыload_profile:load_type: может бытьrpsилиinstances:rps: requests per second — указываем желаемое количество запросов в секундуinstances: указываем желаемое количество активных тредов, которые будут генерировать столько rps, сколько смогут, см. Dynamic thread limit
schedule: может бытьconst,lineилиstep(или все три вместе) — определяет характер генерируемой нагрузки, см. Tutorials:const: указывается в виде (load,dur), где load — кол-во rps, dur — время для выполнение тестирования, в примере выше — выполняем 1 запрос в секундв течении 30 секундline: указывается в виде (a,b,dur), где a — начальное кол-во rps, b — конечное, dur — время для выполнение тестирования, в кечении котрого значение будет линейно увеличиваться от a до bstep: указывается в виде (a,b,step,dur), где a — начальное кол-во rps, b — конечное, step — на сколько rps увеличивать, dur — время между каждым step
ssl: включаем поддержку запросов по HTTPS (не забываем указать 443 вaddress)
console: включаем вывод результатов в консольtelegraf: агент мониторинга для сбора метрик с тестируемого хоста, рассмотрим в Monitoring (Telegraf)
И запускаем Танк из Docker-образа:
[simterm]
$ docker run --rm -v $(pwd):/var/loadtest -it direvius/yandex-tank
[/simterm]
Результат:
Monitoring (Telegraf)
С помощью Telegraf можно по SSH подключиться к тестируемом хосту, и с нимать метрики с него, после чего отображать их в результатах тестирования в режиме реального времени.
Включаем его в load.yaml:
... telegraf: enabled: true package: yandextank.plugins.Telegraf
Настройки метрик описываются в отдельном файле, создаём monitoring.xml, см. Configuration file format:
<Monitoring>
<Host address="rtfm.co.ua" interval="1" username="root">
<CPU />
<Kernel />
<Net />
<System />
<Memory />
<Disk />
<Netstat/>
</Host>
</Monitoring>
Тут в address — сервер, с которого будем собирать метрики, interval — интервал сбора метрик, username — пользователь, под которым Telegraf будет подключаться на сервер.
При этом у этого пользователя на тестируемом хосте в ~/.ssh/authorized_keys должна быть записана публичная часть SSH-ключа для аутентификации (см. SSH: авторизация по ключам).
Приватную часть передадим в контейнер исмонтируем в контейнер в файл /root/.ssh/id_rsa, т.к. процессы в контейнере запускаются под рутом:
[simterm]
$ docker run --rm -v $(pwd):/var/loadtest -v /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11:/root/.ssh/id_rsa -it direvius/yandex-tank
[/simterm]
Paramiko: SSHException: not a valid RSA private key file
При первом запуске Telegraf выдал ошибку:
[simterm]
16:32:54 [ERROR] Failed to install monitoring agent to rtfm.co.ua
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/yandextank/plugins/Telegraf/client.py", line 209, in install
out, errors, err_code = self.ssh.execute(cmd)
File "/usr/local/lib/python2.7/dist-packages/yandextank/common/util.py", line 72, in execute
with self.connect() as client:
File "/usr/local/lib/python2.7/dist-packages/yandextank/common/util.py", line 42, in connect
timeout=self.timeout, )
File "/usr/local/lib/python2.7/dist-packages/paramiko/client.py", line 437, in connect
passphrase,
File "/usr/local/lib/python2.7/dist-packages/paramiko/client.py", line 749, in _auth
raise saved_exception
SSHException: not a valid RSA private key file
[/simterm]
Возникает она из-за формата ключа — на DigitalOcean он по-умолчанию в PEM/OpenSSH.
Проверяем:
[simterm]
$ file /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11 /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11: OpenSSH private key
[/simterm]
Конвертируем его в RSA:
[simterm]
$ ssh-keygen -p -m PEM -f /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11
[/simterm]
Проверяем снова:
[simterm]
$ file /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11 /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11: PEM RSA private key
[/simterm]
Запускаем тесты повторно — Telegraf выведет собираемые и игнорируемые метрики и вообще свою конфигурацию:
[simterm]
$ docker run --rm -v $(pwd):/var/loadtest -v /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11:/root/.ssh/id_rsa -it direvius/yandex-tank
...
16:36:38 [INFO] Detected monitoring configuration: telegraf
16:36:38 [INFO] Preparing test...
16:36:38 [INFO] Telegraf Result config {'username': 'root', 'comment': '', 'telegraf': '/usr/bin/telegraf', 'python': '/usr/bin/env python2', 'host_config': {'Kernel': {'fielddrop': '["boot_time"]', 'name': '[inputs.kernel]'}, 'Netstat': {'name': '[inputs.netstat]'}, 'System': {'fielddrop': '["n_users", "n_cpus", "uptime*"]', 'name': '[inputs.system]'}, 'Memory': {'fielddrop': '["active", "inactive", "total", "used_per*", "avail*"]', 'name': '[inputs.mem]'}, 'Net': {'interfaces': '["eth0","eth1","eth2","eth3","eth4","eth5"]', 'fielddrop': '["icmp*", "ip*", "udplite*", "tcp*", "udp*", "drop*", "err*"]', 'name': '[inputs.net]'}, 'Disk': {'name': '[inputs.diskio]', 'devices': '["vda0","sda0","vda1","sda1","vda2","sda2","vda3","sda3","vda4","sda4","vda5","sda5"]'}, 'CPU': {'fielddrop': '["time_*", "usage_guest_nice"]', 'name': '[inputs.cpu]', 'percpu': 'false'}}, 'startup': [], 'host': 'rtfm.co.ua', 'telegrafraw': [], 'shutdown': [], 'port': 22, 'interval': '1', 'custom': [], 'source': []}
16:36:38 [INFO] Installing monitoring agent at [email protected]...
16:36:38 [INFO] Creating temp dir on rtfm.co.ua
16:36:38 [INFO] Execute on rtfm.co.ua: /usr/bin/env python2 -c "import tempfile; print tempfile.mkdtemp();"
...
[/simterm]
После чего запустит нагрузочное, а в правой панели будет выведить статистику ресурсов сервера:
И работа агента на тестируемом сервере:
[simterm]
root@rtfm-do-production-d10:~# ps aux | grep tele root 4580 0.5 0.4 309992 9436 pts/1 Ssl+ 15:38 0:00 python2 /tmp/tmpZez6yJ/agent.py --telegraf /tmp/telegraf --host rtfm.co.ua root 4582 7.1 1.5 851256 31896 ? Ssl 15:38 0:01 /tmp/telegraf -config /tmp/tmpZez6yJ/agent.cfg
[/simterm]
Autostop
Модуль автостопа позволяет автоматически остановить тесты при возникновении каких-либо событий.
Например, можно настроить остановку тестирования, если количество 5хх ошибок будет больше 10%, или время ответа превысит некое пороговое значение.
Добавляем:
...
autostop:
autostop:
- http(2xx,100%,1s)
Тут для примера — остановить выполнение, если в течении 1 секунды 100% ответов будут с кодом 2хх.
Запускаем, и:
[simterm]
$ docker run --rm -v $(pwd):/var/loadtest -v /home/setevoy/.ssh/setevoy-do-nextcloud-production-d10-03-11:/root/.ssh/id_rsa -it direvius/yandex-tank ... 16:56:24 [INFO] Monitoring received first data. 16:56:24 [WARNING] Autostop criterion requested test stop: http(2xx,100%,1s) 16:56:24 [WARNING] Autostop criterion requested test stop: 2xx codes count higher than 100.0% for 1s, since 1612889780 16:56:24 [INFO] Finishing test... 16:56:24 [INFO] Stopping load generator and aggregator ...
[/simterm]
Тест сразу остановился.
Больше примеров — в документации тут>>>.
Полность файл load.yaml получился таким:
phantom:
address: rtfm.co.ua:443
header_http: "1.1"
headers:
- "[Host: rtfm.co.ua]"
uris:
- /
load_profile:
load_type: rps
schedule: const(1,30s)
ssl: true
console:
enabled: true
telegraf:
enabled: true
package: yandextank.plugins.Telegraf
config: monitoring.xml
autostop:
autostop:
- http(2xx,100%,1s)
В целом, на этом всё.
Возможностями порадовал, можно придумывать запуск автоматических load-тестов для приложений в Kubernetes-кластере.

