cLVM, lvmlockd или как приручить СХД

Проблема

У вас есть много нод и общий на всех блочный сторадж(iSCSI, FC, SRP etc.). Вам нужно гибко управлять этим стораджем — создавать, удалять, ресайзить, снапшотить LUNы, при этом иметь возможность работать с любым LUN’ом на любой ноде. Типичный пример — группа хостов и множество ВМ на этих хостах к которым LUNы подключаются напрямую. Как известно, это единственный способ получить максимум производительности блочного хранилища.
Но, ваша СХД не имеет API либо делает все операции очень медленно, либо у вас нет програмистов способных реализовать управление этой СХД. Другая причина, наличие нескольких СХД и желание работать с ними одинаково.

Альтернативное управление СХД.

LVM, точнее одна из реализаций cLVM(Cluster LVM) на ваш выбор.

CLVM — это расширение для LVM2 которое позволяет безопасно использовать один или несколько шареных LUN’ов на множестве хостов.
Суть идеи. Мы привозим на все хосты LUN, создаем на любом из хостов PV, VG, LVs и все члены кластера сразу же видят все LV, их изменения а так же могут сами изменять любые параметры VG,LV. Тоесть нам более не нужно вообще ходить в СХД. Не нужно там нечего создавать, удалять, экспортить\мапить. Все, теперь вся работа с лунами может быть выполнена локально, на любой из нод кластера. Причем, время выполнения операций создания, удаления будет всегда предсказуема т.к. за это отвечает Device Mapper который по сути мапит адреса виртуального устройства(Logical volume) на адреса физического.

В свою очередь — CLVM обеспечивает целостность метаданных LVM которые хранятся прямо на PV! За счет механизма DLM(Distributed Lock Manager), реализуется механизм блокировок гарантирующий, что в один момент времени будет выполняться только одно изменение метаданных.

CLVM представлен в виде сервиса на каждой ноде кластера но сам по себе он не обеспечивает взаимодействие с членами кластера. Для этого ему нужна «общая шина».
В rhel 6 эту шину реализует cman(cluster managment).
cman это высокоуровневый менеджмент над corosync(собственно сердце любого кластера) и различными fancing-агентами.
cman обеспечивает доставку сообщений всем членам кластера и поддерживает кворум, пока живо большинство нод.

Настройка

На всех нодах кластера:

yum install lvm2-cluster

 не уверен, что это нужно, скорее всего он будет подгружен автоматически:

modprobe dlm

 DLM(Distributed Lock Manager) который реализует POSIX lock механизм позволяющий лочить не весь файл а только часть(хз как это работает).

Конфиг cman, конкретно в случае с cLVM очень простой:

cat /etc/cluster/cluster.conf
<cluster name="test" config_version="2">
   <clusternodes>
     <clusternode name="clvm1" nodeid="1">
         <fence>
         </fence>
     </clusternode>
     <clusternode name="clvm2" nodeid="2">
         <fence>
         </fence>
     </clusternode>
     <clusternode name="clvm3" nodeid="3">
         <fence>
         </fence>
     </clusternode>
   </clusternodes>
   <fencedevices>
   </fencedevices>
   <rm>
   </rm>
</cluster>

 В конфиге должны быть описаны все ноды кластера и он должен быть на всех нодах.

Стартуем на всех нодах:

/etc/init.d/cman start

cman готов. Осталось настроить LVM на его использование:

vim /etc/lvm/lvm.conf

locking_type = 3
/etc/init.d/clvm start

Все. Теперь, можно создавать, удалять, изменять, снапшотить LV, VG на шареном PV и все изменения будут доступны на всех нодах кластера.

Ограничения cLVM

1. corosync не поддерживат более 32 нод в кластере(может быть 64, но это не точно, нужно смотреть код).
2. cman не позволяет завести одну ноду в два кластера.

Будущее cLVM — lvmlockd

Это другой подход к реализации cLVM. Здесь не нужен кластер менеджмент вообще. Блокировки объявляются не по сети — через общую шину кластера а пишутся прямо на диск(который общий)! Это снимает ограничение на количество нод в кластере. Теоретически в таком кластере может быть до 2000 нод.

Но есть и минусы. Этот механизм не готов к промышленной эксплуатации. Часть функциональности еще на экспериментальной стадии. Доступен только в rhel 7.1 и выше.

Настройка

На всех нодах:

yum install lvm2-lockd sanlock -y
vim /etc/lvm/lvm.conf

locking_type = 1
use_lvmlockd = 1

Задать уникальный(1-2000) host_id на каждой ноде:

vim /etc/lvm/lvmlocal.conf
systemctl start lvm2-lvmlockd wdmd sanlock

Создание VG

vgcreate --shared <vgname> <devices>

на других нодах, что бы иметь возможность работать с shared VG:

vgchange --lock-start <vgname>

Создание LV

lvcreate --name <name> --size 10Gb <vgname>

после создания, LV сразу же имеет статус ACTIVE и для нее создается DM девайс и симлинк в /dev  на этой ноде.

Если нужно, использовать LV на другой ноде, прежде его нужно деактивировать:

