[UPD]Взрослеем с GlusterFS

Всем привет.

Компания в которой я работаю довольно динамично развивается, соответвенно и растет количество серверов, пользователей. Вопросы отказоустойчивости становятся все более актуальными, чем ранее.
Исторически сложилось, что некоторые данные лежат в файлах и подключены клиентами к бекендам по NFS. Однако не хотелось, что бы центральный сервер был точкой отказа.
Rsync-варианты отмели сразу. После изучения вопроса и опыта других людей, а также некоторых тестов s3fs, которая к слову была кандидатом №1 на распределенное хранилище, была выбрана GlusterFS.

Не вдаваясь в подробности, которые вы к слову можете найти по ссылкам Основной сайт, Комьюнити скажу, что для наших целей такое хранилище вполне подходило. Главной особенностью GlusterFS является то, что клиент пишет на любой доступный в данное время мастер, и делает репликацию на недоступный после того как он вернулся в строй.

Итак приступим к настройке. Оговорюсь, что одновременно работал и старый NFS на серверах, они вполне уживаются на одной машине. Нам это было нужно на время перехода с NFS.

Устанавливаем сервер:
aptitude install glusterfs-server


Описываем конфиг(/etc/glusterfs/glusterfsd.vol):
volume posix
    type storage/posix
    option directory /mnt/Files
   end-volume

   volume locks
    type features/locks
    subvolumes posix
   end-volume

   volume Files
    type performance/io-threads
    option thread-count 8
    subvolumes locks
   end-volume

   volume server
    type protocol/server
    option transport-type tcp
        option auth.login.Files.allow user # Будем подключаться по связке login+password
        option auth.login.user.password secret_pass
    subvolumes Files
   end-volume

Дублируем пакет glusterfs-server и конфиг(/etc/glusterfs/glusterfsd.vol) на втором сервере.

Устнавливаем клиент:
aptitude install glusterfs-client


Описываем конфиг для клиента(/etc/glusterfs/glusterfs.vol):
volume server1.com
type protocol/client
    option transport-type tcp
    option username user
    option password secret_pass
    option remote-host 10.132.259.159 # server1.com
    option remote-subvolume Files
   end-volume

   volume server2.com
    type protocol/client
    option transport-type tcp
    option username user
    option password secret_pass
    option remote-host 10.184.179.175 # server2.com
    option remote-subvolume Files
   end-volume

   volume replicate
    type cluster/replicate
    subvolumes server1.com server2.com
   end-volume

   volume writebehind
    type performance/write-behind
    option cache-size 1MB
    subvolumes replicate
   end-volume

   volume cache
    type performance/io-cache
    option cache-size 512MB
    subvolumes writebehind
   end-volume
 


Загружаем модуль fuse
modprobe fuse


пробуем монтировать ФС
/usr/sbin/glusterfs -f /etc/glusterfs/glusterfs.vol /mnt/Files

df -h

/etc/glusterfs/glusterfs.vol 199G  120G   70G  64% /mnt/Files


Теперь о небольших граблях. Gluster-FS не монтируется при ребуте через fstab, т.к. модуль fuse не загружается автоматически. Можно пересобрать ядро, но мы поступим проще.
Добавляем в конец /etc/initramfs-tools/modules:

fuse


Выполняем:
update-initramfs -u -k `uname -r`


Добавляем в /etc/fstab:
/etc/glusterfs/glusterfs.vol  /mnt/Files  glusterfs  defaults  0  0


Ребут и профит.

Ну, предвидя вопросы о тестах, приведу парочку показательных, Gluster-fs vs NFS vs POHMELFS. Файл весом ~700Мб.

GlusterFS:
root@domU-12-41-56-0F-34-81:~# time cat /mnt/Files/ubuntu-11.10-desktop-amd64+mac.iso > /dev/null

real    0m28.101s
user    0m0.000s
sys     0m4.700s
root@domU-12-41-56-0F-34-81:~# time cat /mnt/Files/ubuntu-11.10-desktop-amd64+mac.iso > /dev/null

real    0m20.321s
user    0m0.000s
sys     0m2.030s
root@domU-12-41-56-0F-34-81:~# time cat /mnt/Files/ubuntu-11.10-desktop-amd64+mac.iso > /dev/null

real    0m36.444s
user    0m0.000s
sys     0m1.410s


POHMELFS(Взято отсюда POHMELFS: NFS по-новому):
stolen@stolen ~/soft/pohmelfs-server.git $ time cat /mnt/pohmel/share/GRTMPVOL_RU_20.10.08.iso >/dev/null

real 1m37.150s
user 0m0.010s
sys 0m1.270s

stolen@stolen ~/soft/pohmelfs-server.git $ time cat /mnt/pohmel/share/GRTMPVOL_RU_20.10.08.iso >/dev/null

