GlusterFS, NFS — заметки о скорости и крохотном хранилище
В нашем проекте есть немного (~500GB) статических файлов, которые раздаются через nginx. Лежат они на одном физическом сервере и подключены по NFS к серверу, на котором запущен nginx. Скорость сети между серверами 1GBit/s. И вот мы задумались о том, чтобы как-то обезопасить проект от «потери» сервера, хранящего статические файлы. Сразу отметём вопросы выбора типа хранилища, просто примем тот факт, что мы выбрали GlusterFS, а вот почему и как, вы узнаете в статье.
У нас было только одно требование к GlusterFS — скорость должна быть не сильно ниже текущего NFS, ведь почти в каждой статье пишут, что как раз скорость у GlusterFS хромает.
Общие положения
- Для тестирования скорости и «игр» с GlusterFS разворачивались виртуалки (CPU — 1, RAM — 1GB, Disk — 10GB) в облаке openstack у одного из провайдеров. Сеть между виртуалками 1GBit/s.
- В качестве серверов GlusterFS используется Ubuntu 22.04 и ее пакеты glusterfs-server, nfs-ganesha-gluster из стандартного репозитория. Хоть мы и стараемся использовать на серверах RedHat base дистрибутивы (Centos, AlmaLinux), но как ни странно, нормально установить GlusterFS на AlmaLinux8 и AlmaLinux9 не вышло. Если будет интересно почему, то могу написать в комментариях.
- Скорость измерялась с помощью скрипта. Да, тупо записывали на диск/nfs-папку/glusterfs-том 1GB блоками по 1MB. Потом сравнивали показатели. Ведь все познается в сравнении, не правда ли?
#!/usr/bin/env perl $s = 0; for ($i = 1; $i &1; sync`; $rv =~ /\s+(\d+)\.?\d?\s+MB\/s/; $s += $1; print $rv; > printf("speed = %0.0f\n", $s/3);
Самое замечательное в GlusterFS это то, что она очень гибкая в конфигурировании томов, которые могут плавно переходить от Distribute к Replicate и затем к Distributed‑Replicate. Да, кстати, читатель этой статьи должен знать термины GlusterFS, ну или желательно, чтобы знал, ну или не желательно, в общем, как хотите, но в статье будут встречаться термины GlusterFS без особых объяснений.
Скоростные испытания
srv1, srv2 — виртуалки в роли сервера, client — виртуалка в роли клиента, eth0 на srv1 замерялась через vnstat в момент теста скорости.
На srv1 замеряем скорость локального диска.
На srv1 запускаем обычный NFS сервер и расшариваем папку /mnt/nfs *(rw,sync,no_subtree_check,no_root_squash,no_all_squash)
На client монтируем расшаренную nfs-папку через mount -t nfs4 srv1: и замеряем скорость.
eth0 на srv1 показывает rx: 940.61 Mbit/s tx: 7.95 Mbit/s
На srv1 выключаем обычный NFS сервер, создаем GlusterFS том (далее glusterfs-том) gv0 из одного кирпичика на srv1. Тип glusterfs-тома получится Distribute. Затем расшариваем glusterfs-том gv0 через nfs-ganesha.
далее тип glusterfs-тома Distribute
На srv1 монтируем gv0 том через mount -t glusterfs localhost: и замеряем скорость.
eth0 на srv1 показывает rx: 1.94 kbit/s tx: 3.00 kbit/s
На client монтируем gv0 том через mount -t glusterfs srv1: и замеряем скорость.
eth0 на srv1 показывает rx: 961.47 Mbit/s tx: 6.45 Mbit/s
На client монтируем gv0 том через mount -t nfs4 srv1: и замеряем скорость.
eth0 на srv1 показывает rx: 921.94 Mbit/s tx: 2.67 Mbit/s
К glusterfs-тому gv0 подключаем srv2 с фактором репликации 2, тип которого становится Replicate.
далее тип glusterfs-тома Replicate
На srv1 монтируем gv0 том через mount -t glusterfs localhost: и замеряем скорость.
eth0 на srv1 показывает rx: 4.57 Mbit/s tx: 968.52 Mbit/s
На client монтируем gv0 том через mount -t glusterfs srv1: и замеряем скорость.
eth0 на srv1 показывает rx: 422.84 Mbit/s tx: 2.44 Mbit/s
На client монтируем gv0 том через mount -t nfs4 srv1: и замеряем скорость.
eth0 на srv1 показывает rx: 604.81 Mbit/s tx: 682.26 Mbit/s
Выводы по испытаниям
- Удивляет то, что у glusterfs-тома с типом Distribute скорость записи по всем случаям монтирования чуток выше, чем у локального диска и обычного nfs соответсвенно. Замеры делались несколько раз и каждый раз наблюдалась такая картина. Казалось бы, должно быть наоборот. Главный вывод из этого такой: на одном сервере смело можно использовать glusterfs-том типа Distribute, не теряя в скорости. Только вот зачем, спросите вы. Ну хотя бы для того, чтобы изначально заложить вариант расширения хранилища.
- Когда glusterfs-том трансформируется в тип Replicate, скорость начинает падать. Что вполне очевидно, т.к. файлы начинают зеркалироваться на двух серверах (как raid1 у mdadm). Падение происходит по разному у разных типов монтирования, что тоже вполне очевидно, если посмотреть на показатели загруженности eth0 на srv1. При монтировании через mount-t glusterfs скорость упала до 54 (в два раза), при этом eth0 на srv1 загружен лишь на половину, т.к. вторая половина трафика ушла на srv2, т.е. client в момент записи пишет сразу на два сервера и eth0 у client при этом загружен на 100%. При монтировании через mount-t nfs4 скорость упала до 84, при этом eth0 на srv1 загружен на 100%, но трафик уже идет в обоих направлениях. т.к. srv1, получая байты от client, вынужден отправлять их на srv2.
- Теоретически можно предположить, что если на client сделать две сетевухи и объединить (bonding) их в одну, то при монтировании через mount-t glusterfs скорость должна возрасти в два раза, т.е. до 108, что полностью соответствует обычному NFS.
Исходя из вышесказанного, мы решили поэтапно перенести наше хранилище статических файлов с одного сервера на другой с glusterfs-томом типа Distribute с последующим добавлением второго сервера и преобразованием glusterfs-тома в Replicate. Да, скорости в 84 для нашего типа нагрузки вполне хватает. Ну и поскольку в итоге планируется два сервера, то желательно разнести их по разным зонам доступности. Схема получилась вот такой.
+ --- nfs endpoint / +------/-------+ | / | | +--------+ | | | srv1 | | | | 900G | | availability | +--------+ | zone 1 | | ===|==============|============== | | | +--------+ | availability | | srv2 | | zone 2 | | 900G | | | +--------+ | | | | Replicated | | volume 900G | +--------------+
Для того чтобы можно было «потерять» один из серверов в такой схеме и продолжить нормально работать, нужно выполнить два условия: точка монтирования nfs должна быть только на одном из серверов; glusterfs-том нужно потюнить вот так:
gluster volume set gv0 network.ping-timeout 5 gluster volume set gv0 cluster.quorum-type fixed gluster volume set gv0 cluster.quorum-count 1
Подводя общие итоги, хочется сказать
Скорость GlusterFS нифига не медленная, а очень сильно зависит от «толщины» сети и типа тома. Например, сама GlusterFS рекомендует использовать фактор репликации равный 3, но тогда скорость записи упадет не в два раза, а в три, т.к. клиент будет одновременно писать на три сервера вместо двух. И следовательно, чем выше нужна скорость, тем «толще» надо делать сеть. А вот как делать сеть «толще», надо думать — либо ставить 10GBit/s сетевухи, либо пытаться объединять сетевухи. Все очень сильно зависит от требований и финансовых возможностей проекта.
Схема из двух серверов и с монтированием glusterfs-тома по nfs вполне работоспособна. Скорость, конечно, падает по сравнению с обычным nfs, но не в два раза, как с монтированием по glusterfs. Это куда лучше, чем использовать rsync и прочее для возможности «потери» сервера.
Немного фантазий, проверенных на практике
Если нам перестанет хватать места, то можно легко добавить еще пару серверов srv3 и srv4 (добавлять нужно парами), и тогда тип glusterfs-тома станет Distributed-Replicate, а схема будет уже такой:
+-----------------------------------------+ | | | +- vip for nfs -+ | | / \ | | / \ | | +------/-------+ +-------\------+ | | | / | | \ | | | | +--------+ | | +--------+ | | | | | srv1 | | | | srv3 | | | | | | 900G | | | | 900G | | | availability | | +--------+ | | +--------+ | | zone 1 | | | | | | ===|==|==============|=====|==============|==|============== | | | | | | | | +--------+ | | +--------+ | | availability | | | srv2 | | | | srv4 | | | zone 2 | | | 900G | | | | 900G | | | | | +--------+ | | +--------+ | | | | | | | | | | Replicated | | Replicated | | | | volume 900G | | volume 900G | | | +--------------+ +--------------+ | | | | Distributed volume 1800G | +-----------------------------------------+
При такой схеме файлы будут распределяться по имени на разные пары серверов. Например, файл с именем speed_test_11.img попадет на сервера srv1 и srv2, а файл с именем speed_test_22.img попадет на сервера srv3 и srv4. Дальше представим, что client монтирует glusterfs-том через mount-t nfs4 , подлючаясь к srv1. В таком случае, если тест скорости будет делаться на файле speed_test_11.img, то скорость будет 84, ну а если на файле speed_test_22.img, то скорость будет 54 (как у монтирования через mount-t glusterfs ), т.к. в этом случае уже сам srv1 будет вынужден по сети отправлять файл на два сервера — на srv3 и srv4. Т.е. надо будет думать над тем, как и где увелиичить «толщину» сети.
«Низкая» скорость при записи по nfs
Дано. Есть два ноды ESX 5.1 объединенных по гигабиту, на одной поднята виртуалка с client, на второй подняты две виртуалки nfsserver, smbserver, причем последние сидят на одном и том же физическом диске.
Везде используется CentOS 6.7
На nfsserver экспортирована директория
/opt/backups/vm001 cl.i.e.nt(rw,sync,no_wdelay,all_squash,anonuid=500,anongid=502)
На client директория монтируется с опциями по умолчанию
# cat /etc/fstab nfs.ser.v.er:/opt/backups/vm001 /opt/backups nfs4 defaults 0 0 # cat /proc/mounts nfs.ser.v.er:/opt/backups/vm001 /opt/backups nfs4 rw,relatime,vers=4,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=cl.i.e.nt,minorversion=0,local_lock=none,addr=nfs.ser.v.er 0 0
Заходим на nfsserver запускаем тест локальной записи pv /dev/zero >zerofile.bin видим цифры порядка 2,42GB 0:00:23 [99,6MB/s] , что так же подтверждается в показаниях atop
Заходим на client в смонтированную директорию запускаем тест nfs чтения pv some_file_from_nfs >/dev/null видим цифры порядка 1,9GB 0:00:06 [52,8MB/s] , что так же подтверждается в показаниях atop на nfsserver
Теперь выполняем тест записи на nfs с client pv /dev/zero >zerofile.bin видим во первых стандартную «пилу» когда скорость заипись постоянно прыгает от нормальных цифр до килобайт 1,37GB 0:00:26 [2,19MB/s] , а во вторых atop на nfsserver показывает что запись идет в коридоре 13MB/s — 17MB/s, выше 18MB/s практически не поднимаясь.
Для доп. проверки цепляем на client директорию с smbserver и повторяем эксперимент. Получаем 1,45GB 0:00:18 [56,7MB/s] и анологичные показатели записи в atop.
Опцию no_wdelay, которую как правило применяю для сглаживания «пилы», отключал но результат не изменился.
Резонный вопрос где могла порытся собака и куда смотреть ?