LVM: использование снапшотов

Введение

В данной статье рассмотрены принципы и методики по применению снапшотов. Для более лучшего понимания материала необходимо знать, что такое LVM на базовом уровне и уметь оперировать с PV, VG, LV.

Назначение и принцип работы снапшотов

Снапшоты отчасти относятся к системам резервного копирования, но по сути не являются бэкапом, а лишь позволяют возвращать данные в исходное состояние на определенный момент времени. Так, когда необходимо сделать полный бэкап (например, сервера с активной базой данных), понадобится останавливать запись на диск и только потом снимать копию, т.к. в противном случае не все данные попадут в копию. Вариант с наличием slave-базы в счёт не берется, т.к. это частный случай ещё одной возможности для создания резервной копии. При больших объемах копирование может занимать несколько часов и более, что недопустимо для production-систем, работающих 24\7 – ведь никто не останавливает боевую базу для снятия дампа.

В таких случаях при необходимости создания полной копии без остановки на запись (почти) и приходят на помощь снапшоты. При создании снапшота происходит моментальный снимок или “заморозка” данных. Процесс создания снимка происходит, как правило, очень быстро – приложение или операционная система на какое-то непродолжительное время приостанавливает запись, и в этот момент создается моментальный снимок текущего состояния данных. Под приостановкой записи подразумевается, что приложение будет работать, но процессы записи на диск осуществляться не будут. Для клиента это может выглядеть как некая кратковременная задержка. Длительность такой задержки будет зависеть от приложения и его размера.

COW (Copy-On-Write)

Итак, разобравшись, что такое снапшот и когда он применяется, необходимо понимать, что происходит с файлами после создания снимка. Снапшот создан, и все старые файлы, т.е. которые не изменялись на момент создания снимка, остались на месте. А вот новые файлы или изменения для существующих уже будут записаны в новое расположение файловой системы на диске. Даже когда модификация данных завершена, старые данные никогда не перезаписываются. По сути будет создан ещё один файл, в котором содержатся все изменения (дельта), которые происходят с исходными данными. Таким образом достигается экономия дискового пространства засчет хранения лишь изменений на диске, а не полной копии данных. Технически происходит следующее: при необходимости изменения старого файла создается reflink и выделяется место под изменения.

Поэтому есть общие рекомендации и напоминания относительно снапшотов:

  1. Снапшот – не бэкап!
  2. Не стоит хранить снапшоты длительное время, особенно в продакшене. Снапшот выполнил свою функцию и должен быть сразу удален.
  3. Не стоит хранить большое дерево снапшотов (2-3 штуки будет достаточно), в противном случае производительность диска значительно просядет.

LVM

По большей части со снапшотами приходится сталкиваться при работе с виртуальными машинами. И действительно, очень удобно бывает сделать снимок виртуалки, провести эксперимент и откатиться на снапшот в случае неудачи. Но возможность создания снапшотов также присутствует и в LVM – когда-то давно я описывал базовые принципы работы LVM в своей статье. Теперь же будет рассмотрен дополнительный функционал по работе со снапшотами.

LVM1 vs LVM2

Перед продолжением, стоит кратко упомянуть, что существуют две версии – LVM1, которая имеет несколько отличий от LVM2. Самым главным отличием является следующее:

  • если блок должен быть изменен в источнике, он сначала копируется в моментальный снимок (снапшот), помечается как скопированный в таблице исключений, а затем новые данные записываются в исходный том. Так работает LVM1, снимки которого являются readonly.
  • LVM2 позволяет создавать снимки для чтения и записи, т.е. работает схожим образом, как и LVM1, но при необходимости записи данных в самом снапшоте, блоки данных помечаются в таблице исключений как используемые и уже никогда не будут скопированы с исходного тома.

Под таблицей исключений понимается хеш-таблица, в которой записываются все сопоставления относительно изменений блоков и таблицы CoW. Но это уже глубокие технические подкапотные детали, с которыми можно ознакомиться по ссылке.

В целом обе версии можно использовать, но у второй есть несомненное преимущество в виде возможности изменений в самом снапшоте.

