Кроме горячо любимых 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-кластере.
Ссылки по теме
- Автоматизация нагрузочного тестирования при помощи инструмента Яндекс.Танк
- Нагрузочное тестирование c Yandex.Tank и JMeter
- Нагрузочное тестирование http-сервера (nginx), 205k+ RPS
- Тестирование в Яндексе: строим свой Лунапарк
- Пример нагрузочного тестирования сайта с Yandex.Tank