real 0m0.591s
user 0m0.003s
sys 0m0.257s

stolen@stolen ~/soft/pohmelfs-server.git $ time cat /mnt/upload/share/GRTMPVOL_RU_20.10.08.iso >/dev/null

real 1m3.719s
user 0m0.003s
sys 0m0.400s


NFS:
root@domU-12-41-56-0F-34-81:run$ time cat /mnt/Files/ubuntu-11.10-desktop-amd64+mac.iso > /dev/null

real    0m15.220s
user    0m0.008s
sys     0m0.423s

root@domU-12-41-56-0F-34-81:run$ time cat /mnt/Files/ubuntu-11.10-desktop-amd64+mac.iso > /dev/null

real    0m16.139s
user    0m0.005s
sys     0m0.160s

root@domU-12-41-56-0F-34-81:run$ time cat /mnt/Files/ubuntu-11.10-desktop-amd64+mac.iso > /dev/null

real    0m18.812s
user    0m0.006s
sys     0m0.177s


Тесты GlusteFS vs NFS на мелких файлах.
Для этих целей набросал скрипт, который генерит 700 файлов и забивает их небольшим контентом:
#!/bin/bash
count=0
while [ $count -lt 700 ]
do
  touch small_files/$count.txt
  openssl rand -base64 $[$count*42] > /root/small_files/$count.txt
  count=$[$count+1]
done


GlusterFS, копирование:
root@domU-12-31-36-0F-71-81:~# time cp /root/small_files/* /mnt/Files/test_small/

real    0m28.318s
user    0m0.010s
sys     0m0.160s
root@domU-12-31-36-0F-71-81:~# time cp /root/small_files/* /mnt/Files/test_small/

real    0m27.432s
user    0m0.000s
sys     0m0.170s
root@domU-12-31-36-0F-71-81:~# time cp /root/small_files/* /mnt/Files/test_small/

real    0m29.397s
user    0m0.010s
sys     0m0.150s

NFS, копирование:
root@domU-12-41-39-01-D1-71:~# time cp /root/small_files/* /mnt/Files/test_small/

real    0m15.848s
user    0m0.008s
sys     0m0.061s
root@domU-12-41-39-01-D1-71:~# time cp /root/small_files/* /mnt/Files/test_small/

real    0m12.792s
user    0m0.002s
sys     0m0.070s
root@domU-12-41-39-01-D1-71:~# time cp /root/small_files/* /mnt/Files/test_small/

real    0m13.417s
user    0m0.006s
sys     0m0.049s



GlusterFS, удаление:
root@domU-12-31-36-0F-71-81:~# time rm /mnt/Files/test_small/*

real    0m5.050s
user    0m0.060s
sys     0m0.000s
root@domU-12-31-36-0F-71-81:~# time rm /mnt/Files/test_small/*

real    0m7.055s
user    0m0.000s
sys     0m0.060s
root@domU-12-31-36-0F-71-81:~# time rm /mnt/Files/test_small/*

real    0m5.300s
user    0m0.040s
sys     0m0.020s

NFS, удаление:
root@domU-12-41-39-01-D1-71:~# time rm /mnt/Files/test_small/*

real    0m4.861s
user    0m0.003s
sys     0m0.013s
root@domU-12-41-39-01-D1-71:~# time rm /mnt/Files/test_small/*

real    0m3.618s
user    0m0.002s
sys     0m0.007s
root@domU-12-41-39-01-D1-71:~# time rm /mnt/Files/test_small/*

real    0m4.297s
user    0m0.003s
sys     0m0.024s


UPD: Добавил тесты на мелких файлах для NFS и GlusterFS.
Share post