Пример использования

Подготовительные работы

После того, как с теорией разобрались, пора переходить к практике! В качестве лабораторного стенда будет использоваться Centos 7 с установленным пакетом lvm2:

yum install lvm2
  • PV: sdb1 5 Гб
  • VG: vg_data 5 Гб
  • LV: lv_data 2,5 Гб
  • точки монтирования: /mnt и /mnt2

Отличительной особенностью является то, что для создания снапшота в VG должно быть свободное пространство, которое будет использоваться для записи изменений, т.е. это место будут занимать изменяемые данные в исходном томе, которые “доезжают” уже после создания снапшота. Поэтому в качестве примера был создан LV размером 2,5 Гб, а остальное пространство осталось неиспользованным:

vgs
  VG      #PV #LV #SN Attr   VSize  VFree
  vg_data   1   1   0 wz--n- <5.00g 2.50g

Далее LV был смонтирован по пути /mnt, и туда записаны произвольные файлы:

df -h
Filesystem                   Size  Used Avail Use% Mounted on
devtmpfs                     454M     0  454M   0% /dev
tmpfs                        464M  6.8M  457M   2% /run
tmpfs                        464M     0  464M   0% /sys/fs/cgroup
/dev/sda3                     19G  4.5G   14G  26% /
/dev/sda1                    190M  136M   41M  78% /boot
/dev/mapper/vg_data-lv_data  2.5G  135M  2.4G   6% /mnt

echo "test record" >/mnt/snapshot.txt
dd if=/dev/zero of=/mnt/test_file bs=512M count=1 oflag=dsync

Команда ниже показывается, что в данный момент присутствует только один LV, готовый к работе (в выводе lvs attr есть флаг “о” – open):

lvs
  LV      VG      Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_data vg_data -wi-ao---- <2.50g

Создание снапшота

Для создания снапшота достаточно выполнить команду ниже. Используется lvcreate, т.к. снапшот по сути является LV, но особенностью является то, что необходимо указать размер, куда будут записываться изменения. Для этого должно быть свободное место в VG, в данном случае из доступных 2,5 Гб указывается 1 Гб и наименование снапшота – snap_vg_data:

lvcreate -L 1G -s -n snap_vg_data /dev/mapper/vg_data-lv_data

Т.к. снапшот – это по сути LV, проверить его наличие можно командой ниже:

lvs
  LV           VG      Attr       LSize  Pool Origin  Data%  Meta%  Move Log Cpy%Sync Convert
  lv_data      vg_data owi-aos--- <2.50g
  snap_vg_data vg_data swi-a-s---  1.00g      lv_data 0.00

Как видно из команды выше, у исходного тома и снапшота появились новые атрибуты:

  1. Источник снапшота, т.е. указывает, что том является исходным относительно снапшота, origin
  2. Права на запись, writable
  3. Политика размещения: унаследовано от VG, inherit
  4. Статус, active
  5. Устройство: открыто или смонтировано, open

Также можно посмотреть более подробный вывод про LV или снапшот, где вся информация будет в расширенном виде:

lvdisplay /dev/vg_data/snap_vg_data
  --- Logical volume ---
  LV Path                /dev/vg_data/snap_vg_data
  LV Name                snap_vg_data
  VG Name                vg_data
  LV UUID                6J1Fxj-x5Gi-i0zh-FHhn-fwA2-A51k-wavtFv
  LV Write Access        read/write
  LV Creation host, time node.local, 2021-05-13 14:36:37 +0300
  LV snapshot status     active destination for lv_data
  LV Status              available
  # open                 0
  LV Size                <2.50 GiB
  Current LE             639
  COW-table size         1.00 GiB
  COW-table LE           256
  Allocated to snapshot  0.00%
  Snapshot chunk size    4.00 KiB
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:3

Помимо атрибутов, появилось поле Data (Allocated to snapshot в lvdisplay), которое показывает свободное место для снапшота в процентах. На данный момент весь выделенный гигабайт свободен, т.к. в исходный том в /mnt не было записано никаких изменений.

Теперь же в исходный том будут внесены изменения для демонстрации поведения снапшота:

