Первая статья была посвящена производительности со стороны локальной системы (https://habr.com/ru/articles/753322/).
Смысл данной статьи остаётся схожей, показать максимальную производительность, когда вопрос сохранности данных решается репликами или бэкапами.
Цель данной статьи протестировать производительность трёх систем объединения физических устройств в одну логическую группу при использовании iSER и NVMe-oF.
В рамках данной статьи будут сравниваться три системы, продемострирующие самые высокие показатели по результатам тестов из первой части.
mdadm raid0
LVM stripe
ZFS stripe (default lz4)
А также самое функциональное решение из доступных бесплатных бэкэндов:
ZFS stripe с компрессией и дедупликацией
При подключении через iSER и NVMe-oF.
Оглавление:
1. Тестовый стенд:
Сервер виртуализации 1:
Motherboard: Supermicro H11SSL-i
CPU: EPYC 7302
RAM: 4x64GB Micron 2933MHz
Сеть: 40GbE ConnectX-3 Pro, 10GbE/25GbE ConnectX-4 LN EN
ОС: ESXi 7U3 build 20036586
Сервер виртуализации 2:
Motherboard: Tyan S8030 (ver 1GbE)
CPU: EPYC 7302
RAM: 4x64GB Micron 2933MHz
Сеть: 40GbE ConnectX-3 Pro x2 (Один адаптер прокинут в ВМ)
ОС: ESXi 7U3 build 21930508
ВМ хранения на сервере виртуализации #2, которая будет предоставлять блочный доступ для хоста 1 и хоста 2:
ОС: Ubuntu 22.04, ядро 6.2.0-26 (mitigations=off)
vCPU: 8
RAM: 64GB (для ZFS расширена до 128ГБ)
Диски: 6xPM9A3 1.92TB (обновлены до версии GDC5902Q)
Схема подключения:

Примечание: Для HCIbench отсутствует документация по тому как поменять код тестирования на использование /dev/nvme0nX, вместо /dev/sdX, в связи с этим тесты проводятся с использованием pvscsi.
Согласно тестам различие между pvscsi и nvme контроллером лежит в пределах погрешности измерения 5% (подробнее в таблице тестов) для версии 7U3, так как полноценный NVMe back-to-back был реализован только в 8U2, которая уже не поддерживается ConnectX-3 :(
Параметр Prepare Virtual Disk Before Testing выставлено в значение Random. Тесты проводятся с использованием - 4 ВМ с двумя дисками по 100ГБ, 8 vCPU, 16GB RAM.
Для выбора тестов ориетиром для параметров были взяты значения из следующего источника.
Тест 1:
VDbench - 4k - 80% rng - 50/50 r/w - 8 thread per disk
Тест 2:
VDbench - 8k - 80% rng - 75/25 r/w - 8 thread per disk
Тест 3:
VDbench - 64k - 80% seq - 75/25 r/w - 8 thread per disk
Тест 4:
VDbench - max_iops_read - 4k - 100% rng - 100/0 r/w - 8 thread per disk
Тест 5:
VDbench - max_iops_write - 4k - 100% rng - 0/100 r/w - 8 thread per disk
Для тестирования падения скорости в результате добавления прослойки в виде ВМ использовались тесты из первой части, результаты ниже в таблице и графика (погрешность +-5%,):
SCSI controller (pvscsi) | NVMe controller | % pvscsi=100% | |
Последовательная запись 4M qd=32 | 4603.11 МБ/с | 4594.44 МБ/с | 99.81% |
Последовательное чтение 4M qd=32 | 4618.22 МБ/с | 4618.33 МБ/с | 100.00% |
Случайная запись 4k qd=128 jobs=16 | 558.56 МБ/с | 541.06 МБ/с | 96.87% |
Случайное чтение 4k qd=128 jobs=16 | 589.72 МБ/с | 581.89 МБ/с | 98.67% |
Случайная запись 4k qd=1 fsync=1 | 54.61 МБ/с | 60.02 МБ/с | 109.90% |
Случайное чтение 4k qd=1 fsync=1 | 28.28 МБ/с | 29.76 МБ/с | 105.21% |
Результаты тестов iperf3 между ConnnectX-3 Pro, выполнялись путём проброса ConnectX-3 Pro в ВМ на каждом из хостов, т.е. схема выглядит следующим образом:

Результатом стало:
Sender | 34.93 Gbits/sec |
Receiver | 34.21 Gbits/sec |
Округляя в меньшую сторону, получаем:
34 Gbits/sec (или 4.25 Gbytes/s)
Относительно OFED. Для тестов также использовалась Ubuntu 20.04 с ядром 5.5 и установленным для него OFED, но Ubuntu 22.04.03 с ядром 6.2 продемонстрировала выше производительность и повторяемость в iperf3.
iperf3
Тесты выполнялись в соответствии с данными рекомендациями (https://fasterdata.es.net/performance-testing/network-troubleshooting-tools/iperf/multi-stream-iperf3/)
s1: [ ID] Interval Transfer Bitrate Retr
s1: [ 5] 0.00-10.00 sec 15.2 GBytes 13.0 Gbits/sec 1062 sender
s1:
s1: iperf Done.
s2: - - - - - - - - - - - - - - - - - - - - - - - - -
s2: [ ID] Interval Transfer Bitrate Retr
s2: [ 5] 0.00-10.00 sec 14.8 GBytes 12.7 Gbits/sec 1856 sender
s2:
s2: iperf Done.
s3: - - - - - - - - - - - - - - - - - - - - - - - - -
s3: [ ID] Interval Transfer Bitrate Retr
s3: [ 5] 0.00-10.00 sec 10.0 GBytes 8.59 Gbits/sec 1027 sender
Суммарно 34.29 Gbits/sec
И с флагом -bidir
s1: [ ID] Interval Transfer Bitrate Retr
s1: [ 5] 0.00-10.00 sec 13.4 GBytes 11.5 Gbits/sec 1705 sender
s1: [ 5] 0.00-10.04 sec 13.2 GBytes 11.3 Gbits/sec receiver
s1:
s1: iperf Done.
s2: - - - - - - - - - - - - - - - - - - - - - - - - -
s2: [ ID] Interval Transfer Bitrate Retr
s2: [ 5] 0.00-10.00 sec 10.4 GBytes 8.93 Gbits/sec 2171 sender
s2: [ 5] 0.00-10.05 sec 10.1 GBytes 8.61 Gbits/sec receiver
s3: - - - - - - - - - - - - - - - - - - - - - - - - -
s3: [ ID] Interval Transfer Bitrate Retr
s3: [ 5] 0.00-10.00 sec 16.8 GBytes 14.5 Gbits/sec 1513 sender
s3: [ 5] 0.00-10.04 sec 16.7 GBytes 14.3 Gbits/sec receiver
s3:
s3: iperf Done.
Сравнивания производительность NVMe дисков при их подключении напрямую в ОС или через VMware с PCIe passthrough можно говорить о том, что производительность не меняется, так как результаты находятся в пределах 2% погрешности.
Тесты
PM1725 | Физический | Через PCIe passthrough |
Последовательная запись 4M qd=32 | 1820.50 МБ/c | 1826.50 МБ/c |
Последовательное чтение 4M qd=32 | 4518.00 МБ/c | 4553.50 МБ/c |
Случайная запись 4k qd=128 jobs=16 | 1504.00 МБ/c | 1502.50 МБ/c |
Случайное чтение 4k qd=128 jobs=16 | 3488.00 МБ/c | 3514.50 МБ/c |
Случайная запись 4k qd=1 fsync=1 | 148.50 МБ/c | 172.50 МБ/c |
Случайное чтение 4k qd=1 fsync=1 | 42.90 МБ/c | 45.45 МБ/c |
PM9A3 (0369) | Физический | Через PCIe passthrough |
Последовательная запись 4M qd=32 | 2811.00 МБ/c | 2811.00 МБ/c |
Последовательное чтение 4M qd=32 | 5822.50 МБ/c | 5845.00 МБ/c |
Случайная запись 4k qd=128 jobs=16 | 2807.00 МБ/c | 2806.00 МБ/c |
Случайное чтение 4k qd=128 jobs=16 | 4601.00 МБ/c | 4746.50 МБ/c |
Случайная запись 4k qd=1 fsync=1 | 211.50 МБ/c | 175.50 МБ/c |
Случайное чтение 4k qd=1 fsync=1 | 98.25 МБ/c | 87.80 МБ/c |
PM9A3 (6310) | Физический | Через PCIe passthrough |
Последовательная запись 4M qd=32 | 2811.00 МБ/c | 2811.00 МБ/c |
Последовательное чтение 4M qd=32 | 5846.50 МБ/c | 5835.50 МБ/c |
Случайная запись 4k qd=128 jobs=16 | 2806.50 МБ/c | 2807.00 МБ/c |
Случайное чтение 4k qd=128 jobs=16 | 4610.00 МБ/c | 4743.00 МБ/c |
Случайная запись 4k qd=1 fsync=1 | 211.50 МБ/c | 178.00 МБ/c |
Случайное чтение 4k qd=1 fsync=1 | 98.30 МБ/c | 87.85 МБ/c |
PM9A3 (6314) | Физический | Через PCIe passthrough |
Последовательная запись 4M qd=32 | 2811.00 МБ/c | 2811.00 МБ/c |
Последовательное чтение 4M qd=32 | 5839.00 МБ/c | 5844.00 МБ/c |
Случайная запись 4k qd=128 jobs=16 | 2806.00 МБ/c | 2807.00 МБ/c |
Случайное чтение 4k qd=128 jobs=16 | 4602.50 МБ/c | 4746.00 МБ/c |
Случайная запись 4k qd=1 fsync=1 | 209.00 МБ/c | 174.50 МБ/c |
Случайное чтение 4k qd=1 fsync=1 | 98.65 МБ/c | 87.20 МБ/c |
PM9A3 (3349) | Физический | Через PCIe passthrough |
Последовательная запись 4M qd=32 | 2811.00 МБ/c | 2811.00 МБ/c |
Последовательное чтение 4M qd=32 | 5844.00 МБ/c | 5835.50 МБ/c |
Случайная запись 4k qd=128 jobs=16 | 2807.00 МБ/c | 2806.50 МБ/c |
Случайное чтение 4k qd=128 jobs=16 | 4598.50 МБ/c | 2328.00 МБ/c |
Случайная запись 4k qd=1 fsync=1 | 208.00 МБ/c | 201.50 МБ/c |
Случайное чтение 4k qd=1 fsync=1 | 98.10 МБ/c | 94.90 МБ/c |
PM9A3 (1091) | Физический | Через PCIe passthrough |
Последовательная запись 4M qd=32 | 2811.00 МБ/c | 2811.00 МБ/c |
Последовательное чтение 4M qd=32 | 5827.00 МБ/c | 5842.50 МБ/c |
Случайная запись 4k qd=128 jobs=16 | 2806.50 МБ/c | 2807.50 МБ/c |
Случайное чтение 4k qd=128 jobs=16 | 4514.00 МБ/c | 4651.00 МБ/c |
Случайная запись 4k qd=1 fsync=1 | 205.50 МБ/c | 172.50 МБ/c |
Случайное чтение 4k qd=1 fsync=1 | 98.00 МБ/c | 87.40 МБ/c |
PM9A3 (0990) | Физический | Через PCIe passthrough |
Последовательная запись 4M qd=32 | 2810.50 МБ/c | 2811.00 МБ/c |
Последовательное чтение 4M qd=32 | 5849.50 МБ/c | 5857.00 МБ/c |
Случайная запись 4k qd=128 jobs=16 | 2797.50 МБ/c | 2807.00 МБ/c |
Случайное чтение 4k qd=128 jobs=16 | 4489.00 МБ/c | 4646.00 МБ/c |
Случайная запись 4k qd=1 fsync=1 | 206.00 МБ/c | 183.50 МБ/c |
Случайное чтение 4k qd=1 fsync=1 | 97.20 МБ/c | 88.05 МБ/c |
Рассматриваться будет 2 сценария:
Выдача блочного устройства через iSER с помощью LIO (настройка осуществляется с помощью targetcli-fb с мастер ветки репозитория)
Выдача блочного устройства через NVMe-oF с помощью SPDK.
Небольшое отступление - сперва планировалось использовать нативную реализацию ядра - nvmet (https://enterprise-support.nvidia.com/s/article/howto-configure-nvme-over-fabrics--nvme-of--target-offload), но она не поддерживается VMware (https://koutoupis.com/2022/04/22/vmware-lightbits-labs-and-nvme-over-tcp/ https://communities.vmware.com/t5/ESXi-Discussions/NVMEof-Datastore-Issues/td-p/2301440), поэтому был использован SPDK (https://spdk.io/doc/nvmf.html, https://spdk.io/doc/bdev.html)
2. iSER
Со стороны Linux:
В настройках LIO прописывается enable_iser boolean=true на уровне портала:
set attribute authentication=0 demo_mode_write_protect=0 generate_node_acls=1 cache_dynamic_acls=1
Дополнительно для девайса прописаны следующие опции (https://documentation.suse.com/ses/7/html/ses-all/deploy-additional.html):
set attribute emulate_3pc=1 emulate_tpu=1 emulate_caw=1 max_write_same_len=65535 emulate_tpws=1 is_nonrot=1
Со стороны VMware:
esxcli rdma iser add
Затем настройка аналогична настройкам как для iSCSI массива.
Производительность mdadm с тестами FIO из первой части на 1 ВМ выглядит следующим образом:
mdadm raid0 1ВМ | МБ/c | IOPS |
Последовательная запись 4M qd=32 | 3632.00 МБ/c | 866.20 |
Последовательное чтение 4M qd=32 | 3796.50 МБ/c | 902.14 |
Случайная запись 4k qd=128 jobs=16 | 352.00 МБ/c | 85736.44 |
Случайное чтение 4k qd=128 jobs=16 | 559.50 МБ/c | 136797.19 |
Случайная запись 4k qd=1 fsync=1 | 39.80 МБ/c | 9712.06 |
Случайное чтение 4k qd=1 fsync=1 | 26.10 МБ/c | 6382.21 |
Конечный график выглядит следующим образом:

2.1 MDADM
mdadm --create --verbose /dev/md0 --level=0 --raid-devices=6 /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 /dev/nvme5n1
mdadm - iSER | МБ/с | IOPS |
4k-50rdpct-80randompct | 486.78 МБ/с | 124615.40 |
8k-75rdpct-80randompct | 941.52 МБ/с | 120514.50 |
64k-75rdpct-80randompct | 3445.29 МБ/с | 55124.70 |
4k-0rdpct-100randompct | 495.13 МБ/с | 126752.90 |
4k-100rdpct-100randompct | 483.9 МБ/с | 123877.10 |
2.2 LVM
lvcreate -i6 -I64 --type striped -l 100%VG -n nvme_stripe nvme
LVM - iSER | МБ/с | IOPS |
4k-50rdpct-80randompct | 514.27 МБ/с | 131652.90 |
8k-75rdpct-80randompct | 957.10 МБ/с | 122509.10 |
64k-75rdpct-80randompct | 3710.36 МБ/с | 59365.80 |
4k-0rdpct-100randompct | 535.9 МБ/с | 137192.80 |
4k-100rdpct-100randompct | 505.42 МБ/с | 129386.40 |
2.3 ZFS
v1 (without dedup)
zpool create -o ashift=12 -O compression=lz4 -O atime=off -O recordsize=128k nvme /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 /dev/nvme5n1 zfs create -s -V 10T -o volblocksize=16k -o compression=lz4 nvme/iser
ZFS - iSER | МБ/с | IOPS |
4k-50rdpct-80randompct | 131.77 МБ/с | 33734.00 |
8k-75rdpct-80randompct | 343.34 МБ/с | 43947.40 |
64k-75rdpct-80randompct | 1418.62 МБ/с | 22698.20 |
4k-0rdpct-100randompct | 80.81 МБ/с | 20690.60 |
4k-100rdpct-100randompct | 251.38 МБ/с | 64354.60 |
v2 (with dedup)
zpool create -o ashift=12 -O compression=lz4 -O atime=off -O dedup=on -O recordsize=128k nvme /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 /dev/nvme5n1 zfs create -s -V 10T -o volblocksize=16k -o compression=lz4 nvme/iser
ZFS - iSER | МБ/с | IOPS |
4k-50rdpct-80randompct | 56.75 МБ/с | 14525.60 |
8k-75rdpct-80randompct | 174.89 МБ/с | 22385.60 |
64k-75rdpct-80randompct | 384.76 МБ/с | 6156.20 |
4k-0rdpct-100randompct | 28.73 МБ/с | 7355.00 |
4k-100rdpct-100randompct | 200.54 МБ/с | 51337.80 |
3. NVMe-oF:
Со стороны Linux:
Помимо банальной установки SPDK (https://spdk.io/doc/getting_started.html), есть 1 нюанс. На момент написания статьи SPDK из мастера не работает с VMware по причине реализации проверки на параметр responder_resources == 0. Со стороны VMware этот параметр равен 1 (https://github.com/spdk/spdk/issues/3115). Поэтому необходимо собрать версию 23.05.x, поэтому процесс установки spdk будет начинаться не с - пофикшено в c8b9bba
git clone https://github.com/spdk/spdk --recursive
modprobe nvme-rdma
modprobe rdma_ucm
modprobe rdma_cm
scripts/setup.sh
screen - либо другая сессия, либо можно написать демона, который будет запускать его сам
build/bin/nvmf_tgt
ctrl+a d - отключение от сессии screen и возврат в консоль
scripts/rpc.py nvmf_create_transport -t RDMA -u 8192 -i 131072 -c 8192
scripts/rpc.py nvmf_create_subsystem nqn.2016-06.io.spdk:cnode1 -a -s SPDK00000000000001 -d SPDK_Controller
scripts/rpc.py bdev_aio_create /dev/md0 md0
scripts/rpc.py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 md0
scripts/rpc.py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t rdma -a 10.20.0.1 -s 4420
scripts/rpc.py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t rdma -a 10.20.0.5 -s 4420
Со стороны VMware:
esxcli system module parameters set -m nmlx4_core -p "enable_rocev2=1" (в противном случае будет ошибка "Underlying device does not support requested gid/RoCE type.")
Затем в веб создаётся VMware NVME over RDMA Storage Adapter, в controller задаётся IP адрес ВМ, указанный ранее, в поле порт - порт 4420
Производительность mdadm с тестами FIO из первой части на 1 ВМ выглядит следующим образом:
mdadm raid0 1ВМ | МБ/с | IOPS |
Последовательная запись 4M qd=32 | 4593.00 МБ/с | 1095.55 |
Последовательное чтение 4M qd=32 | 4618.00 МБ/с | 1101.67 |
Случайная запись 4k qd=128 jobs=16 | 542.00 МБ/с | 132417.04 |
Случайное чтение 4k qd=128 jobs=16 | 575.50 МБ/с | 140674.20 |
Случайная запись 4k qd=1 fsync=1 | 61.50 МБ/с | 15013.28 |
Случайное чтение 4k qd=1 fsync=1 | 30.35 МБ/с | 7418.52 |
Конечный график выглядит следующим образом:

3.1 MDADM
mdadm --create --verbose /dev/md0 --level=0 --raid-devices=6 /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 /dev/nvme5n1
mdadm - NVMe-oF | MB/s | IOPS |
4k-50rdpct-80randompct | 570.59 МБ/c | 146070.90 |
8k-75rdpct-80randompct | 1113.46 МБ/c | 142522.10 |
64k-75rdpct-80randompct | 5775.06 МБ/c | 92401.00 |
4k-0rdpct-100randompct | 593.87 МБ/c | 152033.00 |
4k-100rdpct-100randompct | 540.54 МБ/c | 138378.60 |
3.2 LVM
lvcreate -i6 -I64 --type stripe -l 100%VG -n lvm_stripe stripe
LVM - NVMe-oF | MB/s | IOPS |
4k-50rdpct-80randompct | 596.39 МБ/с | 152675.70 |
8k-75rdpct-80randompct | 1160.72 МБ/с | 148572.30 |
64k-75rdpct-80randompct | 5826.39 МБ/с | 93222.20 |
4k-0rdpct-100randompct | 618.22 МБ/с | 158267.10 |
4k-100rdpct-100randompct | 559.45 МБ/с | 143219.80 |
3.3 ZFS
v1 (without dedup)
zpool create -o ashift=12 -O compression=lz4 -O atime=off -O recordsize=128k nvme /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 /dev/nvme5n1 zfs create -s -V 10T -o volblocksize=16k -o compression=lz4 nvme/iser
NVMe-oF ZFS | MB/s | IOPS |
4k-50rdpct-80randompct | 131.18 МБ/с | 33585.30 |
8k-75rdpct-80randompct | 344.21 МБ/с | 44057.10 |
64k-75rdpct-80randompct | 1409.13 МБ/с | 22546.10 |
4k-0rdpct-100randompct | 78.63 МБ/с | 20129.20 |
4k-100rdpct-100randompct | 267.21 МБ/с | 68406.10 |
v2 (with dedup)
zpool create -o ashift=12 -O compression=lz4 -O atime=off -O dedup=on -O recordsize=128k nvme /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 /dev/nvme5n1 zfs create -s -V 10T -o volblocksize=16k -o compression=lz4 nvme/iser
NVMe-oF ZFS (dedup) | MB/s | IOPS |
4k-50rdpct-80randompct | 56.1 МБ/с | 14362.50 |
8k-75rdpct-80randompct | 183.32 МБ/с | 23464.70 |
64k-75rdpct-80randompct | 355.83 МБ/с | 5693.00 |
4k-0rdpct-100randompct | 28.07 МБ/с | 7185.10 |
4k-100rdpct-100randompct | 211.7 МБ/с | 54195.40 |
4. Вывод
LVM показывает самые высокие результаты, поэтому если брать его за 100%, то результаты тестов будут выглядеть следующим образом:
iSER | LVM | mdadm | ZFS | ZFS dedup |
4k-50rdpct-80randompct | 100.00% | 94.65% | 25.62% | 11.04% |
8k-75rdpct-80randompct | 100.00% | 98.37% | 35.87% | 18.27% |
64k-75rdpct-80randompct | 100.00% | 92.86% | 38.23% | 10.37% |
4k-0rdpct-100randompct | 100.00% | 92.39% | 15.08% | 5.36% |
4k-100rdpct-100randompct | 100.00% | 95.74% | 49.74% | 39.68% |
NVMe-oF | LVM | mdadm | ZFS | ZFS dedup |
4k-50rdpct-80randompct | 100.00% | 95.67% | 22.00% | 9.41% |
8k-75rdpct-80randompct | 100.00% | 95.93% | 29.65% | 15.79% |
64k-75rdpct-80randompct | 100.00% | 99.12% | 24.19% | 6.11% |
4k-0rdpct-100randompct | 100.00% | 96.06% | 12.72% | 4.54% |
4k-100rdpct-100randompct | 100.00% | 96.62% | 47.76% | 37.84% |
ZFS как и ожидалось демонстрирует не самые высокие результаты, но это, в том числе, связано с нагрузкой по CPU, но и в целом на это влияет тот факт, что ZFS не приспособлен для быстрой работы с NVMe.
Все результаты тестов доступны тут и таблица excel тут (да, все таблицы в архиве, так как гугл таблицы ломают формулы).
График всех тестов с группировкой по используемому протоколу подключения выглядит следующим образом (график дублируется из пункт 2 и 3)


График всех тестов с группировкой по используемому софт рейду





P.S. Если Вы считаете, что эти тесты неполные, в них что-то упущено или они некорректны - я открыт к любым предложениям по их дополнению.