LVM на боевых серверах: расширение дисков без даунтайма для хостинга

Задача клиента: расширение хранилища на работающих серверах

Хостинг-провайдер «ХостЛайн» столкнулся с ростом, к которому не был готов: за три месяца количество клиентов удвоилось, а дисковое пространство на серверах подходило к концу. У компании 12 физических серверов с RAID-массивами, на каждом размещено от 20 до 50 виртуальных машин. Файловые системы создавались напрямую на разделах — без LVM.

Проблема очевидна: чтобы добавить диск или перераспределить пространство, нужно было останавливать виртуальные машины, копировать данные и пересоздавать файловые системы. Каждая операция занимала 2-4 часа простоя и требовала ночного окна обслуживания.

Специалисты itfresh.ru предложили миграцию на LVM (Logical Volume Manager) — подсистему Linux для гибкого управления дисковым пространством с возможностью расширения, снапшотов и миграции данных без остановки сервисов.

Архитектура LVM: PV, VG, LV

LVM работает на трёх уровнях абстракции, каждый из которых добавляет гибкость:

  • Physical Volume (PV) — физический диск или раздел, инициализированный для LVM. PV разбивается на экстенты фиксированного размера (по умолчанию 4 МБ).
  • Volume Group (VG) — пул экстентов, объединяющий один или несколько PV. Это аналог виртуального диска неограниченного размера.
  • Logical Volume (LV) — виртуальный раздел внутри VG, на котором создаётся файловая система. Размер LV можно менять динамически.
# Инициализация нового диска как PV
$ pvcreate /dev/sdb
  Physical volume "/dev/sdb" successfully created.

# Создание Volume Group
$ vgcreate vg_hosting /dev/sdb
  Volume group "vg_hosting" successfully created

# Добавление второго диска в существующую VG
$ pvcreate /dev/sdc
$ vgextend vg_hosting /dev/sdc
  Volume group "vg_hosting" successfully extended

# Создание Logical Volume на 100 ГБ
$ lvcreate -L 100G -n lv_vm042 vg_hosting
  Logical volume "lv_vm042" created.

# Создание файловой системы
$ mkfs.ext4 /dev/vg_hosting/lv_vm042

# Монтирование
$ mount /dev/vg_hosting/lv_vm042 /srv/vms/vm042

Для «ХостЛайн» мы создали на каждом сервере единую VG из всех доступных дисков. Это позволило выделять пространство виртуальным машинам гибко — не привязываясь к размеру конкретного физического диска.

Онлайн-расширение: lvextend без остановки сервисов

Главная причина миграции на LVM — возможность увеличить дисковое пространство виртуальной машины на лету. Клиент «ХостЛайн» запрашивает дополнительные 50 ГБ — оператор выполняет две команды, и пространство доступно через секунды.

# Проверяем свободное место в VG
$ vgs
  VG         #PV #LV #SN Attr   VSize   VFree
  vg_hosting   4  35   0 wz--n-   3.64t 890.00g

# Расширяем LV на 50 ГБ
$ lvextend -L +50G /dev/vg_hosting/lv_vm042
  Size of logical volume vg_hosting/lv_vm042 changed from 100.00 GiB to 150.00 GiB.
  Logical volume vg_hosting/lv_vm042 successfully resized.

# Расширяем файловую систему ext4 (онлайн, без размонтирования)
$ resize2fs /dev/vg_hosting/lv_vm042
resize2fs 1.47.0 (5-Feb-2023)
Filesystem at /dev/vg_hosting/lv_vm042 is mounted on /srv/vms/vm042; on-line resizing required
old_desc_blocks = 13, new_desc_blocks = 19
The filesystem on /dev/vg_hosting/lv_vm042 is now 39321600 (4k) blocks long.

# Для XFS используется другая команда (тоже онлайн)
$ xfs_growfs /srv/vms/vm042
meta-data=/dev/vg_hosting/lv_vm042 isize=512    agcount=4, agsize=6553600 blks
data     =                       bsize=4096   blocks=39321600, imaxpct=25
data     =                       bsize=4096   blocks=39321600, imaxpct=25

Можно совместить операции в одну команду:

# Расширить LV и файловую систему одной командой
$ lvextend -L +50G --resizefs /dev/vg_hosting/lv_vm042