dd if=/dev/zero of=/mnt/test_file1 bs=512M count=1 oflag=dsync

Был создан простой файл, забитый нулями, размером 512 Мб. И в lvs это изменение сразу учитывается:

lvs
  LV           VG      Attr       LSize  Pool Origin  Data%  Meta%  Move Log Cpy%Sync Convert
  lv_data      vg_data owi-aos--- <2.50g
  snap_vg_data vg_data swi-a-s---  1.00g      lv_data 50.79

Ещё одним способом для наглядной проверки использования места снапшотом является утилита dmsetup:

dmsetup status /dev/vg_data/snap_vg_data
0 5234688 snapshot 1065088/2097152 4160

В выводе выше интересны последние три цифры:

  • кол-во используемых секторов
  • кол-во доступных секторов
  • кол-во мета секторов

При записи на исходный том количество мета секторов будет увеличиваться.

Повреждения снапшота

Может возникнуть логичный вопрос, а что произойдет, если все секторы будут использованы, и отведенный гигабайт исчерпается? Такой снапшот станет непригодным для использования. Так, если создать ещё один файл через dd и после посмотреть статус:

dd if=/dev/zero of=/mnt/test_file2 bs=512M count=1 oflag=dsync

lvs
  LV           VG      Attr       LSize  Pool Origin  Data%  Meta%  Move Log Cpy%Sync Convert
  lv_data      vg_data owi-aos--- <2.50g
  snap_vg_data vg_data swi-I-s---  1.00g      lv_data 100.00

dmsetup status /dev/vg_data/snap_vg_data
0 5234688 snapshot Invalid

…то можно увидеть, что статус снапшота теперь Inactive в выводе lvs и Invalid в dmsetup.

Такой снепшот непригоден для использования и его остаётся только удалить:

lvremove /dev/vg_data/snap_vg_data

Для предотвращения такой ситуации настоятельно рекомендуется сохранять размер снапшота таким же, как у исходного логического тома, чтобы минимизировать риск повреждения снапшота. Это можно делать в автоматическом режиме, добавив параметры в /etc/lvm/lvm.conf:

snapshot_autoextend_threshold = 70
snapshot_autoextend_percent = 20

Максимальный размер снапшота – 1 Гб. Если его размер превысит 70% от допустимого размера, то есть будет занято 700 Мб, то допустимый размер будет увеличен на 20%, т.е. 1,2 Гб и т.д. Размер моментального снимка LVM будет продолжать увеличиваться до тех пор, пока есть свободное место в VG.

Монтирование снапшота

После повреждения и удаления снапшота, необходимо создать новый уже известной командой:

lvcreate -L 1G -s -n snap_vg_data /dev/mapper/vg_data-lv_data

Но теперь для использования функционала LVM2 можно смонтировать снапшот в отдельную точку /mnt/2:

mount -o nouuid /dev/vg_data/snap_vg_data /mnt2

Если не указать флаг -o nouuid при использовании XFS и смонтированном исходным LV (origin), то возникнет ошибка вида:

mount: wrong fs type, bad option, bad superblock on /dev/mapper/vg_data-snap_vg_data,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.

А в syslog появится сообщение: kernel: XFS (dm-3): Filesystem has duplicate UUID 78db9895-a427-4906-b496-fbd5df8a3ca3 – can’t mount

Причина тому проста: XFS имеет UUID, которые являются уникальными идентификаторами файловой системы. Две файловые системы с одинаковым UUID не могут быть смонтированы на одном сервере. Поскольку снапшоты по сути представляют собой одну и ту же файловую систему, UUID для обоих устройств будут одинаковыми, поэтому и используется ключ nouuid при монтировании.

Теперь имеются две точки монтирования, одна из которых является снапшотом. Для примера можно внести изменения в файлах на /mnt2, а после выполнить слияние с исходным LV.

Слияние (merge) снапшота с исходным LV

