После тестирования NVME over TCP, описанной тут https://habr.com/ru/companies/beeline_tech/articles/770174/, решили проверить, насколько хорошо iScsi в L3-сети работает по сравнение со специализированным решение на FC.

Настройки iScsi

TL/DR

  • Машина в Bios переведена на профиль HPC (был пустой).

  • На уровне OS и iscsid сделаны такие изменения

- name: Setup iScsi
  ini_file:
    dest:  /etc/iscsi/iscsid.conf
    no_extra_spaces: false
    option: "{{item.name}}"
    value: "{{item.value}}"
    backup: no
  loop:
     - { name: "node.session.iscsi.InitialR2T" , value: "Yes"  }
     - { name: "node.session.cmds_max" , value: "256"  }
     - { name: "node.session.queue_depth" , value: "256"  }
     - { name: "node.session.nr_sessions" , value: "8"  }

- name: Setup  /etc/sysctl.conf
  ansible.posix.sysctl:
    name: "{{item.key}}"
    value: "{{item.val}}"
  loop:
    - { key:  net.ipv4.fib_multipath_hash_policy, val: "1 #iscsi"}
    - { key:  net.ipv4.fib_multipath_use_neigh, val: "1  #iscsi"}
    - { key:  net.ipv4.tcp_slow_start_after_idle, val: "0  #iscsi"}

  • На стороне СХД разрешено одновременное подключение нескольких каналов на 8 портов

Достигнутые скорости в 12,3ГБ/c на 100Гб сети признаны хорошими.

Первоначальный тест

Взяли дамп продуктовой базы на определенный день, несколько часов трафика на ней.

На перспективной платформе с рекомендуемыми настройками multipathd от вендора СХД настроили подключение нескольких десятков LUN.
настройки iScsid использовались 'из коробки'

Перенесли данные на будущую платформу.

Запустили воспроизведение трафика.

На графиках увидели, что утилизация сети достигает только 50%.

Начали разбираться, почему так. И что стоит сделать для того, чтобы занять сетевой канал полностью.

Оптимизация на уровне устройств

По умолчанию в Oracle Linux включено объединение нескольких команд на чтение и запись в устройство в одну.
Это не очень подходило для некоторых устройств, поэтому для них пришлось выключить оптимизацию.