lvchange -aln /dev/test/t1

Это приводит к удалению DM деваса и перевод LV в статус ‘inactive’

На ноде на которой нужен этот LV, его нужно активировать:

Активировать эксклюзивно. Это не даст возможности активировать кому то еще.
Ресайз LV можно сделать только активировав эксклюзивно.

lvchange -aey /dev/test/t1

Активировать не эксклюзивно. Другие ноды тоже смогут его активировать.
Но, сделать ресайз не получится. Пока, что это не поддерживается.

lvchange -asy /dev/test/t1

Активация приводит к созданию DM девайса и симлинка для него.

Ресайз LV

Делается как обычно, когда LV активирован эксклюзивно.

Другие ограничения, которые пока еще не решены

limitations of lockd VGs
       Things that do not yet work in lockd VGs:
       · creating a new thin pool and a new thin LV in a single command
       · using lvcreate to create cache pools or cache LVs (use lvconvert)
       · using external origins for thin LVs
       · splitting mirrors and snapshots from LVs
       · vgsplit
       · vgmerge
       · resizing an LV that is active in the shared mode on multiple hosts

подробный man
http://man7.org/linux/man-pages/man8/lvmlockd.8.html

cLVM в ручную

Что будет если не использовать то или иное    сLVM расширение?

Ну например мы создадим LV на ноде А и сразу увидим ее в списке блочных устройств

[root@clvm1 ~] lvs
  LV      VG       Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_root VolGroup -wi-ao----  8.51g                                                    
  lv_swap VolGroup -wi-ao----  1.00g                                                    
  t1      test     -wi-a----- 20.00g
[root@clvm1 ~] lsblk

sda                           8:0    0  100G  0 disk
├─test-t1 (dm-2)            253:2    0   20G  0 lvm

На другой ноде, мы прекрасно считаем LVM метаданные но DM-девайс и привычный симлинк на него нам не кто не создаст:

[root@clvm2 ~] lvs
  LV      VG       Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_root VolGroup -wi-ao----  8.51g                                                    
  lv_swap VolGroup -wi-ao----  1.00g                                                    
  t1      test     -wi------- 20.00g

                  

[root@clvm2 ~] lsblk                                                 

sda                           8:0    0  100G  0 disk

Но все это можно делать в ручную.

Создание LV

Node A:

[root@clvm1 ~] lvcreate --name t1 --size 10G test
  Logical volume "t1" created.

Node B:

[root@clvm2 ~] lvscan
  ACTIVE            '/dev/VolGroup/lv_root' [8.51 GiB] inherit
  ACTIVE            '/dev/VolGroup/lv_swap' [1.00 GiB] inherit
  inactive          '/dev/test/t1' [10.00 GiB] inherit

тут мы видим, что LV существует но в статусе inactive.

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

[root@clvm2 ~] lvchange -aey /dev/test/t1
[root@clvm2 ~] lsblk
 
sda                           8:0    0  100G  0 disk
└─test-t1 (dm-2)            253:2    0   10G  0 lvm

Теперь этим диском можно пользоваться на ноде B. Это своего рода аналог экспорта на нужную NC только с помощью LVM.

Ресайз LV

Node A

[root@clvm1 ~] lvresize /dev/test/t1 --size +10G

Node B

Если нечего не делать то на других нодах размер DM девайса не изменится хотя lvscan покажет новый размер(он читает метаданные):

[root@clvm2 ~] lvscan
  ACTIVE            '/dev/test/t1' [20.00 GiB] inherit

Это связано с тем, что LVM это надстройка над device-mapper. Именно DM мапит LV на те или иные PV.
То есть мало изменить метаданные LVM, нужно еще сказать DM, что бы он перестроил свою таблица с учетом новых размеров:

Вот как выглядит карта до дерганья DM:

[root@clvm2 ~] dmsetup table test-t1
0 20971520 linear 8:0 8388600

а теперь мы говорим, DM привести LV к новому виду:

[root@clvm2 ~]# lvchange --refresh /dev/test/t1

и вот новая таблица с новым мапингом:

[root@clvm2 ~] dmsetup table test-t1
0 41943040 linear 8:0 8388600

Удаление LV

Теперь сделаем это на ноде B

[root@clvm2 ~] lvremove /dev/test/t1

LV, будет удален из метаданных, удален DM мапинг, и симлинк на LV.

на других нодах, где был активирован этот LV(нода A), его не будет в метадате но останется DM девайс и симлинк.
По сути в lsblk останется девайс в который можно продолжать писать!
Опять же, это по тому, что device-mapper живет отдельной жизнью от LVM.
LVM в случае удаления LV сам удаляет маппинг DM. Но, т.к. мы удалили LV на ноде B, а на ноде A не кто не отслеживает изменения метадаты(это как раз задача CLVMD). В таком случае мы должны удалить мапинг DM сами.

[root@clvm1 ~] dmsetup remove test-t1

Приофит.                    

В рассылке LVM мне сказали, что в принципе, если отсутствует конкуренция модификации методанных LVM, то можно и восе обойтись от cLVM.
Но, выбор за вами, я не бы не рискнул)