Данный функционал очень удобен при выполнении различных экспериментов. Самый простой, для примера: есть софт, который меняет файлы на диске. Перед применением на продакшене, необходимо проверить, что всё будет работать корректно. Смонтированный снапшот продуктивной LV идеально подойдет для проведения эксперимента – в случае его успешности можно будет выполнить слияние с исходным томом или же просто удалить. Исходная файловая система при этом никак не пострадает. Применение данного функционала можно найти в различных случаях.

На снапшоте для некоторых файлов вносятся изменения, после чего необходимо отмонтировать исходный LV и сам снапшот:

umount /mnt
umount /mnt2

lvdisplay должен показывать, что LV том не используется и значение open равно нулю:

lvdisplay /dev/vg_data/lv_data

  --- Logical volume ---
  LV Path                /dev/vg_data/lv_data
  LV Name                lv_data
  VG Name                vg_data
  LV UUID                cf06Db-ZGJy-ABmx-l111-CVx2-fXK7-6QgYOD
  LV Write Access        read/write
  LV Creation host, time node.local, 2021-05-13 14:28:46 +0300
  LV snapshot status     source of
                         snap_vg_data [active]
  LV Status              available
  # open                 0
  LV Size                <2.50 GiB
  Current LE             639
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:0

Теперь можно запустить слияние всех изменений из снапшота в исходный LV:

lvconvert --merge /dev/vg_data/snap_vg_data -b

Ключ -b означает запуск в фоновом режиме. Если в Attr значение “О”, значит мерж в процессе:

lvs
  LV      VG      Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_data vg_data Owi-a-s--- <2.50g             0.00

Наблюдать за прогрессом изменения секторов можно через dmsetup:

watch -n 1 dmsetup status /dev/vg_data/lv_data

В конечном итоге, если слияние завершилось, атрибуты будут следующие:

lvs
  LV      VG      Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_data vg_data -wi-ao---- <2.50g

Если кажется, что процесс подвис, а в dmsetup не происходит изменений, то нужно убедиться, что LV том не примонтирован. Если попытаться смонтировать том, то будет ошибка Command on LV vglxc/wikisnapshot is invalid on LV with properties: lv_is_merging_cow. В таком случае можно попытаться перезапустить мерж, указав аргументом наименование VG:

lvchange  --refresh vg_data

Заключение

В статье были рассмотрены теоретические аспекты назначения и применения снапшотов, а также проведены практические проверки на примере LVM2 в Centos 7. Резюмируя, стоит выделить основные моменты, о которых стоит помнить (повторюсь для закрепления):

  • Снапшот – не бэкап! Удобно создавать снапшоты, проводить какие-либо действия с файлами из снапшота, а после выполнять его удаление.
  • Размер моментального снимка LVM не зависит от размера исходного логического тома, так как моментальный снимок LVM занимает намного меньший размер, в то время как полноценная резервная копия занимает почти эквивалентный размер по сравнению с исходным логическим томом (в зависимости от типа сжатия).
  • Снапшоты не распределяют дисковое пространство сами по себе, как связанные с ними исходные LV, потому что для снимка требуется пространство только тогда, когда исходный LV был изменен, поэтому нужно следить за свободным местом в VG.

И ремарка по целесобразности использования снапшотов в прицнипе: конечно, в чистом виде создание снапшотов так или иначе тормозит работу приложения, но по идее всего лишь на несколько секунд плюс-минус. Но в любом случае при наличии критичной highload-системы и высокого SLA, создание снапшота на работающем сервере никто выполнять не будет – как минимум, такие серверы выводят из эксплуатации (методом исключения из балансировки, например), и далее уже выполняют создание снапшота, если это необходимо, или используют иные средства. А на всех же прочих не столь критичных системах вполне допустимо появление кратковременной задержки в пару секунд при создании снапшота опять же, если такой необходимо создать – например, перед обновлением какого-либо софта.

Лично мне не доводилось использовать снапшоты LVM, т.к. обычно я пользуюсь снапшотами, которые предоставляет делать гипервизор для виртуальных машин. Принцип работы такой же, что описан в начале статьи. Но также есть серверы, доступа к которым из консоли гипервизора у меня нет, и вот тут в теории уже можно будет попробовать использовать возможности снапшотов в LVM.

Используемые источники

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: