Рубрика:
Администрирование /
Администрирование
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
Сергей Супрунов
FreeBSD: некоторые особенности сборки ядра
Сборка собственного ядра на сервере – это почти обязательный ритуал для каждого системного администратора. Сегодня мы поговорим о том, как это делать по возможности быстро и эффективно.
Плюсы и минусы «стандартного» подхода
Информацию о том, как собирать собственное ядро, можно найти практически в любой книге, посвящённой системе FreeBSD. Естественно, есть она и в официальной документации (в частности, см. Handbook), так что не будем останавливаться на этом вопросе.
В конфигурационном файле ядра в первую очередь по устоявшейся традиции отключают все «лишние» устройства. Действительно, какой смысл собирать в ядре поддержку сетевых карт USB или SCSI-дисков, если их в сервере нет и в ближайшие годы не планируется? Так что, добавляя поддержку пакетного фильтра или квот, практически любой системный администратор заодно пробегает и по стройным рядам device-строк, безжалостно расставляя комментарии перед теми, которые выглядят подозрительно.
Но одной из особенностей сборки ядра во FreeBSD является то, что, даже закомментировав в конфигурационном файле строку, отвечающую за то или иное устройство или опцию, вы всё равно получите их поддержку в виде модуля. То есть драйвер редко используемого устройства не будет постоянно занимать место в оперативной памяти, но при необходимости его всегда можно подгрузить.
Но есть здесь и небольшой недостаток – время на сборку модулей будет всё равно потрачено. И зачастую даже небольшое изменение конфигурации ядра требует нескольких часов на пересборку, особенно на не слишком мощном «железе». Как правило, особых проблем это не создаёт (запустил сборку и пошёл обедать; да и на вопрос начальства «Чем занимаешься?» всегда можно честно ответить: «Ядро собираю»). Однако иногда «жаба душит», когда десятки минут созерцаешь процесс сборки чего-то, что никогда на сервере не понадобится... Попытаемся решить эту проблему.
Ничего лишнего!
Допустим, вам нужно пересобрать ядро на сервере. А действительно ли необходимы здесь модули поддержки звуковых карт? А как насчёт USB, если из оборудования здесь – четыре сетевых карты в PCI-слотах да CD-привод для аварийно-восстановительных работ? А зачем нужна поддержка NTFS, Ext2/3, Reiserfs и прочих, если единственной системой была, есть и будет FFS (ну, может, ещё ZFS через годик-другой, когда притрётся), поскольку разводить «зоопарк» на боевом шлюзе не придёт в голову даже самому отъявленному экспериментатору?
Понятно, что всё лишнее будет непременно из конфигурации ядра исключено. Только вот, как уже упоминалось выше, всё, что не указано в конфигурации, по-прежнему будет собираться в виде модулей. То есть ждать придётся столь же долго... Впрочем, можно и не ждать!
Попробуем минимизировать не только ядро, но и время, затрачиваемое на его сборку. Для начала по традиции уберём лишнее.
Например:
- Определитесь с нужным семейством процессоров. Как минимум, i486 сейчас уже мало где остались, и совсем необязательно загромождать ядро кодом поддержки оного.
- PROCFS, а с ней и PSEUDOFS в ряде случаев можно безболезненно отключить. Некоторые утилиты (преимущественно отладочного характера, такие как truss) могут требовать поддержки PROCFS, но в большинстве случаев можно обойтись и модулем.
- На совместимости с предыдущими версиями (опции COMPAT_*), на мой взгляд, лучше не экономить. Впрочем, если очень хочется, можно поэкспериментировать и в этом направлении.
- INET6 в ближайшие месяцы вы собираетесь использовать? Вряд ли.
- Списки доступа (UFS_ACL)? Вещь полезная, но не везде – не думаю, что на интернет-шлюзе или DNS-сервере нельзя будет обойтись стандартными правами доступа.
- NFS, MSDOSFS, CD9660 на сервере часто используете? Если нет – долой из ядра, хватит и поддержки в модуле... Хотя, с другой стороны, наличие этих опций будет не слишком обременительно для системы, зато вероятность столкнуться с проблемами при работе с CD- и Flash-дисками несколько уменьшится.
- В принципе на боевом сервере можно исключить и средства отладки, особенно если для тестирования есть отдельная машина, где в случае необходимости можно будет воспроизвести проблемную ситуацию и «снять» нужные дампы.
С имеющимися у вас устройствами, думаю, сами разберётесь (не забывайте только про устройство miibus, требуемое для работы некоторых сетевых карт; его исключение – довольно распространённая ошибка). Я обычно в ядро включаю то, что работает постоянно. То, в чём необходимость возникает сравнительно редко, проще оставить модулем. Это же правило я применяю и к различным опциям (например, поддержку пакетных фильтров как-то привык «вкомпилировать» в ядро). Впрочем, это только моё мнение.
Если подходить к этому вопросу более детально, то следует учитывать, что использование модулей обеспечивает дополнительную гибкость (вы динамически можете подгружать нужные модули, например, в случае добавления нового оборудования). С другой стороны, каждый модуль – это дополнительные структуры в памяти плюс дополнительное время на «стыковку» при загрузке. Впрочем, объёмы требуемой памяти не слишком велики по современным меркам, да и затраты времени пренебрежимо малы (тем более на серверах, где загрузка – не самая частая операция). Так что вопрос лежит, скорее, в плоскости личных предпочтений. Иногда рассматривается также аспект безопасности (можно собрать монолитное ядро и полностью запретить от греха подальше загрузку модулей, скажем, в результате перевода системы на securelevel 1 или выше), но здесь мы не будем вторгаться в эту тему.
С этим, думаю, всё понятно. А как влиять на то, какие модули должны быть собраны? В конфигурацию ядра можно добавить удобную для таких случаев опцию:
makeoptions MODULES_OVERRIDE='cd9660 netgraph nfsserver nfsclient'
При наличии такой строки модулями будут собраны только поддержка CD9660 (вдруг когда-нибудь понадобится CD-диск подмонтировать), NFS и интерфейсов netgraph. Остальное попросту не будет собираться, не отнимая ни времени, ни места на диске. (Названия модулей соответствуют именам каталогов в /usr/src/sys/modules, и, как правило, по названию несложно догадаться об их предназначении.)
Естественно, приведённый выше пример не следует рассматривать в качестве эталонного – вы и только вы можете определить, какие модули вам нужны, а какие нет. Также нужно учитывать, что таким образом можно очень легко привести систему в неработоспособное состояние, поэтому проверьте сначала по kldstat, какие же модули используются системой в различных режимах работы, чтобы ничего не забыть. Ну и несколько раз подумайте – а правда ли вы сможете жить без звука на своём боевом сервере?
Make.conf вам в помощь
Если характер работы сервера таков, что список модулей, которые могут понадобиться, практически не меняется (частный случай – полное отсутствие модулей, если вы привыкли работать исключительно с монолитным ядром), то параметр MODULES_OVERRIDE можно задать в файле /etc/make.conf – это значение будет оказывать влияние на все собираемые ядра. Таким образом, есть два пути жёстко задать список модулей – в make.conf, если все ваши ядра должны будут использовать один и тот же набор модулей, и в конфигурационном файле ядра (опция makeoptions MODULES_OVERRIDE), если для каждого ядра необходимо (или желательно) задавать свой набор модулей.
Есть более кардинальный путь – опция NO_MODULES в том же make.conf позволяет вообще отключить сборку модулей при сборке ядра. Опция MODULES_WITH_WORLD оставляет вам шанс – при её наличии модули будут собираться, но не с ядром, а с «миром» (во время выполнения команды make buildworld). Поскольку сборка всей системы выполняется сравнительно редко (при обновлении системы да изредка при устранении той или иной ошибки, оказывающей влияние на многие подсистемы ОС), а пересборка ядра не всегда требует перекомпиляции всех модулей, то определённый смысл в этом есть. Если же потребуется пересобрать какой-то из модулей, это в любое время можно сделать вручную:
# cd /usr/src/sys/modules/<имя_модуля>
# make
# make install
При необходимости можно запустить команду «kldxref /boot/kernel» (иногда модули размещаются и в отдельном каталоге – /boot/modules), чтобы обновить «подсказки» ядру, где и какие модули искать. Хотя обычно эта команда автоматически запускается при выполнении цели install. Собрать все модули вручную можно, выполнив команду make all install в каталоге /usr/src/sys/modules.
В дополнение к MODULES_OVERRIDE есть опция WITHOUT_MODULES, которая позволяет исключить сборку конкретных, указанных в ней модулей (из тех, что останутся для сборки после применения опции MODULES_OVERRIDE). Особого смысла разрешать определённые модули в MODULES_OVERRIDE и тут же исключать часть из них в WITHOUT_MODULES нет. Но если не использовать MODULES_OVERRIDE, то с помощью WITHOUT_MODULES можно исключить те модули, которые заведомо не нужны (например, драйверы звуковых карт), но при этом выполнить сборку всего остального «на всякий пожарный случай».
Несколько предостережений напоследок
Если вы используете модули, но решили не пересобирать их каждый раз вместе с ядром, внимательно следите за тем, влияет ли исправление тех или иных критических ошибок на ваши модули – не исключена ситуация, что, скрупулёзно выполнив все предписания из рассылки freebsd-security, вы на самом деле останетесь с открытой уязвимостью в модуле, который не пересобирался вместе с ядром.
И не забывайте, экспериментируя с ядром, оставлять пути отступления, копируя работоспособное ядро в отдельный каталог. Это позволит вам в случае проблем загрузиться с прежним ядром, разобраться в проблеме и устранить допущенные ошибки. Также имеет смысл сохранять устанавливаемое при инсталляции системы ядро GENERIC (если его нет, то всегда можно собрать на основе одноимённого файла в каталоге конфигурационных файлов ядра). Когда-нибудь оно сможет вас выручить, например, если придётся в аварийном порядке загружаться на оборудовании, поддержка которого в вашем рабочем ядре не предусматривалась.
Удачи!
Приложение
Пара советов
Хотя эти советы не оказывают непосредственного влияния на размер или скорость сборки ядра, но при частых его пересборках могут несколько упростить жизнь.
Если вы постоянно (или преимущественно) работаете с одним конфигурационным файлом ядра, то чтобы каждый раз не вводить в командной строке опцию «KERNCONF=MYKERN», укажите эту опцию в файле /etc/make.conf. Правда, не забывайте после этого явно указывать файл GENERIC, если захотите пересобрать ядро по умолчанию.
Иногда бывает, что рабочее ядро остаётся, но его конфигурационный файл безвозвратно теряется. Конечно, составление конфигурации с нуля – лучший способ навести в ядре порядок. Однако не всегда на это есть время и силы. Для подстраховки можно добавить в конфигурационный файл ядра такую строку:
options INCLUDE_CONFIG_FILE
Это позволяет сохранить текущий конфигурационный файл в самом ядре (в двоичном файле). Несколько лишних килобайт проблемой не станут, зато если вы вследствие печального стечения обстоятельств потеряете конфиг, на основе которого собиралось ядро, то всегда сможете его восстановить, используя команду strings, выбирающую из двоичного файла строковые фрагменты:
# cd /boot/kernel
# strings -n 3 kernel | sed -n 's/^___//p'
Перенаправив вывод в файл и немного подчистив при необходимости (к сожалению, последовательность из трёх символов подчёркивания, идентифицирующая строки сохранённой конфигурации, встречается и в других местах ядра; как правило, такой «мусор» появляется в самом начале полученного вывода), вы получите исходную конфигурацию, и даже со всеми комментариями, которые там были изначально.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|