| ||
Современный Linux-сервер: как планировать дисковые ресурсы
Алексей Барабанов
Опубликовано в 1 и 2 номерах журнала "Системный администратор" за 2006 год.
Подписку можно оформить в любом почтовом отделении связи (
Роспечать - индексы 20780, 81655, Пресса России - 87836) или через
альтернативные способы подписки.
От того, насколько правильно будет учтен и cпрогнозирован рост данных, размещенных на создаваемом сервере, зависит в самом прямом смысле срок "жизни" самого сервера! Но можно не заниматься математическим предсказанием увеличения объема информации в сети, а использовать технологии хранения, допускающие оперативное масштабирование и резервирование.
Большинство из представленных далее положений и рекомендаций прошли многолетнюю проверку практикой. Но тем не менее не надо все изложенное считать жесткой схемой. Это всего лишь одно из мнений. Воспринимите статью как попытку упорядочить подход и поиск общих путей решения проблемы планирования дисковых ресурсов. И задача эта, ранее в эпоху магнитных дисков типа RK для PDP-11 решаемая всегда очень просто и однозначно, а сейчас - уже с привлечением всего разнообразия современных технологий, далее будет лишь эволюционировать в сложности и многообразии подходов. Поэтому эпитет "современный" в названии надо читать как соответствующий настоящему уровню развития. Выберем для работы универсальный дистрибутив, например, SuSE Linux 10.0 выпуска конца 2005 года, который и примем за эталон современности. Далее рассмотрим, что нам сейчас предлагается и какой сложности выбор предстоит сделать каждому при создании нового сервера.
Постановка задачи
Прежде всего зададимся вопросом, в чем цель действий, производимых в процессе разметки дисковых устройств. Нужны ли вообще все эти "страдания молодого Вертера", если каждый дистрибутив, и SuSE в том числе, предлагает в процессе установки выполнить автоматическое разбиение? Как определить критерии оценки правильности решения о типе и способе обустройства дисковых ресурсов сервера? Определим нашу цель так: правильным будет такой способ, который в дальнейшем цикле эксплуатации сервера позволит без привлечения избыточных ресурсов провести как комплекс работ по повышению отказоустойчивости, по увеличению емкости, так и, наконец, провести модернизацию операционной системы или миграцию сервера на иное оборудование. Это, так сказать, программа-максимум. Совсем не обязательно, что все это предстоит. В моей практике много таких серверов, которые работают до полного износа оборудования (более 5 лет) без каких-либо модернизаций. Но целью выбора оптимальной структуры дисковой системы поставим именно удовлетворение перечисленных критериев. Прокомментируем их.
Во-первых, что такое цикл эксплуатации сервера. Будем считать таковым срок от введения сервера в строй до его демонтажа, или до модернизации (upgrade) операционной системы или аппаратного обеспечения. Первое понятно, второе обосную. Поскольку все, что далее описывается, относится к области профессиональной деятельности, то всякая работа имеет денежный эквивалент, и экономия средств принимается одним из главных критериев любой профессиональной деятельности. Так и здесь. Модернизация производится не из-за вдруг возникшей тяги системного администратора к новизне, а потому что в старой версии или на старом оборудовании сервер далее работать не может. То есть несоответствие стало столь существенным, что решено потратить средства на модернизацию. Ну а если так, то существенные изменения позволяют считать сервер после модернизации уже другим и соответственно этому начать отсчет нового цикла, тем более что и операционная система, и оборудование сервера сами по себе имеют жизненный цикл, который нецелесообразно превышать.
Во-вторых, зачем нужно увеличение отказоустойчивости? Почему при вводе сервера в строй это не считали необходимым, а вот со временем вдруг озаботились? Будем считать, что с увеличением срока эксплуатации возрастает объем внутренних данных сервера и тем самым увеличивается его информационная и абсолютная ценность.
В-третьих, после вышесказанного совершенно очевидно, что возрастание внутренних данных приводит к необходимости увеличения емкости хранения рано или поздно.
И, в-четвертых, модернизация сервера или его миграция на иное оборудование является неотвратимой закономерностью, если только компания-заказчик, где сервер работает, не предполагает разориться вместе с завершением эксплуатации сервера. Поэтому задумываться о том, какой ценой будет производиться модернизация, надо сразу при "закладке" сервера.
Перечислив положительные качества, не забудем упомянуть и отрицательные - те, что обозначены в формулировке как "избыточные ресурсы". Избыточным будем считать все, что привлекается лишь для совершения самой операции увеличения, улучшения или модернизации. Например, если для увеличения дискового пространства потребуется не только подключить новый диск, но еще и придется выкинуть старый, то такой нескомпенсированный обмен надо считать "избыточным ресурсом". Также избыточными будем считать все траты на подобные операции. Например, если модификацию можно осуществить без перерыва в работе, то это идеал, в противном случае - нет. А на практике там, где обсуждаются не идеальные, но реальные условия, чем меньше ресурсов потребуется для проведения операции, тем лучше.
Резюмируем вышесказанное. Во всех технологических выборах следует предпочитать те способы и методы, которые снизят стоимость дальнейших преобразований и модификаций. Вот такой получается "восточный дракон", кусающий собственный хвост.
Теперь, когда цель ясна и определена, обсудим сами устройства хранения и те технологии, что предлагаются на выбор "из коробки" при сегодняшнем уровне развития в SuSE Linux 10.0.
Иерархия уровней представления дисковых данных
Современный Linux-сервер является многофункциональным устройством, работающим в сети. Если абстрагироваться от его прикладного назначения и попытаться представить весь спектр возможных уровней и способов доступа к данным, то получится большая схема, напоминающая многослойный пирог. Иерархию сетевого доступа к данным тоже принято изображать в виде многоуровневой схемы инкапсуляции. Только если сетевая модель уже давно канонизирована, то схема вложенности уровней доступа к дисковым данным не имеет привычного вида, что допускает вольности в ее представлении. Итак, если все доступные в SuSE Linux 10.0 технологии попытаться уложить в единую схему, отражающую их взаимосвязь и взаимодействие, то получится нечто вроде изображенного на рис. 1.
Рисунок 1. Схема иерархии уровней представления дисковых данных
Прокомментирую эту схему. Хотя все аббревиатуры и обозначения являются традиционными в Linux, расшифрую их:
n DISK - физическое дисковое устройство;
n MD - так называемый multiple device или программный RAID;
n LVM - виртуальный диск по технологии Logical Volume Manager;
n DRB/iSCSI - сетевой диск по соответствующей технологии;
n EXT3... - уровень представления, соответствующий файловым системам;
n NFS... - уровень представления, соответствующий сетевым файловым системам и протоколам, используемым для организации сетевого доступа к файлам.
Каждый окрашенный прямоугольник отделяет регион, включающий технологии соответствующей категории. Их три:
n SAS - устройства, физически подключаемые к серверу;
n SAN - блочные устройства, подключаемые по сетевым интерфейсам;
n NAS - файловые системы, доступные через сеть.
Все перечисленные на схеме технологии могут быть задействованы в пределах одного серверного блока или, точнее, одного хоста. Безусловно, необходимость их использования должна диктоваться областью применения. И вот здесь для нашего обсуждения будет важно то, какую гибкость в настройке и модернизации обеспечивают все изображенные элементы. Для этого рассмотрим подробнее ту же схему, но с точки зрения операций и их взаимодействия по пути эскалации технологических уровней.
Будем далее исходить из предположения, что все используемые технологии применяются к одному физическому дисковому устройству. Это не исключает в дальнейшем использования дополнительных дисков, но задает более жесткие рамки вариантов выбора. Например, под MD в дальнейшем будет пониматься исключительно RAID1.
Диаграммы переходов
Для того чтобы определить ключевые, или, в нашей терминологии, "дорогостоящие" технологические элементы, построим диаграмму переходов в процессе возможных настроек от самого нижнего уровня DISK до самого верхнего NFS... Полученная диаграмма представлена на рис. 2.
Рисунок 2. Диаграмма настроек
Узлы соответствуют технологическим уровням представления данных, а стрелки обозначают возможные направления в процессе настройки сервера. Нумерация узлов проставлена в порядке самого длинного маршрута настроек. Все очевидно и не нуждается в пояснениях. А вот теперь повернем стрелки в обратном направлении! Представим, что некий шаг настройки оказался ошибочным, но решение о его отмене пришло лишь в процессе эксплуатации, спустя некоторое время. Например, в процессе установки были последовательно пройдены этапы 1 DISK, 5 EXT3..., 6 NFS.... И спустя некоторое время появилась необходимость перевести работающую систему под LVM. То есть надо последовательно перевести сервер по диаграмме настроек 6 NFS..., 5 EXT3... и затем в узел 3 LVM. После чего снова в поступательном движении по диаграмме настроек вернуться в узел 6 NFS..., который соответствует полностью работоспособному серверу. Вторую диаграмму назовем диаграммой переделок. В ней все вектора изменили направление на противоположное, и рядом с каждым из них добавился комментарий, оценивающий стоимость переделки. Результат изображен на рис 3.
Рисунок 3. Диаграмма переделок
Итак, все возможные стоимости переделок уложились в четыре градации: потеря сервиса, отключение сервиса, условно возможно, потеря данных. Например, рассмотрим возможные переделки для узла файловых систем EXT3... Во-первых, можно переразметить диск, на котором размещена файловая система - это условно возможная операция, так как на диске должно оставаться свободное место для таких манипуляций. Во-вторых, можно перевести используемый диск в статус RAID1 - это условно возможная операция, так как в случае наличия свободного места в файловой системе для размещения суперблока операцию можно провести "на лету". В-третьих, можно перевести файловую систему под управление LVM - эта операция проводится с потерей данных, так как LVM использует размещение суперблоков в теле рабочих разделов так, что не представляется возможным выделить для этого единое пространство. Ну и, наконец, можно отключить от используемой файловой системы сетевое блочное устройство - эта операция приводит только к отключению самого сервиса и ни к чему более серьезному.
Таким образом, самая серьезная ситуация складывается вокруг переделок, требующих установки LVM. Если подключение RAID или переразметка диска могут быть проведены без резервного копирования всех данных в некоторых случаях, то помещение томов с данными под управление LVM потребует 100% сохранения всей задействованной информации. Здесь можно сделать вывод, что именно LVM является той критической технологией, решение об использовании которой надо принимать на самом раннем этапе планирования дисковых ресурсов.
Таблица операций
Попробуем поместить все данные из диаграмм в таблицу 1. Слева в столбце 1 - исходное состояние, сверху в ряду 1 - конечное, в ячейке на пересечении соответствующих состояний указана операция, переводящая начальное состояние в конечное. Таким образом, в ячейки левой нижней части таблицы, разделенной диагональю, попадут операции переделок и их стоимости, а в ячейки правой верхней части попадут операции настроек.
Теперь в этой таблице голубым цветом по вертикали, то есть в целевых столбцах, выделим технологии, допускающие оперативное масштабирование, и салатным, также по вертикали, - те технологии, что позволяют организовать горячее резервирование по схеме RAID.
Таблица 1. Операции и стоимости
|
DISK |
MD |
LVM |
DRB/iSCSI |
EXT3... |
NFS... |
DISK |
Разбиение диска |
Создание MD и подключение |
Создание LVM и подключение |
Запуск drbd/ iscsid |
Разметка fs и монтирование |
|
MD |
Условно возможна миграция MD на иной раздел диска |
|
Создание LVM и подключение |
Запуск drbd/ iscsid |
Разметка fs и монтирование |
|
LVM |
Условно возможна миграция PV |
Условно возможно перемещение PV внутрь MD |
|
Запуск drbd/ iscsid |
Разметка fs и монтирование |
|
DRB/iSCSI |
Условно возможна миграция раздела DRB/iSCSI |
Условно возможно перемещение раздела внутрь MD |
Невозможно без полного резервного копирования |
|
Разметка fs и монтирование |
|
EXT3... |
Условно возможна миграция FS |
Условно возможно перемещение FS внутрь MD |
Невозможно без полного резервного копирования |
Отключение от сетевого блочного устройства |
|
Запуск nfsd/ smbd |
NFS... |
|
|
|
|
Отключение всех потребителей и остановка сервиса |
|
Если исходить из условия, что необходимо обеспечить масштабирование емкостей в оперативном порядке, то выбор однозначен. Поскольку в предыдущем разделе уже был сделан вывод о том, что технология LVM единственная, которая требует решения о ее применении на самом раннем этапе, то можно сказать, выбор сделан - LVM непременно надо использовать.
Далее, у нас два кандидата для возможного увеличения отказоустойчивости путем горячего резервирования. Безусловно, сравнивать RAID и сетевые блочные устройства просто некорректно. Но в рамках рассматриваемой модели мы не учитываем ничего, кроме возможности перенастроить нужный уровень представления данных и последствий такой перенастройки. И следуя этому принципу, получается, что создание сетевого блочного устройства на основе локального - это лишь запуск соответствующего сервиса, а переключение локально подмонтированного диска на сетевой режим работы без изменения его объема или размещения тоже не представляет особой проблемы. Итак, из двух технологических подходов, MD и DRB/iSCSI, будем самым неудобным в модификации, и поэтому самым "дорогим", считать MD.
На этом этапе можно сформулировать первые принципы планирования дисковых ресурсов.
Принцип 1. Следует, по возможности, переключить все размеченные разделы жесткого диска в режим работы программного RAID, пусть и неполного, что позволит в дальнейшем при необходимости перевести их в режим горячего резервирования.
Принцип 2. Следует, по возможности, объединить все созданные физические тома под управлением LVM - для того, чтобы в дальнейшем, при необходимости, легко манипулировать объемом используемых логических томов.
Обращаю внимание на уточнение "по возможности". Обсуждение этих "возможностей", а также все, что касается стратегии разбиения на разделы, оставим для второй части этой статьи. Сейчас просто учтем эту оговорку и просто попытаемся оценить эффект от следования заявленным выводам, как принципам планирования дисковых ресурсов.
Тестирование
Да, именно так - тестирование. Нет ничего проще, чем оценить издержки использования этих, запасенных впрок, технологических изысков MD и LVM, путем проверки с помощью самого рядового теста файловой системы bonnie, проверяющего символьные и блочные операции чтения-записи, как повлияет на его результаты внесение соответствующих изменений в настройки.
В тестовом компьютере было установлено 1 Гб оперативной памяти. Это не очень "удобный" объем, так как максимальный размер тестового файла в 32-битном режиме составляет 2 Гб, что несколько снижает точность измерений. И поэтому дополнительно были сделаны проверки в 64-битном режиме и с размером тестового файла в 4 Гб. Полученные результаты представлены в таблице 2. В самом левом столбце перечислены операции, на которых проводились измерения, а в самой верхней строке сокращениями обозначены условия тестирования.
Таблица 2. Зависимость скорости доступа от разбиения и типа разметки
|
sda3 |
sda3,md3 |
sda3,md3,lvm |
sda3,md3,amd64 |
sda3,md3,4096 |
sda2,md2 |
Символьная запись |
43891 - 0,96 |
46049 - 1,01 |
47326 - 1,03 |
44301 - 0,97 |
41087 - 0,90 |
48253 - 1,05 |
Блочная запись |
55173 - 0,94 |
60449 - 1,03 |
60397 - 1,03 |
55792 - 0,95 |
49368 - 0,84 |
54367 - 0,93 |
Перезапись |
21288 - 0,99 |
21768 - 1,01 |
21618 - 1,00 |
20570 - 0,95 |
20688 - 0,96 |
21839 - 1,01 |
Символьное чтение |
24281 - 1,07 |
21815 - 0,96 |
21791 - 0,96 |
30829 - 1,36 |
36220 - 1,60 |
21732 - 0,96 |
Блочное чтение |
54047 - 1,01 |
53622 - 1,00 |
53288 - 0,99 |
51793 - 0,97 |
51768 - 0,96 |
54335 - 1.01 |
Опишем их по порядку:
n sda3 - проверка проводится на "чистом" разделе диска, размеченного под ext3;
n sda3,md3 - файловая система размечена поверх половинки "зеркала" RAID1;
n sda3,md3,lvm - раздел, использованный как половинка RAID1, помещен в LVM, и уже поверх него размечена файловая система ext3;
n sda3,md3,amd64 - случай 2, но в режиме 64 бита;
n sda3,md3,4096 - условия как в предыдущем 64-битном варианте, но с размером тестового файла в 4 Гб;
n sda2,md2 - случай 2, но со смещением к начальным областям диска.
Результаты тестов показаны в Кб/сек. Рядом с ними рассчитаны индексы отклонений от средней величины, определенной по первым трем испытаниям. Для наглядности данные таблицы представлены в графическом виде в форме столбчатой диаграммы (см. рис. 4).
Рисунок 4. Зависимость скорости доступа от разбиения и типа разметки
Испытания с 1-го по 3-е определяют то, как влияет использование дополнительных уровней представления данных на скорость работы. Практически отклонения не превышают 5%. Совершенно понятно, что с увеличением числа "слоев" трансляции уровней представления немного подрастает скорость записи и немного снижается скорость чтения. Это объясняется тем, что при записи большее число программных драйверов создает большую массу кеширующих механизмов, и в сравнении с тестом на файле 4 Гб (колонка 5) видно, как увеличение размера в 2 раза довольно существенно снижает результаты по записи. А вот в процедуре чтения данных увеличение числа уровней представления лишь увеличивает цепочку запросов, если данные не сохранены в кеше, и, значит, немного снижает скорость. Сравнение результатов тестирования, произведенного на другом разделе диска (колонка 6), с аналогичным по условиям (колонка 2) дает основания считать результаты последней достаточно достоверными, так как за небольшим исключением скорости обмена данными схожи. Здесь очень интересно отметить, что переход на 64-битную платформу показывает резкий прирост скорости символьного чтения. Вероятно, из-за более эффективного использования индексов в кеше. Безусловно, увеличение числа прогонов, изменение соотношения размера тестового файла к объему оперативной памяти и другие приемы, возможно, дали бы более стабильные результаты, но, скорее всего, общий уровень показателей не изменился бы существенно. Можно считать, что уровень отклонения не превысит 5% и в реальной работе. Поскольку, как видно по результатам, выигрыш в записи сопровождается потерями в чтении, то никакого существенного ухудшения работы системы такой тюнинг не принесет в общем случае.
Как подтверждение правильности сделанных здесь выводов приведем тот факт, что RHEL (серверная версия Red Hat Linux) по умолчанию устанавливает все данные, кроме размещаемых в каталоге /boot, именно в раздел под управлением LVM. Даже swap помещается на раздел LVM для того, чтобы можно было в дальнейшем манипулировать его объемом. Иначе говоря, преимущества технологичности сопровождения создаваемого сервера с лихвой окупают трудноуловимые "жертвы" производительности.
Теперь, уверившись в правильности предложенных выше принципов, попробуем применить их на практике.
Практический рецепт миграции на RAID1
Внимание! Используйте описанную ниже технологию на свой страх и риск. Автор не несет ответственности за возможные повреждения данных и настоятельно рекомендует выполнить процедуру резервного сохранения критически важной информации. Далее все описано применительно к SuSE 10.0. Не забудьте сделать поправку под актуальную платформу.
Как было ранее заявлено, надо стремиться к переводу разделов под RAID и LVM с самого раннего этапа. При этом вовсе не обязательно, чтобы в системе было необходимое количество дисков для построения RAID или присутствовала сложная иерархия устройств, управляемая LVM. Вовсе нет! Все должно быть применимо даже к единственному жесткому диску. В отношении LVM проблем нет, даже если диск один. А вот RAID1, технологически работающий даже на одном диске, в процессе инсталляции системы с использованием стандартных установщиков не удается так просто включить в работу. Для исправления этой проблемы применяются схемы с миграцией готовой системы с обычных разделов на второе дисковое устройство, как на половинку "зеркала". То есть возникает та самая аппаратная избыточность, которой мы стремились избежать. Но можно воспользоваться тем, что суперблок MD записывается в конец используемого раздела, и с точки зрения файловой системы структура раздела более не меняется. Таким образом, если на этапе установки разместить систему на некотором разделе, а потом уменьшить объем файловой системы так, чтобы в полученном "хвостике" уместился бы суперблок RAID1, то при такой трансформации данные никак не должны пострадать. Проверим это.
В работе используем раздел /dev/sda3, размеченный как ext3, но можно использовать любую файловую систему, допускающую изменение размера. Все манипуляции надо производить над немонтированным разделом. Если трансформируется корневой раздел, то надо использовать или спасательный диск, или альтернативную загрузку. Итак, вот разметка диска до начала работ:
# fdisk -l /dev/sda
Disk /dev/sda: 120.0 GB, 120034123776 bytes
255 heads, 63 sectors/track, 14593 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/sda1 1 131 1052226 82 Linux swap / Solaris
/dev/sda2 132 1377 10008495 fd Linux raid autodetect
/dev/sda3 * 1378 2683 10490445 83 Linux
Внутри раздела уже создана файловая система.
# fsck /dev/sda3
fsck 1.38 (30-Jun-2005)
e2fsck 1.38 (30-Jun-2005)
/dev/sda3: clean, 117054/1311552 files, 720522/2622611 blocks
По умолчанию использован блок с размером 4 Кб. Уточнить действительный размер можно с помощью утилиты dumpe2fs с ключом -h. Теперь есть возможность сразу рассчитать размер и положение суперблока MD, как указано в usr/include/linux/raid/md_p.h и уменьшить размер файловой системы соответственно. После подстановки в формулу для расчета переведем все числа, указанные в блоках, в шестнадцатеричные:
Размер устройства MD = (размер физического устройства & ~ (размер суперблока -1) - размер суперблока = 2622611 & ~(15) -16 == 0x280493 & ~(0xF) - 0x10 = 0x280480 = 2622592 блоков.
Полученное значение составит размер полученного диска MD. Начиная с указанного блока будет размещаться суперблок MD длиной 64 Кб. Но можно пойти по самому примитивному пути и заставить систему сообщить нужный размер, как мы и сделаем далее.
Создадим RAID1 из раздела /dev/sda3. На предупреждение о том, что внутри уже найдена размеченная файловая система, не обращаем внимания - мы же знаем, что делаем!
# mdadm -C /dev/md3 -l 1 -n 2 /dev/sda3 missing
mdadm: /dev/sda3 appears to contain an ext2fs file system size=10490444K mtime=Mon Jan 9 01:08:28 2006
Continue creating array? y
mdadm: array /dev/md3 started.
Теперь проверим целостность файловой системы внутри полученного MD. Утилита должна указать на несоответствие размера раздела и размера файловой системы, после чего проверку следует прервать:
# fsck /dev/md3
fsck 1.38 (30-Jun-2005)
e2fsck 1.38 (30-Jun-2005)
The filesystem size (according to the superblock) is 2622611 blocks
The physical size of the device is 2622592 blocks
Either the superblock or the partition table is likely to be corrupt!
Abort<y>? yes
fsck.ext3 /dev/md3 failed (status 0x8). Run manually!
Полученный из сообщения "физический" размер в 2622592 блока по 4 Кб, который, кстати сказать, совпадает с заранее рассчитанным, нужно будет использовать при коррекции размера файловой системы. Но предварительно выполним проверку файловой системы на /dev/sda3, так как иначе утилита resize2fs откажется работать.
# e2fsck -f /dev/sda3
e2fsck 1.38 (30-Jun-2005)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sda3: 117054/1311552 files (0.5% non-contiguous), 720522/2622611 blocks
А вот теперь скорректируем размер самой системы:
# resize2fs /dev/sda3 $(( 2622592 * 4 ))K
resize2fs 1.38 (30-Jun-2005)
Resizing the filesystem on /dev/sda3 to 2622592 (4k) blocks.
The filesystem on /dev/sda3 is now 2622592 blocks long.
Для контроля снова проверим целостность файловой системы на /dev/md3:
# e2fsck -f /dev/md3
e2fsck 1.38 (30-Jun-2005)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/md3: 117054/1311552 files (0.5% non-contiguous), 720522/2622592 blocks
Если эта система была корневой и/или использовалась в процессе загрузки, то надо внести дополнительные правки в содержимое файлов, управляющих загрузкой системы.
Монтируем новый раздел:
# mount /dev/md3 /mnt
# mount | grep md3
/dev/md3 on /mnt type ext3 (rw)
Сначала исправим /etc/fstab, так как изменилось имя устройства, использованного для монтирования раздела:
# perl -i.orig -p -e 's,/dev/sda3,/dev/md3,g' /mnt/etc/fstab
# cat /mnt/etc/fstab | grep md3
/dev/md3 / ext3 acl,user_xattr 1 1
И для того чтобы инициировать автоматическое детектирование RAID в процессе загрузки системы, поправим тип раздела (для краткости используем неинтерактивную форму):
# fdisk /dev/sda <<EOT
t
3
fd
w
EOT
Перечитаем таблицы разметки диска:
# partprobe
Если обновленный раздел используется в качестве корневого, то есть его имя передается загрузчиком ядру, то надо поправить меню загрузки. В нашем случае /boot размещен на модифицируемом разделе. Здесь принимается без объяснений то, что следует использовать загрузчик grub. Обоснование этого, а также и многих других правил, оставим для второй части статьи. Итак, проводим такую же правку, как и с /etc/fstab:
# perl -i.orig -p -e 's,/dev/sda3,/dev/md3,g' /boot/grub/menu.lst
Теперь все готово к работе. Надо только не забыть, что initrd должен "понимать" тип нового раздела. И если это не так, то следует пересобрать initrd, указав в /etc/sysconfig/kernel среди имен модулей в параметре INITRD_MODULES дополнительно raid1.
Напоследок, если возникают трудности с загрузкой, то продемонстрируем протокол установки загрузчика из модифицированного раздела.
# grub <<EOT
> root (hd0,2)
> setup (hd0)
> quit
> EOT
GNU GRUB version 0.96 (640K lower / 3072K upper memory)
...
grub> root (hd0,2)
Filesystem type is ext2fs, partition type 0xfd
grub> setup (hd0)
Checking if "/boot/grub/stage1" exists... yes
Checking if "/boot/grub/stage2" exists... yes
Checking if "/boot/grub/e2fs_stage1_5" exists... yes
Running "embed /boot/grub/e2fs_stage1_5 (hd0)"... 15 sectors are embedded...succeeded
Running "install /boot/grub/stage1 (hd0) (hd0)1+15 p (hd0,2)/boot/grub/stage2 /boot/grub/menu.lst"... succeeded
Done.
grub> quit
Таким образом, была осуществлена трансформация "на лету". Условием ее успешного выполнения стало то, что в файловой системе было свободно не менее 2622611-2622592 = 19 блоков или 76 Кб. Для повторения этого "трюка" в другом Linux, не в SuSE, или с другим типом файловой системы надо обеспечить наличие необходимых для трансформации файловой системы утилит.
Вопросы выбора типа файловой системы, способа распределения данных по разделам, организация процесса загрузки и многое другое, что осталось за рамками рассмотрения, будут освещены во второй части статьи.
Планирование дисковых ресурсов, выполняемое на этапе закладки сервера, позволит значительно сократить возможные издержки в случае наступления непредвиденных ситуаций. Для этого надо подойти к решению многих привычных вопросов с учетом возможных последствий.
В первой части обсуждения данной темы [1] на основании анализа эксплуатационного цикла сервера были выдвинуты два принципа (использовать всегда RAID1 вместо обычных разделов диска и перевести максимум объема под управление LVM), исходя из которых, предлагалось производить планирование дисковых ресурсов. Но существует еще одна, и не последняя, цикличность в работе серверов, как и любых компьютеров, которую надо принять во внимание - процесс загрузки. Это неизбежная фаза начинается сразу после включения питания и завершается после выхода системы в рабочий режим. Ключевую роль в ней играет загрузчик. Необходимость существования независимого от операционной системы загрузчика обусловлена именно тем, что надо согласовать уровни представления систем хранения данных с точки зрения BIOS и того, как их "представляет" ядро ОС. Из двух крайностей, поместить BIOS в ядро или само ядро в BIOS, был выбран технологический компромисс - загрузчик. Обсудим подробнее.
Процесс загрузки
Загрузка - это последовательность передачи управления от BIOS оборудованию, которая включается в процессе аппаратной инициализации, к ядру операционной системы. Процесс обслуживает упомянутый "загрузчик" (на диаграмме - LOADER). Существуют два типа загрузки - сетевая и локальная. Сетевая загрузка осуществляется только с помощью внешних серверных ресурсов, поэтому опустим её рассмотрение. Итак, далее обсуждаем только загрузку с SAS-устройств.
В начальный момент времени BIOS, собравший всю доступную информацию о физически подключенных устройствах, производит в определенном порядке перебор систем хранения и поиск на них загрузчика. Управление будет передано первому подходящему. BIOS доступна лишь физическая структура устройств. Все, на что он "способен", - это загрузить первый сектор, проверить наличие специальной сигнатуры и передать управление полученному коду. Главные ограничения: код размещается в объеме сектора (512 байт), выбирается всегда лишь первый сектор. Поскольку BIOS никак не учитывает существование разметки дисков, то загрузчик смело может занимать 510 байт (512 - сигнатура).
Теперь обсудим конечную точку работы загрузчика (но не конечную точку загрузки!). Загрузчик "должен" точно так же, как чуть раньше это сделал BIOS, найти следующий программный код, то есть ядро ОС, загрузить его, проверить корректность и передать управление. Естественно, расположение ядра операционной системы и всех необходимых для загрузки файлов зависит от типа и свойств самой ОС. Хотя в заголовок статьи вынесено утверждение, что рассматривается именно Linux, но это не значит, что вместе с ним на дисковых ресурсах не будут располагаться и другие ОС.
Итак, получили "разрыв" представлений. Воспользуемся все той же диаграммой переходов в процессе настройки для иллюстрации (рис. 1).
Рисунок 1. Видимость уровней представления на разных стадиях загрузки
Синим цветом на рисунке обозначено то, что "может видеть" BIOS, а зеленым то, что "должен видеть" загрузчик. Между узлами 2 MD и 5 EXT3... изображена двунаправленная стрелка. Как было показано в первой части статьи [1], логическая структура файловой системы, положенной поверх RAID1, не меняется. Благодаря этому можно считать, что если загрузчик обязан "понимать" файловую систему, то он будет "понимать" её, размещенную поверх MD. Но это и максимум его "понятливости". Иначе говоря, на настоящий момент не представляется возможным разместить всю систему целиком на логических томах LVM. Приходится часть, необходимую для загрузки, все-таки выносить за пределы этой столь удобной системы управления томами данных.
Это утверждение иллюстрируется все тем же RHEL, в котором файлы, участвующие в загрузке, размещаемые традиционно в /boot, записываются во внешний по отношению ко всей системе том, который не подключается в управление LVM.
Вывод. Хотя очень правильно все, что можно, внести внутрь LVM, но приходится мириться с существованием разделов, проинициализированных в последовательности 1 DISK, 2 MD, 3 EXT3... И следующий вопрос: достаточно ли одного только /boot, как считают в компании RedHat, или все-таки надо нечто посущественней? Для этого разберем, как работает загрузчик.
Работа загрузчика
Linux в силу своей открытости стал весьма консервативной системой, так как каждая его компонента подвергается очень подробному анализу на адекватность назначению. Хотя вместе с дистрибутивом SuSE поставляются четыре загрузчика (Lilo, Grub, Syslinux, Loadlin), но в качестве стандартных, как правило, использовались только два - Syslinux и Grub. Долгое время они развивались, конкурируя друг с другом, и лишь недавно определилось, что будущее именно за Grub. Объясню, почему так.
Опять возвращаемся к рис. 1. Посмотрите, загрузчик не обращается к физическим дисковым устройствам, он "смотрит" только на файловые системы. Именно это свойство, а не что-то иное определило преимущества проекта Grub. Дело в том, что загрузчик должен предоставить оператору выбор путей загрузки. И Grub считывает файл меню, свои кодовые файлы и файлы загружаемых систем, пользуясь только собственным драйвером файловой системы и никак не привязываясь к физическим константам устройств. Lilo, являсь исторически более ранним творением, не придерживался такой концепции, почему и вынужден был уступить.
Внимание: изначально в дистрибутиве SuSE 10.0 поставляется Grub версии 0.96. Этот релиз содержит ошибку. В обновлениях предлагается версия 0.97. В дальнейшем будет применяться именно эта, обновленная версия.
Рассмотрим, как работает Grub. Для этого обратимся к рис. 2, где наглядно представлен процесс установки и загрузки Grub. Обсуждение будем вести в терминологии Grub.
Рисунок 2. Работа загрузчика Grub
Итак, в самом начале BIOS считывает код загрузчика из первого сектора диска (1 на рисунке). 512 байт явно недостаточно, чтобы разместить там драйвер файловой системы. Эта часть загрузчика называется stage1. Её назначение - загрузить stage1_5 - специальную фазу, содержащую драйвер файловой системы. Проблема в том, чтобы добиться однозначности размещения этой фазы по отношению к stage1. Это достигается путем записи данной компоненты на "нулевую" дорожку загрузочного устройства, т.е. вслед за первым сектором, содержащим stage1. В режиме LBA (диски актуальных для серверов ёмкостей в другом режиме просто не работают), на дисковом устройстве размещается 63 сектора в дорожке. То есть уровень "интеллекта" stage1_5 может быть повышен до 30 Кб. Для работы с файловой системой ext3 хватает чуть более 8Кбайт. Иначе говоря, резервы эволюции у проекта Grub еще есть.
После подключения stage1_5 (2 на рисунке) загрузчик уже "умеет" читать выбранную файловую систему и, значит, "может" найти все недостающее для его работы. А именно: основную свою компоненту stage2 (3 на рисунке) и файл, содержащий меню, menu.lst (4 на рисунке). Все! Теперь в памяти компьютера работает полностью собранный загрузчик, который "пользуется" возможностями файловых систем для поиска всех указанных в меню файлов. Таким путем обеспечивается независимость первых фаз загрузки от конкретного размещения файлов внутри файловой системы. То есть, если модифицировать stage2, или изменить menu.lst, или какие-то из загружаемых файлов, описанных в меню, то при следующей загрузке stage1+stage1_5, как ни в чем не бывало, загрузят новые файлы.
На рис. 2 показано, как реальное разбиение жесткого диска "понимается" загрузчиком. В процессе установки надо указать корень, где размещены все файлы загрузчика. В нашем случае это делается командой root (hd0,1). Установщик определяет тип файловой системы и согласно этому подбирает следующую фазу - e2fs_stage1_5. И далее остается лишь указать, куда записывать stage1+stage1_5. Это производится командой setup (hd0). После чего нужные компоненты записываются на нулевую дорожку указанного устройства, и в них жестко прошивается размещение и названия остальных файлов stage2 и menu.lst, иначе говоря, первая команда root (hd0,1), указывающая на корень загрузчика. Заметим, что корень, в котором размещается загрузчик, может, и даже очень часто, не совпадать с корнем самой загружаемой системы.
Определим здесь минимум-миниморум того, что должно быть размещено на разделе загрузки, (hd0,1) в нашем случае. Если мы обсуждаем загрузку Linux-системы, то на этом разделе, кроме уже перечисленных файлов загрузчика, нужно разместить ядро и initrd, данные для инициализации виртуального диска, подключаемого в процессе загрузки ядра системы. Примерно так и рассуждают в компании RedHat, когда выделяют /boot в качестве раздела загрузки. Теперь обсудим реальное положение дел.
Эксплуатационные фазы
Давайте мысленно вернемся к исходным целям вырабатываемых механизмов и способов разметки. Итак, главное - добиться условий для манипуляций с логическими томами и размещенными на них файловыми системами таких, чтобы максимально насколько возможно оставлять сам сервер в работоспособном состоянии, чтобы для обслуживания не требовалось физического вмешательства (поскольку это несовместимо с автоматизацией и вообще с логикой работы вычислительных систем). Если, как это предложено все в том же RHEL, корневая файловая система размещена на логическом томе LVM, то для преобразований надо будет сначала отмонтировать корень. Конечно, можно просто заявить, что это не понадобится, так как всегда можно к самому корню подмонтировать нужный объем, взятый все с того же LVM. Примем пока это объяснение. А если возникает необходимость в обновлении используемой системы? А если надо выполнить в системе настройку, результат которой может оказаться не на 100% успешным? Тогда возникает требование иметь на SAS-устройстве второй экземпляр системы со своим независимым корнем. И, загрузив этот второй экземпляр системы, можно выполнить все перечисленные операции.
Состояние сервера, работающего под управлением вспомогательного экземпляра операционной системы, будем называть фазой обслуживания (на диаграмме Out Of Order).
Здесь снова получаем прежнюю проблему. Ведь можно и корень второй системы разместить на LVM, вынеся лишь /boot в отдельный раздел диска. Тогда задумаемся, какая глубина online-преобразований (без отключения) требуется. Если надо оставить возможность перепланировки всего дискового устройства, то разумно ВСЕ данные вспомогательной системы вынести на отдельный раздел. Аналогичное соображение верно и в отношении основной системы.
Наблюдательный читатель спросит: ну хоть /var можно вынести в примонтированный том и тем самым сократить размер корневого раздела? Конечно, можно! Только надо учесть, что в случае проблем с монтированием в /var на "чистом" корне не будет никаких структур, обеспечивающих работу сервисов - даже /var/run. Поэтому правильной последовательностью будет установка всей системы в единый раздел и потом уже перенос того, что нужно, на другие тома LVM с последующим их монтированием. Такая последовательность установки позволит практически с минимальной потерей функциональности отключать все "на лету" и соответственно менять. Значит, сэкономить не получится!
Таким образом, у нас появилась еще пара принципов планирования дисковых ресурсов серверов.
Принцип 3. Необходимо кроме основной системы создать независимую по разметке вспомогательную систему, которая будет обеспечивать фазу обслуживания сервера в случае необходимости произвести online-преобразования основной системы.
Принцип 4. Все данные, нужные для работы системы в минимальной функциональности, по возможности, надо устанавливать в один корневой раздел. Это увеличит надежность системы и позволит независимым образом манипулировать другими примонтированными разделами.
Следствием этих принципов является то, что возникают все возможности для создания дополнительного резервирования. Кроме использования "зеркальных" дисковых устройств можно создать "зеркальные" системы, которые позволят произвести "откат" изменений в случае повреждения одной из них - той, которая была рабочей, - в процессе online-обслуживания. Иначе говоря, если один из дублей системы предназначался для создания фазы обслуживания, то, сделав эти дубли идентичными, получаем пару, состоящую из основной и резервной системы. Конечно, здесь не идет речь о полном дублировании всех данных. Обсуждается лишь вопрос о создании дубликата корневого раздела в части, обеспечивающей функционал сервера.
Теперь вернемся к "нашим баранам". Итак, размещения лишь /boot на выделенном томе не достаточно, так как это не обеспечит независимой загрузки для манипуляции остальным дисковым пространством. Значит, надо на отдельном разделе, установленном по схеме 1 DISK, 2 MD, 3 EXT3..., разметить всю систему. И кроме того, сделать это дважды, поскольку надо обеспечить еще и фазу обслуживания основной системы. Одновременно с этим получаем "бесплатный" дубликат рабочей системы на случай неожиданного технического повреждения последней (например, из-за ошибки в процессе наложения патчей), то есть фактически добавляем еще и фазу оперативного резерва.
Таким образом, система после загрузки может перейти в одну из трех фаз: рабочую, обслуживания и резерва. Мысль эта не нова. Не могу привести пример из RHEL, но из SuSE - легко! В стандартно создаваемом в процессе установки menu.lst присутствует пункт аварийной загрузки failsafe. Хоть failsafe и полумера, но культурного шока от моих предложений не должно быть.
А что в результате, спрашивается? Можно обойтись без спасательного CD! И все? Ведь получается, что все равно переключение системы из фазы работы в другие производится в традиционном варианте лишь с консоли. Ну можно, конечно, еще и путем редактирования menu.lst, благо, что возможности Grub позволяют это делать без переустановки. Нет, конечно, ради такой чепухи и не стоило бы городить столько. Все это даст эффект лишь в том случае, если настроить систему управляемой загрузки.
Концепция управляемой загрузки
С точки зрения загрузчика, процесс загрузки системы, безусловно, управляем. Но с точки зрения самой системы, он всегда проходит одни и те же фазы загрузки: BIOS - LOADER - одна из эксплуатационных фаз. Выбор конкретной эксплуатационной фазы производится или из консольного меню оператором, или указанием ветки загрузки по умолчанию путем редактирования самого меню. И то и другое представляет собой весьма рукотворный процесс.
Управляемой загрузкой будем считать такой способ настройки, когда выбор нужной фазы работы системы будет происходить автоматически в процессе загрузки. Конечно, для этого в Grub не хватает функциональности. Его исполнительная часть stage2, которая обрабатывает меню, позволяет модифицировать его и даже выполнять какие-то действия с дисковыми устройствами или сетевыми сервисами, занимает от 100 до 200 Кб, в зависимости от сборки. Но этого недостаточно. В процедуре управляемой загрузки нужно иметь возможность выбрать эксплуатационную фазу, анализируя параметры в контексте самого сервера, а не загрузчика. Элементарно, например, если в ходе анализа потребуется прочитать данные или с LVM, или с удаленного тома NFS, или получить путь из LDAP, то вряд ли удастся остаться в рамках только пакета Grub для обеспечения такой функции управления загрузкой.
Итак, обслуживание стадии управления загрузкой будет производиться Linux как универсальной платформой. Присвоим новой фазе работы сервера название служебной (на диаграммах Stuff). Это проходная фаза, в которой по некоторым критериям будет выбрана следующая фаза загрузки, произведена соответствующая коррекция и далее произведена перезагрузка. В Grub существует механизм выбора пути загрузки по содержимому специального файла default, который записывается утилитой grub-set-default. Хотя можно и просто менять текст самого menu.lst.
Но чтобы данная функциональная схема запустилась, надо обеспечить назначение служебной фазы как пути загрузки по умолчанию для следующей перезагрузки после запуска каждой из других фаз - пунктов меню. Можно воспользоваться все той же утилитой grub-set-default или так же менять содержимое menu.lst. Но в Grub есть специальный оператор (savedefault), который обеспечивает запись нужного значения прямо из stage2, то есть до передачи управления на загружаемую ОС, которая в общем случае может быть и несовместима с утилитой grub-set-default.
Получается, что кроме уже перечисленных двух систем (одна основная, другая резервная) надо создать еще и третью? Нет, достаточно использовать одну из уже имеющихся, но в специальном режиме. Как это сделать, покажем на примере чуть позже. На примере же и проиллюстрируем, как планируется диаграмма переходов состояний сервера в процессе загрузки.
А сейчас зададимся вопросом, а не ересь ли предлагается здесь - создание специальной инсталляции Linux только для обеспечения загрузки? Нет! Есть аналог предложенного решения. Известен в "миру" как EFI (Extensible Firmware Interface). Изначально он создавался как новый формат модульного заменителя традиционного BIOS. Но в результате получилось, что такой универсальный инструмент может грузить и ОС, используя свои сильно расширенные возможности. Для обеспечения процесса загрузки с помощью EFI системы Linux используется компонента ELILO (программа в формате EFI), которая читает все загружаемые файлы со специального системного раздела, размеченного в FAT. Объем такого раздела небольшой по нынешним меркам - 128 Мб, как рекомендовано. На нем должны располагаться и ядра, и initrd, и все, что может понадобиться как загрузчику ELILO, так и другим компонентам EFI, список которых не ограничивается лишь драйверами и диагностическими утилитами. Но факт остается фактом: то, до чего еще не додумались разработчики проприетарного EFI, легко реализуется на самом Linux.
Пример управляемой загрузки
В качестве иллюстрации технологии управляемой загрузки рассмотрим синтетический пример: управляемую загрузку рабочей станции. Такая подмена предмета позволит сделать пример полностью законченным и конкретным. Одновременно это даст возможность продемонстрировать большее число приемов загрузки с помощью Grub. И кроме того, покажет, что рамки применения, казалось бы, серверной технологии можно с успехом расширить.
Поставим задачу следующим образом. Нужно создать универсальную рабочую станцию, которая будет автоматически загружиться как Linux-станция, Windows-станция и Xтерминал. Согласно нашей концепции будут также реализованы дополнительные состояния - служебное и состояние обслуживания. Полная диаграмма переходов состояний, начиная с запуска Grub, будет выглядеть, как представлено на рис. 3.
Рисунок 3. Изменение состояний рабочей станции в процессе управляемой загрузки
Зеленым цветом обозначены узлы, соответствующие рабочим состояниям, желтым - служебные, красным - состояние обслуживания. Рабочая станция пребывает в состояниях обслуживания и служебном в течение времени, необходимого на выполнение запрограммированных задач. А вот пребывание в рабочих состояниях ограничивается лишь целевой необходимостью и завершается командой оператора на перезагрузку или выключение, но также может быть инициировано удаленным запросом с центрального сервера, управляющего всей сетью подобных рабочих станций. Естественно, технология такого запроса полностью определяется платформой, которой этот запрос должен управлять. Например, для того чтобы выключить MS Windows XP удаленно с Linux-сервера, можно воспользоваться специальным запросом MS RPC:
> rpcclient -c shutdowninit -U username%password ip-address
где username и password соответствуют бюджету администратора на компьютере с адресом ip-address, где будет запущена процедура выключения (которая, кстати, не сможет автоматически завершить работающие программы, увы).
Меню Grub для обеспечения требуемой смены состояний можно построить следующим образом:
# cat /boot/grub/menu.lst
color white/blue black/light-gray
default saved
hiddenmenu
timeout 5
#0
title Out Of Order
root (hd0,1)
kernel /boot/vmlinuz root=/dev/sda2 vga=0x332 selinux=0 splash=0 showopts 3
initrd /boot/initrd
savedefault 4
#1
title Linux
root (hd0,1)
kernel /boot/vmlinuz root=/dev/sda2 vga=0x332 selinux=0 splash=0 showopts 5
initrd /boot/initrd
savedefault 4
#2
title Windows
root (hd0,2)
chainloader +1
makeactive
savedefault 4
#3
title Terminal
bootp
root (nd)
kernel /lts/pxe/vmlinuz.ltsp root=/dev/ram0 rw init=/linuxrc
initrd /lts/pxe/initrd.lts
savedefault 4
#4
title Stuff
root (hd0,1)
kernel /boot/vmlinuz root=/dev/sda2 vga=0x332 selinux=0 tonextboot splash=0 showopts 3
initrd /boot/initrd
savedefault
#
Это, конечно же, один из возможных вариантов, и многие параметры надо назначить согласно используемому оборудованию и принятым установкам работы. В частности, выше видно, что все состояния, обслуживаемые Linux, совмещают один экземпляр системы (так как цель демонстрации лишь управляемая загрузка). Пункты меню, соответствующие основным состояниям, более-менее однозначны: N 1 Linux и N 2 Windows соответствуют стандартным способам запуска этих систем из Grub. N 3 Terminal запускает клиента LTSP путем загрузки ядра и initrd с ресурса tftp, который указывается по протоколу DHCP. Для того чтобы сработала команда bootp, надо вместо stage2, устанавливаемой в ходе стандартной процедуры, разместить в корне Grub stage2, специально собранную для работы с сетью:
# cp /usr/lib/grub/stage2.netboot /boot/grub/stage2
При этом выполнение всех остальных команд меню не пострадает. Пункты меню N 4 Stuff и N 0 Out Of Order во всем практически подобны стандартному режиму запуска Linux на уровень 3. Но для их правильного функционирования надо запрограммировать специальную обработку этих режимов в процессе инициализации соответствующего уровня. Продемонстрируем, как это сделать для служебного режима, поскольку он является ключевым для реализации всей схемы.
Будем использовать в качестве управляющего признака содержимое файла, размещенного на локальном http-ресурсе. Далее принимаются стандарты SuSE на расположение таких файлов. Например, сделаем так: если следует запустить станцию с адресом 192.168.0.166 с использованием пункта меню Grub с номером 1, то запишем этот номер в файл, названный по IP-адресу нужной станции (действия производятся на http-сервере):
# echo 1 >/srv/www/htdocs/192.168.0.166
Это значение можно прочесть со станции с помощью wget, lynx или curl, обратившись по адресу http://www.office.localnet/192.168.0.166, если именно такой адрес у нашего локального http-ресурса. Получив значение нового рабочего состояния, скрипт устанавливает параметры следующей загрузки, используя утилиту grub-set-default.
Скрипт, который будет анализировать параметр управления загрузкой, назовем tonextboot. Для того чтобы он вызывался автоматически, придется поместить его в процесс стартовой инициализации соответствующего уровня, в нашем случае уровня 3:
# cp tonextboot /etc/init.d
# insserv tonextboot
Но чтобы скрипт "знал", когда запускать систему в служебном режиме, добавим специальный параметр, который будем передавать через Grub ядру в командной строке так, чтобы потом можно было проверить его наличие через /proc/cmdline. Примем таким параметром управляемое слово "tonextboot". Если этого слова нет, то скрипт "считает", что это какой-то иной режим запуска, а не Stuff. Если же такое слово обнаруживается, то следует выполнить действия, указанные на рис. 3. Полный текст скрипта, сделанный по стандартам SuSE приведен ниже. Чтобы скрипт правильно встал в порядок загрузки, указано, что для его работы требуется инициализированный сетевой уровень.
Скрипт tonextboot
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: tonextboot
# Required-Start: network
# Should-Start:
# Required-Stop: network
# Default-Start: 3
# Default-Stop:
# Description: Check and set next boot way
### END INIT INFO
. /etc/rc.status
rc_reset
NULL=/dev/null
SRV="http://www.office.localnet/"
#VERB=1
DEF=2
abort() {
[ "1${VERB}" != "1" ] && { echo ; echo -n "Error: $1" ; }
rc_status -u
rc_exit
}
default() {
[ "1${VERB}" != "1" ] && { echo ; echo -n "Error: $1" ; }
BOOT=$DEF
echo -n " to $BOOT"
$GRUB $BOOT
rc_status -v
/sbin/shutdown -r now
rc_exit
}
echo -n "Check and set next boot way"
case "$1" in
start)
STUFF=$(cat /proc/cmdline | grep tonextboot)
[ "1${STUFF}" == "1" ] && { abort "use only for stuff level!" ; }
CURL=`which curl 2>$NULL`
[ "1${CURL}" == "1" ] && { abort "need curl!" ; }
GRUB=`which grub-set-default 2>$NULL`
[ "1${GRUB}" == "1" ] && { abort "need grub-set-default!" ; }
HOST=$(hostname -i | grep 192.168)
[ "1${HOST}" == "1" ] && { default "cant resolve address!" ; }
BOOT=$(${CURL} --max-filesize 2 -s ${SRV}${HOST} | grep "[[:digit:]]")
[ "1${BOOT}" == "1" ] && { default "cant get boot way!" ; }
echo -n " to $BOOT"
$GRUB $BOOT
rc_status -v
/sbin/shutdown -r now
;;
*)
rc_status -s
;;
esac
rc_exit
Скрипт очень простой и прозрачный по смыслу. В нем есть обработка только одной непредвиденной ситуации - если скрипт "не может" вообще никак "узнать" следующее состояние сервера. Тогда принимается политика "по умолчанию", которая управляется переменной DEF.
Нельзя не сказать и о том случае, когда grub-set-default будет вызван с номером, превышающим число возможных ветвлений меню Grub. Тогда система запустится с параметрами нулевого пункта меню. Это надо учитывать при планировании порядка размещения состояний в меню Grub.
Все перечисленные настройки, включая модификацию stage2, выполняются без переустановки Grub. Затем производится начальная инициализация grub-set-default 4 и после перезагрузки система станет работать в зависимости от того уровня, что назначен на сервере www.office.localnet для данной станции.
Таким приемом можно управлять офисом или классом компьютеров, заставляя их автоматически загружаться в нужный режим.
Сопутствующие вопросы
Рассмотрение темы планирования дисковых ресурсов не будет полным, если не коснуться вопросов надежности программных уровней представления данных (LVM, MD и проч.) и выбора типа файловой системы. Вопреки традиционному подходу, не будем придавать этим вопросам статус основополагающих. И вот по какой причине.
В отношении LVM существует расхожее бытовое мнение о, якобы, низкой ее надежности, основанное на том факте, что после повреждения структуры LVM практически невозможно восстановить данные файловых систем, созданных внутри логических томов. Это неверно построенная логическая цепочка рассуждений. По аналогии, многие люди считают опасными самолеты, на том основании, что, мол, летают быстро и высоко, и при падении выживших крайне мало, но при этом забывают, что статистика свидетельствует, что обычный автотранспорт гораздо опаснее. Но и это не самое главное. В таком рассуждении подменяется объект. Цикл эксплуатации состоит из времени наработки на отказ, отказом и периодом восстановления. Так вот, надежность всецело определяется временем наработки на отказ. И это время не зависит от сложности самой программной системы, а лишь от надежности оборудования. Причина в том, что в настоящее время в ЭВМ применяются детерминированные алгоритмы. То есть вне зависимости от цепочки преобразований пара одинаковых запросов вернет эквивалентные данные. Безусловно, чем сложнее преобразования, тем сложнее их реконструкция на этапе восстановления. Но, во-первых, это уже не имеет отношения к надежности, а, во-вторых, кто сказал, что восстановление сложных систем надо производить примитивными способами?
В отношении MD и остальных программных систем все аналогично. Есть лишь те проблемы, что каждая из таких систем вводит в работу ряд параметров, например, название MD устройства, имя группы LVM, и при физической модификации дисковых устройств возможны конфликты по этой причине. Наличие вспомогательной системы, кроме основной, позволит модифицировать все подобные параметры у основной системы, чтобы избежать конфликта.
Самый спорный вопрос - это, конечно же, предпочтения типа файловой системы. Очень часто этот вопрос перетекает из области рациональной оценки в область вкуса, привычек или политических предпочтений. А как же иначе? Ведь если бы существовало однозначное решение, так все менее популярные проекты просто прекратили бы развиваться. Значит, в каждой из файловых систем есть собственные преимущества.
Попробуем решить спор тривиальным тестированием с помощью bonnie (Таблица 1). Условия полностью совпадают с теми, что были в первой части статьи [1]. Только параметром будет тип файловой системы (перечислены в верхней строке). Режимы тестирования указаны в самом левом столбце. В перекрестьях замеренные результаты в Кбайт в секунду, рядом с которыми изображены индексы отклонения от средней по данному тесту величины.
Таблица 1. Зависимость скорости доступа от типа файловой системы
|
ext3 |
reiserfs |
reiserfs4 |
xfs |
jfs |
Символьная запись |
47362 - 1,01 |
47965 - 1,02 |
37533 - 0,80 |
49783 - 1,06 |
52083 - 1,11 |
Блочная запись |
60396 - 1,01 |
66731 - 1,12 |
51754 - 0,87 |
61549 - 1,03 |
57912 - 0,97 |
Перезапись |
21618 - 0,95 |
22360 - 0,98 |
22116 - 0,97 |
23365 - 1,03 |
24225 - 1,07 |
Символьное чтение |
21791 - 0,82 |
23956 - 0,90 |
29647 - 1,12 |
28199 - 1,06 |
28893 - 1,09 |
Блочное чтение |
53288 - 0,99 |
52851 - 0,98 |
53963 - 1,00 |
54159 - 1,01 |
54350 - 1,01 |
Итоговая оценка |
2 - 0,96 |
2 - 1,00 |
1 - 0,95 |
5 - 1,04 |
4 - 1,05 |
Для наглядности представим результаты в графической форме в виде столбчатой диаграммы (рис. 4). И убедимся, что серьезного преимущества нет ни у одного из форматов.
Рисунок 4. Зависимость скорости доступа от типа файловой системы
Тогда определим для каждой из систем число индексов, превосходящих 1, рассчитаем средний индекс и запишем все это в итоговой строке (строка 6 в таблице 1). Теперь уже можно установить, что лучшие результаты у xfs и jfs, худший - у reiserfs4, а вот те файловые системы, что зачастую принимаются в качестве стандартных в инсталляторах "из коробки", "ходят" в явных середнячках (и даже не в "троечниках"!). Хотя отклонения не превышают 5%. Иначе говоря, нет иного способа объяснить выбор форматов ext3 и reiserfs в качестве стандартов, как учетом их большей отработанности (например, в jfs значительное число возможностей пока имеет статус экспериментальных) и большей историей использования.
Тем более, вспомним, что выбор типа файловой системы для нас актуален лишь относительно. Используя основную систему, можно поменять формат файловых систем, размещенных в LVM, почти "на лету": создать "снапшот" LVM, произвести резервное копирование, создать новый логический том, разметить его в новом формате, синхронизировать данные и перемонтировать. Лишь две последние операции потребуют кратковременного отключения. Даже формат основной системы можно поменять, используя вспомогательную систему. А потом и на ней изменить разметку, воспользовавшись уже основной.
Таким образом, эти, в обычном случае "важные" вопросы - сложность LVM, выбор типа файловой системы - благодаря использованным технологическим приемам переведены в разряд второстепенных.
Заключение
Обсуждение вопросов, связанных с темой планирования дисковых ресурсов, можно считать завершенной. Были сформулированы четыре принципа, которые следует учитывать при создании конкретного серверного решения. Проиллюстрированы разнообразные технологические приемы, сопутствующие предложенным технологиям. Но, безусловно, все вышесказанное носит рекомендательный характер. Не забывайте, что дисковые подсистемы и вопросы, их окружающие, являются лишь частью, хотя и достаточно важной, всех задач, которые решаются в ходе построения прикладного сервера. И конечный выбор способа, которым надо разбить дисковые устройства на разделы, полностью определяется назначением самого сервера. О том, какие преимущества можно получить, используя предложенный здесь подход, обсудим в продолжении цикла.
Литература:
1. Барабанов А. Современный Linux-сервер: как планировать дисковые ресурсы. - Журнал "Системный администратор", N1, 2006 г. - 16-21 с.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |