И Ceph (RBD) и Qemu умеют в discard/trim/unmap. Это означает, что гостевая ОС может отправить соответствующий запрос к хранилищу, чтобы сообщить что данные не нужны. Исходно это было предназначено для SSD-дисков с целью оптимизации wear-leveling (выравнивание износа). В RBD это позволяет удалить ненужные данные из кластера и тем самым уменьшить бекфиллинг, размеры снапшотов и др.
Мы знаем, что RBD виртуально делит диски на куски по 4 МБ (по-умолчанию). Каждый кусок -- это один объект Rados. Соответственно, дискард может либо удалить целиком один объект (если он не нужен), либо сократить размер (вплоть до нуля). Что он не может -- так это продискардить середину объекта или начало. Он мог бы просто заполнить нулями, но нет. Появляется ошибка, правда, не фатальная. В API RBD нет функции для выяснения размера чанка. Поэтому Qemu не может догадаться какие дискарды можно отправлять в librbd, а какие закончатся ошибкой. В документации про это ничего не сказано.
Есть костыль для ceph.conf -- параметр rbd_skip_partial_discard
. Однако:
В связи с чем, лучше проинструктировать Qemu чтобы она сообщила в гостевую об имеющемся выравнивании в 4 МБ. Тогда ядро гостевой ОС не будет отправлять дискарды которые невозможно выполнить в RBD.
К сожалению, libvirt напрямую не может указать это для каждого диска персонально. Но есть костыль:
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<qemu:commandline>
<qemu:arg value='-global'/>
<qemu:arg value='scsi-hd.discard_granularity=4194304'/>
</qemu:commandline>
...
<disk type='network' device='disk'>
<!--
detect_zeroes='on'
https://libvirt.org/formatdomain.html:
NB enabling the detection is a compute intensive operation,
but can save file space and/or time on slow media.
А ещё это может повлиять на бенчмарки в стиле dd if=/dev/zero ...
fio использует случайный паттерн.
-->
<driver name='qemu' type='raw' cache='writeback' discard='unmap'/>
...
</disk>
</domain>
Important
xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'
крайне важен.
Без этой строки <qemu:commandline>
будет проигнорирован. Проверить
можно повторно отредактировав описание ВЫКЛЮЧЕНОЙ виртуальной машины
virsh edit some-domain
Данный фрагмент будет работать только для virtio-scsi. Для IDE аналогично, но мне неизвестно как :).
(Пример по ссылке http://docs.ceph.com/docs/master/rbd/qemu-rbd похоже что устарел и не работает)
Для справки есть ещё такие параметры:
logical_block_size
physical_block_size
min_io_size
opt_io_size
Important
Discard будет работать только для виртуальных дисковых интерфейсов IDE и
virtio-scsi. Не путайте virtio и virtio-scsi -- это два совершенно разных
интерфейса. virtio устарел и более не развивается. В гостевой ОС
virtio-scsi выглядит как /dev/sd*
, а virtio как /dev/vd*
.
Их всех можно посмотреть командой lsblk
в гостевой ОС чтобы удостовериться,
что виртуальная машина настроена правильно
(DISC-GRAN
равен размеру чанка в RBD):
$ lsblk -D NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO sda 0 4M 1G 0 ├─sda1 4176896 4M 1G 0 ├─sda2 3145728 4M 1G 0 └─sda3 3145728 4M 1G 0 $ lsblk -t NAME ALIGNMENT MIN-IO OPT-IO PHY-SEC LOG-SEC ROTA SCHED RQ-SIZE RA WSAME sda 0 512 0 512 512 1 deadline 128 128 2G ├─sda1 0 512 0 512 512 1 deadline 128 128 2G ├─sda2 0 512 0 512 512 1 deadline 128 128 2G └─sda3 0 512 0 512 512 1 deadline 128 128 2G
Чтобы это заработало полностью, нужно не только убедиться что эта возможность появилась на блочном уровне в гостевой ОС, но и чтобы гостевая ОС использовала эту функцию.
fstrim -v -a
. Вручную, либо по расписанию (раз в неделю). Рекомендуется. не уверен, но в Ubuntu, по-моему, работает из коробки.- Опции для SWAP-разделов. TODO: расписать какие именно. Есть первичный дискард перед подключением, есть включение дискарда во время работы.
- Есть опции при монтировании различных ФС чтобы выполняли discard для данных которые стали ненужными (после удаления файлов)
- Команда
blkdiscard
для очистки всего устройства либо раздела или тома LVM.
Warning
Говорят, что опции монтирования и аналогичные опции для SWAP-раздела понижают производительность. С другой стороны, массивный fstrim по расписанию может дать непредвиденные проседания IO в гостевой ОС.
TODO: всё работает из коробки как-то само собой. На старых версиях можно включить через реестр. Как посмотреть ? Как форсировано прочистить ?
Настоятельно рекомендуется установить дополнения в гостевую ОС:
- https://fedoraproject.org/wiki/Windows_Virtio_Drivers
- https://www.linux-kvm.org/page/WindowsGuestDrivers/Download_Drivers
Иначе придётся довольствоваться только IDE, а это сильно меньшая производительность.
Для более оптимальной работы приложений внутри гостевой ОС можно пометить диск как non-rotational. По-умолчанию, он rotational.
Коммит, который это добавляет: https://github.com/qemu/qemu/commit/070f80095ad5b1143b50d2faffd2b1a84292e00d
Такая возможность есть, начиная с qemu 2.11 и выше. Настраивается аналогично
discard_granularity
. Нужно выставить
scsi-hd.rotation_rate=1
и scsi-block.rotation_rate=1
(на всякий случай)