# Расширить LV до заполнения всего свободного места в VG
$ lvextend -l +100%FREE --resizefs /dev/vg_hosting/lv_vm042

Важное ограничение: ext4 и XFS поддерживают онлайн-расширение, но не онлайн-уменьшение. Для уменьшения ext4 нужно размонтировать файловую систему. XFS уменьшение вообще не поддерживает — только создание нового LV и копирование данных.

LVM-снапшоты для резервного копирования

LVM-снапшоты создают мгновенную копию LV на определённый момент времени. Технически используется механизм Copy-on-Write (CoW): снапшот не копирует данные, а сохраняет только изменения, сделанные после создания снапшота.

# Создание снапшота (10 ГБ для хранения изменений)
$ lvcreate -L 10G -s -n snap_vm042 /dev/vg_hosting/lv_vm042
  Logical volume "snap_vm042" created.

# Проверка состояния снапшота
$ lvs
  LV          VG         Attr       LSize   Pool Origin   Data%  Meta%
  lv_vm042    vg_hosting owi-aos--- 150.00g
  snap_vm042  vg_hosting swi-a-s---  10.00g      lv_vm042 0.00

# Монтирование снапшота для бэкапа (read-only)
$ mount -o ro /dev/vg_hosting/snap_vm042 /mnt/backup

# Бэкап с помощью rsync
$ rsync -aAXv /mnt/backup/ /backup/vm042/$(date +%Y%m%d)/

# Или создание tar-архива
$ tar czf /backup/vm042_$(date +%Y%m%d).tar.gz -C /mnt/backup .

# Размонтирование и удаление снапшота
$ umount /mnt/backup
$ lvremove /dev/vg_hosting/snap_vm042

Автоматизированный скрипт бэкапа для «ХостЛайн»:

#!/bin/bash
# /opt/scripts/lvm-backup.sh
set -euo pipefail

VG="vg_hosting"
BACKUP_DIR="/backup"
SNAP_SIZE="10G"
RETENTION_DAYS=7

for LV in $(lvs --noheadings -o lv_name $VG | grep -v snap_ | tr -d ' '); do
    SNAP="snap_${LV}"
    MOUNT="/mnt/snap_${LV}"

    echo "[$(date)] Creating snapshot for $LV"
    lvcreate -L $SNAP_SIZE -s -n $SNAP /dev/$VG/$LV || continue

    mkdir -p $MOUNT
    mount -o ro /dev/$VG/$SNAP $MOUNT

    DEST="$BACKUP_DIR/$LV/$(date +%Y%m%d)"
    mkdir -p $DEST
    rsync -aAX --delete $MOUNT/ $DEST/

    umount $MOUNT
    lvremove -f /dev/$VG/$SNAP
    rmdir $MOUNT

    echo "[$(date)] Backup of $LV complete: $DEST"
done

# Удаление старых бэкапов
find $BACKUP_DIR -maxdepth 2 -mindepth 2 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;

Критически важно следить за заполнением снапшота. Если область для изменений (10 ГБ в нашем примере) заполняется на 100%, снапшот становится невалидным и автоматически деактивируется. Мониторинг через lvs -o lv_name,data_percent.

Thin provisioning и LVM cache

Для оптимизации использования дисков мы внедрили thin provisioning — технологию, при которой LV выделяется виртуальный размер, но физическое пространство занимается только по мере записи данных.

# Создание thin pool (общий пул для всех тонких LV)
$ lvcreate -L 2T --thinpool thinpool_hosting vg_hosting
  Thin pool volume with chunk size 64.00 KiB is created.
  Logical volume "thinpool_hosting" created.

# Создание тонкого LV (виртуально 100 ГБ, физически — по потреблению)
$ lvcreate -V 100G --thin -n lv_vm043 vg_hosting/thinpool_hosting
  Logical volume "lv_vm043" created.

# Создание ещё 30 LV по 100 ГБ каждый
# Суммарно 3 ТБ виртуального пространства при пуле 2 ТБ
for i in $(seq 44 73); do
    lvcreate -V 100G --thin -n lv_vm0${i} vg_hosting/thinpool_hosting
done

# Мониторинг фактического заполнения пула
$ lvs -o lv_name,lv_size,data_percent,metadata_percent vg_hosting/thinpool_hosting
  LV                LSize Data%  Meta%
  thinpool_hosting  2.00t 34.21  8.45