Comments 27

    0
    Краш-тесты проводили? Что происходит если один из серваков «уронить»?
      +3
      Если один мастеров недоступен, клиент пишет на тот который онлайн. После того как «упавший» мастер возвращается в строй, любое действие на клиенте, например ls -la в том каталоге, который рассинхронизирован заставит клиента синхронизировать недостающие данные на оживший мастер.
        0
        А если в рассинхронизированном каталоге никаких действий не делается, будет ли запущена когда нибудь синхронизация?

        И не пробовали ли создавать не 700 мелких файлов, а скажем несколько миллионов?
          0
          Насколько я знаю, самостоятельно не будет запущена.

          У нас лежит на мастерах как раз ~1,5-2 миллиона файлов, но одновременно такое количество никто не читает и не создает, поэтому не проводил таких тестов.
          0
          А дёргали кабель во время записи?
          Помучал glusterfs 3.2.6 и пришёл к выводу — не отказустойчивая…
          2(и 4) пира glusterd:
          cat /usr/local/glusterfs/glusterd.vol
          volume management
          type mgmt/glusterd
          option working-directory /etc/glusterd
          option transport-type socket,rdma
          option transport.socket.keepalive-time 10
          option transport.socket.keepalive-interval 3
          end-volume


          volume сконфигурировал через cli gluster:
          gluster volume create testvol replica 4 transport tcp mcg000:/exp0 mcg001:/exp1 mcg002:/exp2 mcg003:/exp3
          gluster volume set testvol auth.allow 192.168.56.*
          gluster volume set testvol allow-insecure on
          gluster volume set testvol network.ping-timeout 1
          gluster volume start testvol


          Один клиент-glusterfs, пишу в файлы
          for i in {0..1000000}; do echo $i >> glusterfsmntpoint/file1.txt
          for i in {0..1000000}; do echo $i >> glusterfsmntpoint/file2.txt


          Дёргаю кабель жду таймаут — втыкаю, один файл пишется, другой висит на io, или оба висят.
          Перезапускаю peer который висит (/etc/init.d/glusterd restart) начинает формироваться второй файл.
          Такая ситуация повторяется и с 4 пирами

          Другая ситуация, ничего не дёргаю, просто перезапускаю один из пиров в то время как клиент продолжает писать — в результате split-brain на одном файле или на обоих или трёх ну т.п.

          Как-бы совсем не отказустойчиво это…

          инфа о volume которая отдаётся клиентам при подключении к кластеру:
          Given volfile:
          +------------------------------------------------------------------------------+
          1: volume testvol-client-0
          2: type protocol/client
          3: option remote-host mcg000
          4: option remote-subvolume /exp0
          5: option transport-type tcp
          6: option ping-timeout 1
          7: end-volume
          8:
          9: volume testvol-client-1
          10: type protocol/client
          11: option remote-host mcg001
          12: option remote-subvolume /exp1
          13: option transport-type tcp
          14: option ping-timeout 1
          15: end-volume
          16:
          17: volume testvol-client-2
          18: type protocol/client
          19: option remote-host mcg002
          20: option remote-subvolume /exp2
          21: option transport-type tcp
          22: option ping-timeout 1
          23: end-volume
          24:
          25: volume testvol-client-3
          26: type protocol/client
          27: option remote-host mcg003
          28: option remote-subvolume /exp3
          29: option transport-type tcp
          30: option ping-timeout 1
          31: end-volume
          32:
          33: volume testvol-replicate-0
          34: type cluster/replicate
          35: subvolumes testvol-client-0 testvol-client-1 testvol-client-2 testvol-client-3
          36: end-volume
          37:
          38: volume testvol-write-behind
          39: type performance/write-behind
          40: subvolumes testvol-replicate-0
          41: end-volume
          42:
          43: volume testvol-read-ahead
          44: type performance/read-ahead
          45: subvolumes testvol-write-behind
          46: end-volume
          47:
          48: volume testvol-io-cache
          49: type performance/io-cache
          50: subvolumes testvol-read-ahead
          51: end-volume
          52:
          53: volume testvol-quick-read
          54: type performance/quick-read
          55: subvolumes testvol-io-cache
          56: end-volume
          57:
          58: volume testvol-stat-prefetch
          59: type performance/stat-prefetch
          60: subvolumes testvol-quick-read
          61: end-volume
          62:
          63: volume testvol
          64: type debug/io-stats
          65: option latency-measurement off
          66: option count-fop-hits off
          67: subvolumes testvol-stat-prefetch
          68: end-volume


            0
            for i in {0..1000000}; do echo $i >> glusterfsmntpoint/file1.txt
            for i in {0..1000000}; do echo $i >> glusterfsmntpoint/file2.txt

            for i in {0..1000000}; do echo $i >> glusterfsmntpoint/file1.txt; done
            for i in {0..1000000}; do echo $i >> glusterfsmntpoint/file2.txt; done
              0
              gluster volume create testvol replica 4 transport tcp mcg000:/exp0 mcg001:/exp1 mcg002:/exp2 mcg003:/exp3

              В документации сказано, что создание реплики >2 еще стабильностью не отличается.
              Источник: access.redhat.com/site/documentation/en-US/Red_Hat_Storage/2.0/html/Administration_Guide/sect-User_Guide-Setting_Volumes-Replicated.html
              0
              Предположим ситуация. Есть две мастер ноды. Одна ушла в даун. Пока она была в дауне на ноду 2 что-то записали. Нода1 поднялась, но к этим данным обращений небыло, по этому они обратно не реплицировались. Что означает, что часть данных не продублирована и в случае потери ноды2 мы эти данные навсегда теряем. Так?
              +3
              Хочу добавить от себя, использовать GlusterFS можно только когда все ее ноды связаны напрямую быстрым каналом, в идеале в одной стойке. Мы же использовали GlusterFS для failover'a, при этом сервера находились в разных датацентрах(все было в ДЦах softlayer'a, на серверах был 1 Gb/s, пинг между нодами ~ 30 ms).

              Это привело к проблемам, которые отняли много времени и нервов. Все системные вызовы к ФС на клиентах с GlusterFS жутко тормозили. Оказывается, она добавляет какие-то свои обработчики к syscall'ам ( open, fread, etc ), причем не обязательно было обращаться к директории на которую смонтирована GlusterFS, проблема проявлялась даже при обращении к локальной ФС.

              Оставляю это здесь, возможно кому-нибудь это поможет.
                0
                У GlusterFS есть нативный протокол через Fibre Channel. Это самый быстрый вариант.

                Через TCP/IP для веб-приложений рекомендуют NFS-клиента, вместо нативного, но выигрыш небольшой. Скажем, 5%.
                  0
                  А на какое решение перешли для failover?
                    +1
                    В данный момент решили проблему в лоб. Копируем нужные файлы на локальную файловую систему, а шарим их с помощью NFS. Забыл сказать, что у GlusterFS есть еще GEO-репликация, которая решает проблему распределенных нод в разных ДЦ, но она нам не подходит, потому что файлы в нашей системе должны быть доступны для всех клиентов сразу, после завершения их записи на распределенную ФС.
                  +1
                  Тесты не корректны, у GlusterFS 3 вида хранилищ + 2 гибридных. У каждого хранилища свои преимущества и недостатки при работе с малыми/большими файлами.
                    +1
                    Тесты не призваны были покрыть все варианты использования GlusterFS. Я привел лишь для своей конфигурации. То, что не провел тестов на мелких, мой промах.
                      0
                      *мелких файлах
                        0
                        Добавил тесты на мелких файлах для NFS и GlusterFS.
                    0
                    Есть ли какие-либо данные по степени избыточности GlusterFS? Т.е., к примеру, каким полезным объемом будет обладать файловая система, в случае если она состоит из 10 серверов, каждый из которых выделяет под нее 1 ТБ?
                      0
                      От 1 до 10тб. Смотря как настроите репликацию.
                        0
                        Избыточность настраивается. Вы можете делать 5 копий на 10 серверов, или 10 копий на 10 серверов. Только не забудьте, что GlusterFS пишет данные синхронно. Т.е. write на клиенте не возвратится до тех пор, пока все 10 серверов не возвратят write.

                        Есть т.н. geo-replication, которая асинхронная, но у неё свои ограничения.

                          0
                          А сколько при этом занимают метаданные? в случае 10 копий на мой взгляд было бы делать каскадные обновления, т.е. write на клиент возвращается при успешной записи первых двух серверов, но после этого «догоняются» данные до оставшихся 8. Еще интересно какой процент от данных занимают метаданные.
                            0
                            Метаданные? Нет никаких особых метаданных. Сервера вообще-то довольно тупые. Есть кеш записи, кеш чтения, read-ahead кеш (емнип). Всё настраивается, короче.
                        0
                        Вы сравнивали со старым POHMELFS. Мы тут уже активно тестим новый, который использует Elliptics в качестве стораджа, там всё намного вкуснее, читает-пишет со скоростью диска на сторадже. Асинхронная запись, довольно агрессивное использование page-cache, автоматическое определение умерших реплик и переподключение к ним… В общем, ждите скоро в новых ядрышках :)

                        Хотя Евгений тут вот из угла вещает, что результаты низковаты даже для старого POHMELFS, должно было быть быстрее NFS.
                          0
                          С удовольствием посмотрю на новые версии «Похмела». Единственное, что самостоятельно не хватит времени поднять и потестить сейчас. Так, что пока оставлю заочно эту роль за кем нибудь:)
                            0
                            Вообще Elliptics надо как то более активно развиватся, eblob.ru хороший сайт но малоинформативен.
                            Ставить опоты самому нету времени и сил, а в продакшен что то подное ой как надо.
                            0
                            Эх, про ceph бы подобную статью :)
                              –3
                              «Gluster-FS не монтируется при ребуте через fstab, т.к. модуль fuse не загружается автоматически. Можно пересобрать ядро, но мы поступим проще.»
                              Хм......, а ведь можно ещё проще:

                              root@debian:~# echo "fuse" >> /etc/modules

                              после ребута:
                              root@debian:~# lsmod | grep fuse
                              fuse 44316 0
                              root@debian:~#


                                +1
                                Отказался от гластера более полутора лет назад, когда его еще не купил редхат. Он не мог определить толком на каком из нодов местс полно, а на каком нет, и показывая что места полно выдавал при попытке записи что его нет, упираясь в занятый нод. Вполне возможно что индусы допилили уже. Nfs у него был битый и падучий. когда я об этом добавил в описание в википедию индусы стали стирать инфу. Впечатлений много и все отрицательные.

                                Only users with full accounts can post comments. Log in, please.