ls -l /dev/mapper/*my_mask* | awk -F "-> ../" '{print $2}' | while read dev; do echo "$dev" ;echo 2 > /sys/devices/virtual/block/$dev/queue/nomerges; cat /sys/devices/virtual/block/$dev/queue/nomerges ;done

Первоначальный анализ.

Средствами СУБД была запущена валидация таблиц, которая создавала нагрузку, которая упиралась в 50Гб/c и давала рекорды по потреблению электричества на сервере.

htop показывал большой процент ожидания в ядре.

Решили посмотреть на настройки iscsid.

Нашли в нем

################################
# session and device queue depth
################################

# To control how many commands the session will queue, set
# node.session.cmds_max to an integer between 2 and 2048 that is also
# a power of 2. The default is 128.
node.session.cmds_max = 128

# To control the device's queue depth, set node.session.queue_depth
# to a value between 1 and 1024. The default is 32.
node.session.queue_depth = 32

Поменяли глубину node.session.queue_depth на 256.

После чего рестартовали iscsid и повторили тест с валидацией таблиц.

Потребление процессора (и электричества) стало нормальным, скорость поднялась примерно до 75Гб/с.

Дальнейшие увеличения node.session.queue_depth влияния не оказывало, решили использовать синтетические тесты чтобы выяснить что нужно подкрутить. Конечной целью было загрузить сеть дисковыми операциями полностью.

Синтетические тесты

Синтетические тесты решено было производить с помощью FIO на машине такой же конфигурации по модели, процессору. памяти, сети в том же коммутаторе.

Для тестов там уже было 48 дисков с СХД, что чуть хуже чем на оригинальном стэнде с базой, но приемлемо.

Диски через multipath.conf получали имена, под которыми были видны в /dev/mapper

Простая строка в шелл, наподобие такой

cat 1.txt | grep " ->" | awk -F">" '{print $2}' | tr "." "_" |  awk '{print "\tmultipath {\n\t\twwid\t3"$3"\n\t\talias\t"$1"\n\t}"}'

Позволит быстро создать нужные строки для /etc/multipath.conf конфига.

'3' перед '$3', в котором wwid, это такая специфика протокола

This issue has been explained in the man page of scsi_id:

– scsi_id queries a SCSI device via the SCSI INQUIRY vital product data (VPD) page 0x80 or 0x83 and uses the resulting data to generate a value that is unique across all SCSI devices that properly support page 0x80 or page 0x83.
– If a result is generated it is sent to standard output, and the program exits with a zero value. If no identifier is output, the program exits with a non-zero value.
– scsi_id is primarily for use by other utilities such as udev that require a unique SCSI identifier.
– By default all devices are assumed blacklisted, the –whitelisted option must be specified on the command line or in the config file for any useful behavior.
– SCSI commands are sent directly to the device via the SG_IO ioctl interface.
– In order to generate unique values for either page 0x80 or page 0x83, the serial numbers or worldwide names are prefixed as follows.

Identifiers based on page 0x80 are prefixed by the character ‘S’, the SCSI vendor, the SCSI product (model) and then the the serial number returned by page 0x80. For example:

# /lib/udev/scsi_id --page=0x80 --whitelisted --device=/dev/sda
SIBM 3542 1T05078453


Identifiers based on page 0x83 are prefixed by the identifier type followed by the page 0x83 identifier. For example, a device with a NAA (Name Address Authority) type of 3 (also in this case the page 0x83 identifier starts with the NAA value of 6):

Собрать небольшой томик из 48 кусочков для тестов можно так

ls -1 /dev/mapper/*testdata* | grep exp | xargs vgcreate vg_testdata
lvcreate -i 4 -I 64 -n testdata -l 100%FREE vg_testdata

Для наших тестов мы использовали полоски на диске в 256k, соответственно -I 256

Если же вам не надо собирать LVM, а нужно просто передать партиции, занимающие 100% диска, под управление СУБД, то можно для них сделать такое udev правило.

ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="prefix*", ENV{DM_NAME}=="*p1", ENV{DM_NAME}=="*pattern*p1", OWNER="rdbmuser", GROUP="rdbmgroup", MODE="0660", SYMLINK+="prefix_disk/pattern_$env{DM_NAME}"

Сами тесты

Собрав стэнд начали запускать FIO, получая достаточно стабильные цифры, в параллельном терминале запуская sar -n DEV 3, наблюдая распределение трафика по адаптерам, реакцию на опускание одного из 4х, 2х из 4х, возврат адаптеров.

Распределение было неравномерным.
У нас 2 двухпортовых карточки, второй порт на каждой был недозагружен.

Возникла идея проверить настройки электропотребления в BIOS. Там не был выбран никакой профиль. Поставили HPC.

Скорость немного приподнялась.

Действуя в том же духе решили обновить прошивки сетевых карт на последнее стабильное FW. На скорость не повлияло.

Решили выяснить как MTU 9000 вместо 1500 влияет на скорость.
Распределение по адаптерам стало более ровным. Только изменением MTU мы получили 2% дополнительной утилизации канала. Поэтому решили оставить.

Поиграться с NUMA настройками на тестовом сервере не представлялось возможным.

 pwd;cat  en*np{0..1}/device/num*
/sys/class/net
-1
-1
-1
-1

Этот шаг настройки опустили.

Согласно рекомендациям производителя на СХД было сконфигурировано 4 порта. Умолчальные настройки iscsid строили по одному пути.

Стали играться с числом параллельных подключений до порта.

Для этого надо сбросить существующие настройки в /var/lib/iscsi/nodes, рестартовать iscsid, повторить регистрацию через посылку sendtargets. И залогиниться на СХД.

Особо баловаться с увеличением числа путей не стоит. Каждый путь создает блочное устройство. Их число не просто так 10 тысячами ограничено. И с некоторого момента начинается падение производительности.

Мы остановились на 8.

Получилось 4x8 пути до устройства. Трафик в таком случае стал идеально ровно размазываться по 4 сетевым картам и стремиться к 100Гб/c.

Для дальнейшего улучшения скорости мы разделили наши диски на несколько логических групп.

  1. Диски для файловых систем

  2. Диски для журналов БД

  3. Диски для данных БД.

Каждая группа дисков подавалась со своих 4 портов на СХД.

Наконец мы добились почти 100% загрузки сети.

Выводы

Проведя в изысканиях 2 полных первых майских рабочих недели (это 5 рабочих дней, но в неделях страшнее) получили настройки, которые показали себя в 5 раз лучше имеющейся инфраструктуры на FC.

  1. Кладем массив по IOPS мелким блоком на запись и чтение (1 млн запись и 1.5млн чтение)

  2. Почти кладем сеть по пропускной средним блоком (12.3Gb/s)

Запись

# fio  --rw=write --bs=4k --numjobs=136 --iodepth=256 --size=10T --ioengine=libaio --direct=1  -group_reporting --name=jour
nal-test --filename=/dev/mapper/vg_exp_data-exp_data
journal-test: (g=0): rw=write, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=256
...
fio-3.19
Starting 136 processes
^Cbs: 136 (f=136): [W(136)][0.0%][w=4575MiB/s][w=1171k IOPS][eta 04d:00h:33m:27s]
fio: terminating on signal 2

Чтение

# fio  --rw=read --bs=4k --numjobs=136 --iodepth=256 --size=10T --ioengine=libaio --direct=1  -group_reporting --name=journ
al-test --filename=/dev/mapper/vg_exp_data-exp_data
journal-test: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=256
...
fio-3.19
Starting 136 processes
^Cbs: 136 (f=136): [R(136)][0.0%][r=5731MiB/s][r=1467k IOPS][eta 02d:21h:33m:50s]

Бонус: Сравнение с NVME over TCP

Вдруг захотелось сравнить полученную производительность с NVME.

Настроил по инструкции из упомянутой вверху статьи.
Тесты само собой делал на 1 диске.
Первый же тест уперся в скорость этого единственного диска.

Поняв, что тест неправильный собрал LVM том из 4 NVME over TCP дисков на локальной машине. По идее 128 соединений до каждого.

Но с параметрами для теста, который выдавал 12,3ГБ/c по iScsi получил только 9ГБ/c

Заключение

Может быть мы делаем все неправильно. Если это так, то большая просьба в комментариях поделиться своими рецептами эффективной утилизации пропускных возможностей сети iScsi трафиком.

Комментарии (0)