Thin provisioning позволил «ХостЛайн» предоставлять клиентам большие диски, зная, что большинство из них никогда не заполняют их полностью. Overcommit 150% — стандартная практика для хостинга.

Для ускорения дисковых операций мы добавили LVM cache — NVMe SSD используется как кэш для массива HDD:

# Подготовка SSD для кэша
$ pvcreate /dev/nvme0n1
$ vgextend vg_hosting /dev/nvme0n1

# Создание кэш-пула на SSD (200 ГБ кэш + метаданные)
$ lvcreate -L 200G -n cache_data vg_hosting /dev/nvme0n1
$ lvcreate -L 1G -n cache_meta vg_hosting /dev/nvme0n1

# Объединение в кэш-пул
$ lvconvert --type cache-pool --poolmetadata vg_hosting/cache_meta \
    vg_hosting/cache_data

# Подключение кэша к существующему LV
$ lvconvert --type cache --cachepool vg_hosting/cache_data \
    --cachemode writeback vg_hosting/lv_vm042

# Проверка статистики кэша
$ lvs -o name,cache_read_hits,cache_read_misses,cache_write_hits \
    vg_hosting/lv_vm042
  LV       CacheReadHits CacheReadMisses CacheWriteHits
  lv_vm042 847293        12451           523847

Режим writeback даёт максимальную производительность (записи кэшируются на SSD), но требует UPS — при потере питания данные из SSD-кэша могут быть утрачены. Режим writethrough безопаснее, но ускоряет только чтение.

Миграция между дисками: pvmove без даунтайма

Когда один из HDD на сервере «ХостЛайн» начал показывать ошибки SMART, нужно было срочно перенести данные на новый диск — без остановки виртуальных машин. LVM позволяет это сделать командой pvmove.

# Проверка SMART-статуса
$ smartctl -a /dev/sdb | grep -E 'Reallocated|Current_Pending'
  5 Reallocated_Sector_Ct   0x0033   098   098   036    Pre-fail  Always       -       142
197 Current_Pending_Sector  0x0012   100   100   000    Old_age   Always       -       8

# Какие LV расположены на проблемном диске
$ pvs -o+pv_used --segments /dev/sdb
  PV         VG         Fmt  Attr PSize   PFree  Used
  /dev/sdb   vg_hosting lvm2 a--  931.51g 12.00g 919.51g

# Подготовка нового диска
$ pvcreate /dev/sdd
$ vgextend vg_hosting /dev/sdd

# Миграция всех данных с /dev/sdb на /dev/sdd (онлайн!)
$ pvmove /dev/sdb /dev/sdd
  /dev/sdb: Moved: 0.2%
  /dev/sdb: Moved: 3.8%
  /dev/sdb: Moved: 7.1%
  ...
  /dev/sdb: Moved: 100.0%

# Удаление старого диска из VG
$ vgreduce vg_hosting /dev/sdb
  Removed "/dev/sdb" from volume group "vg_hosting"

# Очистка метаданных LVM
$ pvremove /dev/sdb

Процесс pvmove работает в фоне, данные копируются поблочно, и все операции I/O прозрачно перенаправляются. Виртуальные машины продолжают работать без прерывания. Скорость миграции зависит от нагрузки — для 900 ГБ данных на нашем сервере процесс занял около 4 часов.

Для мониторинга прогресса в фоне:

# Запуск pvmove в фоне
$ pvmove -b /dev/sdb /dev/sdd

# Проверка прогресса
$ lvs -a -o name,copy_percent | grep pvmove
  [pvmove0]  45.32

Мониторинг и восстановление после сбоя

LVM хранит метаданные в специальной области на каждом PV и автоматически создаёт резервные копии в /etc/lvm/backup/ и /etc/lvm/archive/. Это критически важно для восстановления.

# Обзор всех PV, VG, LV
$ pvs
  PV         VG         Fmt  Attr PSize   PFree
  /dev/sda2  vg_hosting lvm2 a--  931.51g  0
  /dev/sdc   vg_hosting lvm2 a--  931.51g  12.00g
  /dev/sdd   vg_hosting lvm2 a--  931.51g 280.00g
  /dev/nvme0n1 vg_hosting lvm2 a-- 476.94g  275.94g

$ vgs
  VG         #PV #LV #SN Attr   VSize  VFree
  vg_hosting   4  35   0 wz--n-  3.24t 567.94g

