Предисловие Ссылка на заголовок
Вот и пришла пора увеличить место на своём домашнем сервере, для этого было куплено 2 диска разных производителей, но одинакового объёма.
Захотелось сделать soft RAID1, но мне не очень подходит mdadm, так как я хочу иметь более гибкое зеркало, которое можно будет легко расширить в будущем, а не выделять сразу большой объём.
Решил попытать счастья с LVM RAID, но информации по нему, в сжатом виде, мало, в основном всё заканчивает на том, как его создать. Попробую исправить этот пробел.

Мои диски
LVM Ссылка на заголовок
Нам понадобится 2 диска, если вы собираетесь настраивать RAID, если нет, то просто пропускайте части с настройкой второго диска.
Для тестирования необязательно иметь настоящие диски, можно использовать обычные файлы: How to create virtual block device (loop device/filesystem) in Linux
sdX, sdY, sdZ
, во избежание потери данных на реальных носителях.Инициализация Ссылка на заголовок
Казалось бы, сделал pvcreate
над диском и готово, но не тут то было…
Согласно рекомендациям1 2, стоит всегда создавать разделы на диске, во избежание проблем с софтом, который не знает об LVM и будет считать диск пустым.
Для разбивки диска я буду использовать gdisk
, обычно уже установлен, но если что, устанавливается командой:
apt install gdisk
gdisk /dev/sdX
# Смотрим разделы и проверяем, тот ли мы диск выбрали.
p
# Создаём пустую GUID partition table.
o # жмём `y`, чтобы удалить все разделы и создать GPT запись.
# Создаём первый и единственный раздел на весь диск.
n
1
<enter>
<enter>
8e00 # Указываем, что данный раздел относится к LVM.
# Теперь можно просмотреть то, что получилось.
p
# Если всё устраивает, то осталось записать изменения на диск.
w # жмём `y`, чтобы подтвердить запись.
проделываем то же самое со вторым диском.
Добавляем диски в LVM
pvcreate /dev/sdX1 /dev/sdY1
# или коротко
pvcreate /dev/sd[XY]1
Создаём группу vgdata
из двух дисков
vgcreate vgdata /dev/sdX1 /dev/sdY1
# или коротко
vgcreate vgdata /dev/sd[XY]1
Простой логический диск Ссылка на заголовок
Создаём простой логический диск с именем lv0
на 3ГБ:
lvcreate --size 3G --name lv0 vgdata
# или коротко
lvcreate -L 3G -n lv0 vgdata
RAID 1 (mirror) Ссылка на заголовок
Создаём логический диск с RAID 1 под именем lvmirror
на 3ГБ:
lvcreate --size 3G --name lvmirror --mirrors 1 vgdata
# или коротко
lvcreate -L 3G -n lvmirror -m1 vgdata
можно указать флаг --nosync
, чтобы пропустить синхронизацию пустого зеркала.
Смотрим что получилось Ссылка на заголовок
lvs -a -o +devices
Колонка Cpy%Sync
показывает, процент синхронизации, а Devices
, устройства, на которых находятся данные логического диска.
FS Ссылка на заголовок
Осталось создать файловую систему:
mkfs.ext4 /dev/vgdata/lvmirror
И можно примонтировать и пользоваться
mount /dev/vgdata/lvmirror /mnt/
Тестируем LVM RAID 1 и учимся чинить Ссылка на заголовок
Как можно доверять свои данные технологии, когда ты не знаешь, что произойдёт в случае нештатной ситуации и как всё починить без потери данных.
Для начала, посмотрим, как у нас всё выглядит до начала тестов:
lvs -a -o +devices,lv_health_status
LV VG Attr LSize Cpy%Sync Devices Health
lvmirror vgdata rwi-aor--- 3.00g 100.00 lvmirror_rimage_0(0),lvmirror_rimage_1(0)
[lvmirror_rimage_0] vgdata iwi-aor--- 3.00g /dev/sdX1(1)
[lvmirror_rimage_1] vgdata iwi-aor--- 3.00g /dev/sdY1(1)
[lvmirror_rmeta_0] vgdata ewi-aor--- 4.00m /dev/sdX1(0)
[lvmirror_rmeta_1] vgdata ewi-aor--- 4.00m /dev/sdY1(0)
Теперь мы можем приступать к тестированию, но сначала:
Отвал диска (ресинхронизация) и его замена Ссылка на заголовок
В данном случае, мы будем симулировать отвал диска, через изменение его состояния 3
Отключаем диск sdX
:
echo offline > /sys/block/sdX/device/state
Теперь, чтобы LVM понял, что с диском что-то не то, нужно записать на диск данные.
Если FS есть:
echo test > /mnt/test.txt
Если FS нет(эта команда уничтожит FS, если она есть!):
dd if=/dev/zero of=/dev/vgdata/lvmirror count=10
Смотрим результат:
lvs -a -o +devices,lv_health_status
/dev/sdX: open failed: No such device or address
/dev/sdX: open failed: No such device or address
/dev/sdX: open failed: No such device or address
WARNING: Couldn't find device with uuid VkIceg-2ZVd-tTuZ-HgHz-EblT-5GwQ-oH3gKM.
WARNING: VG vgdata is missing PV VkIceg-2ZVd-tTuZ-HgHz-EblT-5GwQ-oH3gKM (last written to /dev/sdX1).
WARNING: Couldn't find all devices for LV vgdata/lvmirror_rmeta_0 while checking used and assumed devices.
WARNING: Couldn't find all devices for LV vgdata/lvmirror_rimage_0 while checking used and assumed devices.
LV VG Attr LSize Cpy%Sync Devices Health
lvmirror vgdata rwi-aor-p- 3.00g 100.00 lvmirror_rimage_0(0),lvmirror_rimage_1(0) partial
[lvmirror_rimage_0] vgdata iwi-aor-p- 3.00g [unknown](1) partial
[lvmirror_rimage_1] vgdata iwi-aor--- 3.00g /dev/sdY1(1)
[lvmirror_rmeta_0] vgdata ewi-aor-p- 4.00m [unknown](0) partial
[lvmirror_rmeta_1] vgdata ewi-aor--- 4.00m /dev/sdY1(0)
Обратите внимание, статус Health
стал partial
Теперь запишем рандомные данные на диск, чтобы можно было увидеть рассинхронизацию:
FS есть, пишем в файл /mnt/random.file
:
dd if=/dev/urandom of=/mnt/random.file bs=10M count=10
FS нет(эта команда уничтожит FS, если она есть!):
dd if=/dev/urandom of=/dev/vgdata/lvmirror bs=10M count=10
Включаем диск sdX
обратно:
echo running > /sys/block/sdX/device/state
Смотрим результат:
lvs -a -o +devices,lv_health_status
LV VG Attr LSize Cpy%Sync Devices Health
lvmirror vgdata rwi-aor-r- 3.00g 100.00 lvmirror_rimage_0(0),lvmirror_rimage_1(0) refresh needed
[lvmirror_rimage_0] vgdata Iwi-aor-r- 3.00g /dev/sdX1(1) refresh needed
[lvmirror_rimage_1] vgdata iwi-aor--- 3.00g /dev/sdY1(1)
[lvmirror_rmeta_0] vgdata ewi-aor-r- 4.00m /dev/sdX1(0) refresh needed
[lvmirror_rmeta_1] vgdata ewi-aor--- 4.00m /dev/sdY1(0)
Ошибки и предупреждения об отсутствии диска пропали, но статус Health
изменился на refresh needed
Чиним Ссылка на заголовок
Запускаем синхронизацию командой:
lvchange --refresh /dev/vgdata/lvmirror
Но если диск выпал, я бы рекомендовал его заменить на новый, проинициализировав его как в начале статьи и добавив в PV и VG:
pvcreate /dev/sdZ1
vgextend vgdata /dev/sdZ1
И заменив диск у зеркала:
lvconvert --replace /dev/sdX1 /dev/vgdata/lvmirror /dev/sdZ1
Замена мёртвого диска Ссылка на заголовок
Теперь давайте просимулируем замену мёртвого диска, для этого нам придётся стереть заголовок нашего диска, чтобы он выглядел как новый:
Эта команда уничтожит данные на диске!
dd if=/dev/zero of=/dev/sdX bs=10M count=1
При вызове
lvs -a -o +devices,lv_health_status
Мы увидим тот же результат, что и при отвале диска, статус Health
стал partial
, но чинится это по другому.
Чиним Ссылка на заголовок
Удалим старый диск из VG
vgreduce --removemissing --force vgdata
Так как мы стёрли заголовки диска, нам придётся проинициализировать диск заново и добавить его в PV и VG:
pvcreate /dev/sdX1
vgextend vgdata /dev/sdX1
И нужно починить наше зеркало
lvconvert --repair /dev/vgdata/lvmirror
Автоматически запуститься ресинхронизация.
Конвертируем логический диск из RAID 1 в обычный Ссылка на заголовок
lvconvert -m0 /dev/vgdata/lvmirror
Конвертируем логический диск из обычного в RAID 1 Ссылка на заголовок
lvconvert -m1 /dev/vgdata/lvmirror
Увеличиваем размер диска с зеркалом Ссылка на заголовок
umount /dev/vgdata/lvmirror
# Добавляем 5GB к диску
lvresize --resizefs --size +5G /dev/vgdata/lvmirror
# Смотрим результат
lvs
Уменьшаем размер диска с зеркалом Ссылка на заголовок
umount /dev/vgdata/lvmirror
# Делаем диск равным 4GB
lvresize --resizefs --size 4G /dev/vgdata/lvmirror
# Смотрим результат
lvs
Мониторинг Ссылка на заголовок
Для мониторинга состояния LVM я написал exporter для prometheus
lvm_exporter
Как я всё сломал Ссылка на заголовок
Пока писал статью, успел сломать тестовый LVM
Inconsistent metadata Ссылка на заголовок
Когда отключил диск, я решил удалить лишнее зеркало (у меня было 2 LV зеркальных), после подключения диска обратно, у меня появилась ошибка при любой команде LVM:
WARNING: ignoring metadata seqno 20 on /dev/sdX1 for seqno 21 on /dev/sdY1 for VG vgdata.
WARNING: Inconsistent metadata found for VG vgdata
WARNING: outdated PV /dev/sdX1 seqno 20 has been removed in current VG vgdata seqno 21.
После долгих поисков, нашёл нужную мне команду в багтрекере 4, которая мне помогла:
vgck --updatemetadata vgdata