понедельник, 30 ноября 2009 г.

Реанимационная машина

Уже достаточно давно известно, что запустить Solaris в виртуальной машине на Windows полностью на ZFS можно.

Теперь - сюрприз.

Виртуальная машина может оказаться реанимационной.

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

Удивлены?

Я тоже был нешуточно удивлен.

"Удивился Бэтмен, удивилась Красная Шапочка - но больше всех удивился Человек-Невидимка."

Понятное дело, что производительность важней всего - но когда файловая система гостевой ОС может в любой момент - буквально в любой момент! - развалиться вдребезги, это как-то заставляет поежиться. Даже с учетом того, что лично я бы виртуальной системе кроме девелопмента в принципе ничего важного не доверил бы.

И все бы ничего было - да вот не со всеми файловыми системами такое прокатывает.

Итак, я цитирую буквально пункт 11.1.3 Troubleshooting от Sun (!) VirtualBox:

If desired, the virtual disk images (VDI) can be flushed when the guest issues the IDE FLUSH CACHE command. Normally these requests are ignored for improved performance.

То есть, это нормально, что виртуальная система игнорирует запросы гостевой ОС на сброс кэша.

А теперь - как это себя ведет?

Плохо ведет.

Если гостевая система стоит на ZFS - конец ей может наступить буквально в любой момент. Проверено на кошечках.

От безобидных нарушений контрольных сумм - до разрушений пулов целиком, корневых и нет - в любое время. Без видимых причин.

Зададимся вопросом - почему?

Транзакционная семантика ZFS, COW, ARC и ZIL играют тут в комбинации злую роль. Нет, это не баг ZFS. Это баг в башке разработчиков систем виртуализации.

Объясняю.

ZFS в принципе не исходит из предположения, что может находиться не непосредственно на физическом устройстве.

Соответственно, когда происходит атомарная запись уберблока, группа транзакций отправляется командой на сброс на виртуальный диск, туда же отправляется команда на запись ZIL. Хост игнорирует эти команды, однако все их он игнорировать не может, поэтому метки ZFS, содержащие уберблоки, попадают в конечном итоге на диск - но при следующем чтении выясняется, что данные, реально содержащиеся на диске и то, что показывают уберблоки - не совпадают!

Особенно устрашающе это выглядит в случае жесткого перезапуска или отключения виртуальной машины - десятки тысяч ошибок контрольных сумм! Несохраненные записи все полностью потеряны, скруббинг пытается эти несоответствия восстановить, пул находится в деградированном состоянии, ошибки прибывают с каждой записью. Если пул корневой - отказ вплоть до невозможности стартовать систему. Внезапно оказываются разрушенными метаданные системных файлов, происходят мнимые повреждения файлов баз - как результат, БД немедленно обрушиваются.

В трех случаях из четырех скруббинг восстанавливает данные. Если есть зеркала - перманентный ресильверинг почти всегда поддерживает пулы в полуживом состоянии. Самое интересное - команда zpool clear сбрасывает счетчик ошибок, если следом выполнить zpool scrub <пул>;zpool scrub -s <пул>;zpool status -v - ошибки исчезают! Ненадолго. Любая последующая обширная операция записи - и все повторяется.

Замечание: Кстати, попутно одно наблюдение - бэкап пула, сделанный при таких обстоятельствах в попытках сохранить жизнь - нецелостный и не может быть использован для восстановления. Восстанавливается лишь часть данных - в моих экспериментах исключений не было.

Окей, читаем мануал VirtualBox дальше:

11.1.3. Responding to guest IDE flush requests

If desired, the virtual disk images (VDI) can be flushed when the guest issues the IDE FLUSH CACHE command. Normally these requests are ignored for improved performance. To enable flushing, issue the following command:

VBoxManage setextradata VMNAME
"VBoxInternal/Devices/piix3ide/0/LUN#[x]/Config/IgnoreFlush" 0

The value [x] that selects the disk is 0 for the master device on the first channel, 1 for the slave device on the first channel, 2 for the master device on the second channel or 3 for the master device on the second channel. Only disks support this configuration option. It must not be set for CD-ROM drives.

Note that this doesn't affect the flushes performed according to the configuration described in 11.1.2. Restoring the default of ignoring flush commands is possible by setting the value to 1 or by removing the key.

Оказывается, нужно всего-то установить два внутренних параметра.

Что они означают? Они модифицируют установки драйвера виртуального контроллера IDE (нативного для VirtualBox) в режим, запрещающий игнорирование запросов IDE FLUSH.

То есть, теперь все должно быть в ажуре - правда, производительность немного упадет (а может, и не немного - но нам-то пофигу, разрушение пулов гораздо хуже!), но записи будут выполняться как ожидается.

Серия экспериментов показала, что данный параметр работает лишь для контроллеров PIIX3. Поддерживаемые VirtualBox контроллеры PIIX4, ICH6, SATA и SCSI - игнорируют данную установку и ZFS на них разлетается в клочья в любой момент. (Ну, может, я не знаю правильного синтаксиса команд для них - но ни одна попытка не была успешной. Я очень хотел оставить Солярис на виртуальных SCSI-дисках ;). Самое неприятное - нигде на форуме VirtualBox я не нашел даже намека на данный issue.).

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

VBoxManage.exe getextradata pegasus enumerate

VBoxManage setextradata pegasus "VBoxInternal/Devices/piix3ide/0/LUN#0/Config/IgnoreFlush" 0
VBoxManage setextradata pegasus "VBoxInternal/Devices/piix3ide/0/LUN#3/Config/IgnoreFlush" 0

VBoxManage setextradata vader "VBoxInternal/Devices/piix3ide/0/LUN#0/Config/IgnoreFlush" 0

Причем проблема была решена полностью, раз и навсегда.

Да, производительность снизилась. Начало ощущаться наличие слоя хоста под файловыми системами гостевой ОС. Но, по крайней мере, прекратились неожиданные массированные разрушения метаданных.

Все ли виртуализационные среды имеют такую неожиданную и милую особенность?

Я не тестировал их все без исключения - это не было и не будет моей целью - но предполагаю, что таким поведенческим свойством не обладают гипервизоры (по определению) и Solaris Containers (Zones). Сильно подозреваю, что чуть больше половины сред виртуализации имеют такую же бомбу под желудком у гостевых ОС.

Я еще раз подчеркиваю - данная проблема не баг ZFS. ZFS не обязана считать, что ее запрос на сброс данных из памяти на диск может быть и будет проигнорирован. В данном случае ее поведение соответствует некачественным физическим дискам. И никакая избыточность не может скомпенсировать постоянно сыплющиеся ошибки контрольных сумм.

Кстати, когда происходят непрерывные попытки восстановления - загрузка процессоров возрастает феерически. Идут непрерывные операции ввода-вывода, гостевая система (вместе с хостом) начинают резко тормозить. Иногда доходит до автоматического старта ресильверинга.

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

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

А еще лучше - откажитесь от использования виртуальных сред. Право же, откажитесь.

Применение их без крайней на то необходимости - действительно крайней! - дурной тон.

"- Ты еще винограду сверху положи! - сказала Гелла, пихая Бегемота локтем".