$ lvs -o lv_name,lv_size,data_percent,origin,pool_lv
  LV           LSize   Data%  Origin Pool
  lv_vm042     150.00g
  lv_vm043     100.00g 45.21         thinpool_hosting
  thinpool_hosting 2.00t 34.21

# Детальная информация о физическом размещении
$ pvdisplay --maps /dev/sdc

# Восстановление метаданных VG из архива
$ vgcfgrestore -l vg_hosting
  File: /etc/lvm/archive/vg_hosting_00042-1234567890.vg
  ...

$ vgcfgrestore -f /etc/lvm/archive/vg_hosting_00042-1234567890.vg vg_hosting

Скрипт мониторинга для «ХостЛайн»:

#!/bin/bash
# /opt/scripts/lvm-monitor.sh
THRESHOLD=85
TG_BOT="5551234567:AAHxxx"
TG_CHAT="-100123456789"

# Проверка заполнения VG
VG_FREE_PCT=$(vgs --noheadings -o vg_free_count,vg_extent_count vg_hosting | \
    awk '{printf "%.0f", ($1/$2)*100}')

if [ "$VG_FREE_PCT" -lt $((100 - THRESHOLD)) ]; then
    MSG="⚠️ VG vg_hosting: свободно ${VG_FREE_PCT}%"
    curl -s "https://api.telegram.org/bot${TG_BOT}/sendMessage" \
        -d chat_id="${TG_CHAT}" -d text="${MSG}" > /dev/null
fi

# Проверка thin pool
DATA_PCT=$(lvs --noheadings -o data_percent vg_hosting/thinpool_hosting | tr -d ' ')
if (( $(echo "$DATA_PCT > $THRESHOLD" | bc -l) )); then
    MSG="⚠️ Thin pool: заполнен на ${DATA_PCT}%"
    curl -s "https://api.telegram.org/bot${TG_BOT}/sendMessage" \
        -d chat_id="${TG_CHAT}" -d text="${MSG}" > /dev/null
fi

Результаты внедрения LVM для «ХостЛайн»:

МетрикаДо (разделы)После (LVM)
Время расширения диска клиенту2-4 часа (даунтайм)10 секунд (онлайн)
Замена неисправного диска4-6 часов (ручная миграция)4 часа (pvmove в фоне, без даунтайма)
Overcommit хранилищаНевозможен150% с thin provisioning
Время бэкапа 100 ГБ VM40 минут (копирование блочного устройства)15 минут (снапшот + rsync)
Производительность I/O (IOPS)HDD baseline+340% с LVM cache на NVMe

Если ваш хостинг работает на физических серверах и вы хотите гибкое управление дисковым пространством — обращайтесь к специалистам itfresh.ru. Мы спроектируем LVM-архитектуру под ваши задачи.

Часто задаваемые вопросы

Да, ext4 и XFS поддерживают онлайн-расширение. Для ext4 используйте resize2fs, для XFS — xfs_growfs. Уменьшение возможно только для ext4 и только после размонтирования. XFS уменьшение не поддерживает в принципе.
Без LVM RAID — все LV, имеющие экстенты на этом диске, будут повреждены. LV, целиком расположенные на других дисках, останутся доступны. Для защиты используйте LVM RAID (lvconvert --type raid1) или аппаратный/программный RAID (mdadm) под LVM.
Обычный LV сразу резервирует физическое пространство на диске. Тонкий LV использует пространство по мере фактической записи данных. Это позволяет создавать LV с суммарным виртуальным размером больше физического пула (overcommit), но требует мониторинга заполнения thin pool.
pvmove безопасен: данные копируются поблочно, все I/O-операции прозрачно перенаправляются, приложения не замечают миграции. При прерывании (сбой питания) pvmove можно возобновить командой pvmove без аргументов. Рекомендуется запускать в screen/tmux и мониторить прогресс.
LVM cache использует быстрый SSD как кэш для медленного HDD. Режим writethrough ускоряет только чтение (безопасен при сбое), writeback ускоряет и запись (требует UPS). На практике даёт 3-5x прирост IOPS для рабочих нагрузок с горячим набором данных.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#lvm#logical volume manager#lvextend#resize2fs#xfs_growfs#lvm snapshot#thin provisioning#dm-cache
Комментарии 0

Оставить комментарий

загрузка...