Разбираемся с загрузкой ArchLinux по сети / Хабр

Что понадобится?

Совсем немного времени и трафика на скачивание нескольких небольших программ, а так же немного времени на
настройку (при наличии знаний по сетям). Помимо этого:

  1. Компьютер с Windows и сетевой картой (линейку 9х не проверял, но и с ней не должно быть проблем, а под NT
    семейством и подавно). Как соединять два компа и настраивать сетку описывать не буду – и так много написано.
    Априори считается, что вы можете соединить между собой два и более компа по сетке.
  2. Компьютер, который будет загружаться по сети с наличием сетевой карты с поддержкой загрузки по сети (PXE)
  3. tftpd32 (вводим в Google и тыкаем на первую ссылку)
  4. pxelinux – часть пакета syslinux – (гуглим по “syslinux” или берем zip-архив тут)
  5. Программа для создания образа дискет. Например, WinImage
    или что-то подобное.
  6. рюмочка коньяка для храбрости 🙂

[править] что такое pxe?

PXE (англ. Preboot Execution Environment, произносится пикси) — среда для загрузки компьютеров с помощью сетевой карты без использования жёстких дисков, компакт-дисков и других устройств, применяемых при загрузке операционной системы.

Что получаем?

Компьютер грузится по сетке, подключается к вашему компьютеру, скачивает загрузчик и ждет вашего ввода команды. Ну
а там смотря что ввели:

Ну и далее только от фантазии зависит 🙂 Можно, например, известные утилиты от Paragon тоже так грузить, но это уже сложнее (надо выковыривать из загрузочных дисков ядра и
образы линукса), можно тот же thinstation terminal client и т.д.

Описание некоторых модулей syslinux

chain.c32 — переключает на следующий загрузчик (grldr, ntldr или просто на загрузчик, установленный на разделе HDD)reboot.c32 — перезагрузка компьютераmenu.c32 — при использовании в меню, может загружать дополнительные меню (подменю), или производить переход назад/между меню. Пример использования:

Перейдем к настройке

Создадим конфиг основного меню и внесем начальные настройки


ui vesamenu.c32                  
PROMPT 0
menu background background.jpg
menu title ServerClub PXE boot menu

LABEL bootlocal
   menu label Boot from first HDD
   kernel chain.c32
   append hd0 0
   timeout 120
 TEXT HELP
The system will boot after the time is up
 ENDTEXT

[править] /var/lib/tftpboot/ltsp/i386/pxelinux.cfg/default

Пример конфигурационного файла PXELINUX.

В этом примере в загрузке
есть три пункта меню:

  1. Ядро 2.4, без использованя framebuffer’а
  2. Ядро 2.6, с использованием framebuffer’а
  3. То же дополнительный параметр ядру, впоследствии доступный через /proc/cmdline
DISPLAY boot.msg
TIMEOUT 300
PROMPT 1

LABEL 1
KERNEL vmlinuz-2.4.34.lan
APPEND root=/dev/nfs rw nfsroot=192.168.15.244:/opt/ltsp/i386/ ip=dhcp

LABEL 2
KERNEL vmlinuz-2.6.19.2
APPEND root=/dev/nfs rw nfsroot=192.168.15.244:/opt/ltsp/i386/ ip=dhcp vga=792

LABEL 3
KERNEL vmlinuz-2.6.19.2
APPEND root=/dev/nfs rw nfsroot=192.168.15.244:/opt/ltsp/i386/ ip=dhcp vga=792 rescue-ata-flash

/home/rdp/.xsession

[править] инсталляция dhcp-сервера

Установка DHCP-сервера:

%# apt-get install dhcp
.
.
.
NOTE: dhcpd's messages are being sent to syslog. Look there for
diagnostics messages.

Starting DHCP server: dhcpd failed to start - check syslog for diagnostics.

DHCP-сервер не заработал в базовой конфигурации – смотрим почему:

%# tail /var/log/daemon.log
Dec 25 17:27:56 debian rpc.statd[4128]: Version 1.0.10 Starting
Dec 25 17:33:43 debian dhcpd: No subnet declaration for eth0 (192.168.15.244).
Dec 25 17:33:43 debian dhcpd: Please write a subnet declaration in your dhcpd.conf file for the
Dec 25 17:33:43 debian dhcpd: network segment to which interface eth0 is attached.
Dec 25 17:33:43 debian dhcpd: exiting.

Анализ лог-файла /var/log/daemon.log говорит, что не описана сеть 192.168.15.0/24.
Указанная сеть была определена автоматически, исходя из адреса
интерфейса, на котором DHCP-сервер прослушивает запросы.
По умолчанию этот интерфейс eth0.
Конфигурационный файл dhcpd.conf не содержит описания этой сети.

Ниже мы отредактируем этот файл и опишем в нём названную сеть.

Если бы было нужно чтобы DHCP-сервер работал на другом интерфейсе,
нужно отредактировать файл /etc/default/dhcp —
указать нужный интерфейс:

%# vim /etc/default/dhcp

INTERFACES="eth1"

Сейчас этого делать не нужно.

[править] настройка tftp-сервера

В момент завершения установки нам было сообщено о том, что TFTP-сервер по-умолчанию не работает в режиме демона, а будет запускаться через интернет-суперсервер inetd. Проверим на наличие строки его настройки в конфигурационном файле inetd:

%# grep tftp /etc/inetd.conf
tftp           dgram   udp     wait    root  /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /var/lib/tftpboot

Перезапустим интернет суперсервер:

%# /etc/init.d/inetd restart
Restarting internet superserver: inetd.

И проверим выполняет ли интернет-суперсервер
прослушивание порта 69 (порт TFTP):

 
%# netstat -lnp | grep :69
udp        0      0 0.0.0.0:69              0.0.0.0:*           7331/inetd

На этом настройка TFTP-сервера завершена.

Я установил TFTP-server (apt-get install tftp-server), который умеет работать в режиме демона, запускается он так:

%# in.tftpd -l -s /var/lib/tftpboot

[править] создание “базовой площадки”

Для работы операционки все необходимые файлы можно разбить на 3 категории:

  • изменяемые сохраняемые (/home …);
  • изменяемые не сохраняемые (/etc /var/log /var/run …);
  • неизменяемые (все прочие).

Мы создадим “базовую площадку”, которая инициализирует файловую систему с учётом вышеописанных принципов. Для упрощения, корневую файловую систему разместим в /ltsp

Для начала экспортируем всё необходимое.
Затем возьмём за основу содержимое локального initrd.img.
Мы экономить не будем, а поэтому закинем необходимые бинарники, а позже библиотеки к ним.
Так же возьмём busybox в качестве шелла — вы сможете использовать /bin/ash в /init для отладочных целей.

Так же нам необходима часть его функций для развёртывания.
ifconfig нам нужен только для того, чтобы убедится в правильности назначения IP-адреса ядром.
С помощью mount.nfs будем монтировать необходимое для работы, т.к. больше ничто не может нормально работать с nfs. Так же нам необходим FIFO-файл initctl в каталоге устройств для “общения” с init’ом.

# mkdir /ltsp;
# cat >> /etc/exports
/ltsp/ *(ro,no_root_squash,async,no_subtree_check)
/usr/ *(ro,no_root_squash,async,no_subtree_check)
/var/ *(ro,no_root_squash,async,no_subtree_check)
/lib/ *(ro,no_root_squash,async,no_subtree_check)
/bin/ *(ro,no_root_squash,async,no_subtree_check)
/sbin/ *(ro,no_root_squash,async,no_subtree_check)
# /etc/init.d/nfs-server restart
# cd /ltsp
# gzip -cd /boot/initrd.img | cpio -imd --quiet
# cp `which busybox` /ltsp/bin
# cp `which ifconfig` /ltsp/bin
# cp `which mount.nfs` /ltsp/bin
# cp `which init` /ltsp/bin
# cd /ltsp/bin
# ln -s busybox ash
# ln -s busybox ln
# ln -s busybox tar
# ln -s busybox gunzip
# ln -s busybox cat
# ln -s busybox mount
# ln -s busybox pivot_root
# mknod /ltsp/dev/initctl p

Проверить, какие библиотеки используют скопированные бинарники можно командой ldd (ldd /sbin/ifconfig). У меня получилось всего 2:

cp /lib/ld-linux.so.2 /ltsp/lib
cp /lib/libc.so.6 /ltsp/lib

/sbin/init запускается первым и остаётся первым всё время. При своём запуске он читает inittab, секцию sysinit. там у нас указано выполнение нашего /init. Это сделано, по большей части, для удобства редактирования.

При загрузке необходимы “свои” конфигурационные файлы. “Выстрелим из бочки” и cнимем копию с рабочей системы скопировав /etc, подправим его. Оригинальный inittab заменит наш файл и загрузка продолжится в исходном режиме. Для уменьшения размеров и ускорения его загрузки по сети, запакуем его и будем распаковывать при каждой загрузке. Так же при загрузке у нас уже, наверняка, будет сконфигурирована сеть, поэтому удалим соответствующие файлы.

[править] создание клиентского образа ltsp

Образ создаётся с помощью скрипта ltsp-build-client.
В качестве аргументов скрипту необходимо указать:

  • архитектуру, для которой выполняется сборка;
  • дистрибутив, на базе которого будет построен образ;
  • зеркало, с которого должны инсталлироваться пакеты системы.

В каталог, который будет для бездисковой станции корневым,
проинсталлируется дистрибутив etch.
В качестве источника пакетов указан локальный apt-proxy.
Вместо него нужно указать соответствующее зеркало.

1. Разделы и файловые системы

Я люблю и уважаю LVM за его гибкость и удобство в работе, поэтому использую сетап, не требующий таблицы разделов на образе client. Вместо этого сразу на client создаётся еще одна VolumeGroup, которая потом режется на lv-тома.

root@target:~# pvcreate /dev/mapper/vg00-client
  Physical volume "/dev/mapper/vg00-client" successfully created
root@target:~# vgcreate client /dev/mapper/vg00-client
  Volume group "client" successfully created
root@target:~# lvcreate -L 12G -n rootfs client
  Logical volume "rootfs" created
root@target:~# lvcreate -l 100%FREE swap client
  Logical volume "swap" created

Создадим файловую систему и разметим раздел под swap:

root@target:~# mkfs.ext4 /dev/mapper/client-rootfs
root@target:~# mkswap /dev/mapper/client-swap

3. Сохранение настроек

Несмотря на то, что действия в targetcli выполняются немедленно, они не сохраняются и после перезагрузки все таргеты не вернутся. В этом поведение LIO похоже на поведение любых других ядерных служб (iptables, ebtables, ipvsadm и т. п.). При сохранении настроек targetcli компилирует всю конфигурацию в shell-скрипт, который просто скармливает нужные данные в configFS.

Сохраним все настройки:

cd /
saveconfig

Таргет готов! Перейдем к настройке DHCP TFTP.

DHCP-сервер


Предполагаем следующую конфигурацию:

Серверы живут в сети 10.0.0.0/24, таргет живет на 10.0.0.2, клиент получает по DHCP адрес 10.0.0.5.

Мануалов в сети море, поэтому коротко:

root@target:~# aptitude install -y isc-dhcp-server

dhcpd.conf:

allow booting;
allow bootp;

subnet 10.0.0.0 netmask 255.255.255.0 {
	range 10.0.0.10 10.0.0.254;
	option broadcast-address 10.0.0.255;
	option routers 10.0.0.1;
	option domain-name-servers 8.8.8.8;
	filename "/pxelinux.0";
}

host client {
	hardware ethernet XX:XX:XX:XX:XX:XX; # Тут должен быть MAC-адрес сетевой карты client'а
	fixed-address 10.0.0.5;
}

Стартуем демон:

root@target:~# /etc/init.d/isc-dhcp-server start

Syslinux

Устанавливаем пакет:

root@target:~# aptitude install -y syslinux syslinux-common

Копируем pxelinux.0 в /var/lib/tftpboot:

root@target:~# cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftboot

Также нам необходим образ ядра (можно взять с хост-системы). Сейчас у меня используется ядро от Ubuntu версии 3.2.0.37:

root@target:~# cp /vmlinuz /var/lib/tftboot/vmlinuz-3.2.0-37-generic

Дальше нужно собрать правильный initramfs. Для этого нам нужен модуль iSCSI:

Example

FIXME would this be better to just exist in specific model’s wiki pages?

FIXME should we create a page to list models with tftp support, noting which ones need the reset button trick?

On many routers, including the Asus WL-500g Premium v1 that I use, you flash an image by disconnecting power, press and hold down the reset button, and connect the power again. Wait a few seconds and the PWR LED will start to blink. Release the reset button. The device will now have a TFTP server running on 192.168.1.1.

Note that many TP-Link models are reported to support the same trick, including the TL-WR740Nv4, TL-WDR4300v1, TL-WDR3600v1, TL-WR842NDv1, TL-WR841NDv8, TL-WR841Nv11, TL-WR841Nv12, TL-MR3020v1, TL-MR3220v2, TL-MR3420v2, TL-WR940Nv2, TL-WR941NDv5, TL-WR1042NDv1 and possibly any other TP-Link model that has a recent firmware upgrade from the manufacturer. For a summary and ongoing experiments, see: http://bkil.blogspot.com/2022/12/hidden-tftp-of-tp-link-routers.html

:/>  Команда Ln: как создавать символические ссылки в Linux

You’ll have to use a Ethernet cable at this point. Connect it to LAN1-LAN4, notWAN. Configure your local machine on the 192.168.1.x/24 network, for example as 192.168.1.42. The router will use 192.168.1.1.

$ tftp 192.168.1.1
tftp> trace
Packet tracing on.
tftp> binary
tftp> put openwrt-brcm-2.4-squashfs.trx
sent WRQ <file=openwrt-brcm-2.4-squashfs.trx, mode=octet>
received ACK <block=0>
sent DATA <block=1, 512 bytes>
received ACK <block=1>
sent DATA <block=2, 512 bytes>
received ACK <block=2>
sent DATA <block=3, 512 bytes>
received ACK <block=3>
sent DATA <block=4, 512 bytes>
...
received ACK <block=4742>
sent DATA <block=4743, 512 bytes>
received ACK <block=4743>
sent DATA <block=4744, 512 bytes>
received ACK <block=4744>
sent DATA <block=4745, 0 bytes>
received ACK <block=4745>
Sent 2428928 bytes in 6.2 seconds
tftp> quit
$

Wait one minute and restart the box by disconnecting and reconnecting power. Some documentations claim that the device should restart by itself but I have never seen this happen, no matter how long I wait.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.

More information about cookies

Iscsi-таргеты

Небольшой ликбез по iSCSI

iSCSI — реализация протокола SCSI поверх TCP. Сам протокол SCSI весьма универсален, теоретически с его помощью можно подключить устройство любого типа. Тем не менее, в большинстве случаев SCSI используется для доступа к тем или иным устройствам хранения данных (жёсткие диски, приводы CD и DVD и т. п.). Для примера Mass Storage Device, использующийся в USB-устройствах, является реализацией SCSI поверх USB. Поэтому, кстати, флешки в Linux опознаются как /dev/sdX-устройства. Использующаяся на серверах шина SAS также является реализацией SCSI (собственно, это видно из названия — Serial Attached SCSI).
В iSCSI различаются понятия таргета (target, целевое устройство, осуществляет приём и выполнение запросов) и инициатора (initiator, порождает запросы). В более привычных терминах таргет — это сервер, а инициатор — клиент.
Таргеты и инициаторы бывают разных видов. iSCSI-таргетом может выступать обычный компьютер, сервер или система хранения данных. Инициаторами обычно выступают сетевые карты (в их ROM бывает прошит необходимый код) или software-реализации.

Для Ubuntu возможно использовать различные iSCSI-таргеты. Вот неполный их список:

Using tftpd-hpa

A detailed guide for beginners to tftpd-hda

There are multiple tftp clients that you can choose from.

Автоматическая установка и оптимизация nextcloud 21 (nginx, mariadb)

Скрипт поддерживает установку в операционных системах Debian 10.8 (AMD64) и Ubuntu 20.04.1 (AMD64). Для работы скрипта необходима установка пакета sudo.

Рассматривается установка на чистую систему, в которой не установлены другие инструменты, необходимые для веб-приложений.

В ходе работы скрипта будут подключены следующие репозитории для использования последних версий пакетов: ppa ondrej для установки php 7.4, ppa mainline для установки последней версии nginx, а так же репозиторий mariadb для установки MariaDB 10.5.

Важно. В качестве домена скрипт укажет имя хост системы . Поэтому перед началом работы скрипта, измените имя хоста системы и перезагрузите систему.

Имя хоста можно поменять следующим образом:

Есть и минусы

  • У tftpd32 есть баг – при одновременном обращении к нему больше одного клиента – жуткие тормоза на этапе
    загрузки pxelinux’а и образов. Если кому-то надо грузить, скажем, сразу много клиентов, то tftpd32 придется оставить
    только как DHCP, убрав в настройках галочку про TFTP Server (если, конечно, нет другого DHCP), а сам TFTP сервер взять другой (к сожалению, те
    серверы что я видел – коммерческие). Однако, при последовательном обращении клиентов – все летает. Так что как
    вариант просто грузить компы по очереди.

Загрузка hiren’s boot cd

Для версии 9.9 нужно скопировать в каталог загрузки файл hiren.ima из образа диска, а так же pxelinux.0 и memdisk из syslinux. Конфиг загрузки

DEFAULT memdisk
APPEND floppy c=35 h=64 s=32 initrd=hiren.ima

Подробно тут

История

Однажды к нам пришли (ну, не сами…) серверы с 14 хардами по 2Тб. Избавившись от аппаратного рейда (зачем — вопрос отдельный), мы задумались о том, что неплохо бы сделать для них загрузку по сети, дабы избавиться от возни с разделами. Диски предполагалось экспортировать по iSCSI, и не хотелось выделять какие-то диски на Особенные Системные Диски, а какие-то на всё остальное. Таким образом возникла задача сделать загрузку по сети с размещением корневого каталога в оперативной памяти.

Конфигурируем tftpd32.exe

Запустили, нажали Settings, в “страшном” окне указываем Base Dirrectory – C:TFTP. Потом выставляем галочки как на
картинке:

Жмем на ОК, еще раз ОК, и перезапускаем tftpd32.

Далее настраиваем наш DHCP сервер:

  1. Выбираем сетевую карточку, к которой подключен пациент
  2. Ставим начало адресов, которые получит первый клиент (этот адрес и количество клиентов не должно пересекаться с
    вашим IP)
  3. Количество адресов (минимум 1)
  4. Имя загрузчика (pxelinux.0)
  5. Маска сети (мат-часть по сетям)
  6. Сохраняемся….

Далее на всякий случай перезапускаем tftpd32. Почти закончили 🙂

Конфигурируем загрузку

Создаем текстовый файл C:TFTPPXELINUX.CFGdefault и редактируем его, скажем, так:

default local
prompt 1
label local
    localboot 1
label dos
    kernel memdisk
    append initrd=dos.imz
label pqpm8
    kernel memdisk
    append initrd=pqpm8.imz
label mem
    kernel memtest

Подробную информацию можно найти в pxelinux.doc из syslinux’a.

Ну и наконец, устанавливаем на компе загрузку с сетевого адаптера по PXE.

Настраиваем загрузку по сети с помощью grub

Поскольку GRUB на нашем сервере уже есть, создадим с его помощью структуру папок для сетевого клиента вот таким образом:

grub-mknetdir --net-directory=$root/boot --subdir=grub

В папке $root/boot появится папка grub и несколько других. Эту файловую структуру мы будем целиком «отдавать» с помощью TFTP-сервера. Сейчас мы используем 64-битный ArchLinux по той причине, что в 32-битной системе нет папки /grub/x86_64-efi/, которая требуется для загрузки систем UEFI.

Создайте файл конфигурации загрузчика со следующим содержимым:

Я взял файл grub.cfg с сервера и убрал из него всё то, что не участвует в отображении загрузочного меню GRUB или как-то связано с дисками.

Обратите внимание на знакомую нам строку с параметрами ядра:

linux /vmlinuz-linux add_efi_memmap ip="$net_default_ip":"$net_default_server":192.168.1.1:255.255.255.0::eth0:none nfsroot=${net_default_server}:/diskless


Как и в

присваиваем значение переменной «ip». Напоминаю, что она используется в обработчике «net», который мы приспособили для настройки сетевой карты в загрузочном сервере. Здесь снова указывается статический IP адрес и постоянное имя сетевой карты eth0. Значения $net_default_ip и $net_default_server подставляются GRUB самостоятельно на основании данных, полученных из самого первого DHCP запроса. $net_default_ip – это выделенный для нашей машины IP адрес, а $net_default_server — IP адрес загрузочного сервера.

Большинство руководств по сетевой загрузке (среди обнаруженных на просторах рунета), предлагают устанавливать переменную так «ip=::::::eth0:dhcp», что вынуждает обработчик net отправлять новый запрос DHCPDISCOVER для повторного получения сетевых настроек.

Нет объективной причины лишний раз «спамить» DHCP-сервер и ждать, пока он откликнется, поэтому снова используем статику и не забываем указать DNS-серверы. Такую задачу мы уже решали, поэтому просто копируем нужные файлы и добавляем службу в автозагрузку:

cp {,$root}/etc/systemd/system/update_dns@.service && cp {,$root}/etc/default/dns@eth0 && arch-chroot $root systemctl enable update_dns@eth0

Возвращаемся к строке с параметрами ядра. Ещё незнакомая нам команда add_efi_memmap (EFI memory map) добавляет EFI memory map доступной RAM. В прошлый раз мы её намеренно пропустили, из-за сравнительно сложной предварительной разметки носителя для поддержки UEFI.

Переменная ядра — nfsroot показывает, где именно в сети нужно искать корневую файловую систему. Она выполняет ту же самую функцию, что и переменная root в загрузочном сервере. В данном случае указан адрес NFS-сервера, который в нашем случае совпадает с TFTP-сервером, но это совершенно необязательно.

Настройка dhcp на cisco

network <ip сети> <маска>ip dhcp pool <Имя пула>bootfile pxelinux.0next-server <IP сервера tftp>default-router <Шлюз>option 66 ascii «Имя сервера»dns-server <DNS сервера>option 150 <IP сервера tftp>domain-name <доменное имя>

Настройка tftp сервера

Более подробно можно прочитать в статье установка TFTP-hpa сервера или настройка Настройка TFTP сервера на Mikrotik RouterOS

Настройка сетевого загрузчика pxe на syslinux

На самом деле, загрузчик SYSLINUX — это целый комплекс загрузчиков, на все случаи жизни, здесь есть и сетевой — PXELINUX, и загрузчик для ISO-образов ISOLINUX и просто загрузчик ОС с жесткого диска. Пока нам потребуется только сетевой. SYSLINUX представляет собой операционную систему в миниатюре, загрузчик с помощью специальных команд, прописываемых в загрузочном меню, может выполнять специальные функции, сохраняемые в исполняемых файлах особого формата — модулях загрузчика.

Начнем с плюсов моего метода

  • Не надо иметь выделенный RIS сервер (вообще не надо сервер) – не всегда он есть под рукой, а иногда за него
    надо платить…
  • Грузить можно любой 1.44, 2.88 и 5.76 (ага, и такие бывают!) образ дискеты как он есть, без изменений
    (единственное если прога на 2-х дискетах 1.44, то ее надо слить в один образ 2.88), плюс образ любого размера,
    который поместится в память клиента (речь уже об образе диска, а не дискеты)
  • Можно грузить различные линуксы, которые работают с RAM диска (например, thinstation – это RDP клиент, или те же
    утилиты от Paragon)
  • Можно грузить различные линуксовые бинарники (например memtest86 )
  • Легко модифицировать любую сеть для такой работы. Надо всего лишь на DHCP сервере сети указать IP нашего PXE
    сервера и имя загрузчика. Это в моей статье не описывается, так как уже было описано в первой статье (два параметра для DHCP – 066, 067), и админам думаю проблем не составит сделать нужные
    изменения)
  • Можно все нужные файлы таскать с собой на Flash диске – и тогда любой комп быстро превращается в PXE сервер
    (только надо перенастроить в tftpd32 – путь к файлам и IP адреса, и перезапустить его)
:/>  Команда nslookup, получение информации от DNS - ИТ Проффи

Несколько слов о конфиге pxelinux

В корне tftp-сервера размещается загрузчик pxelinux.0. Для его конфигурирования используется один из файлов в каталоге pxelinux.cfg. Таким образом, полный путь к каталогу конфигов загрузки /var/lib/tftpboot/pxelinux.cfg.

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

  • 1905cddb-18f7-4f21-a91c-3daee3408bee – имя соответствует GUID клиентского компьютера
  • 00-23-8B-82-42-F2 – имя соответствует MAC-адресу компьютера
  • C0A80063 – с именем, соответствующим IP-адресу (в данном случае 192.168.0.99) в шестнадцатиричном представлении
  • C0A8006, C0A800….C0, C – с именем, соответствующим части IP-адреса в шестнадцатиричном представлении
  • default – дефолтовый

Если файл не найден, то загрузчик перезагрузит компьютер через некоторое время.

Документация по PXELINUX (на английском)

Подготовка сервера dhcp

Файл /etc/dhcp/dhcpd.conf

В секции host должна присутствовать запись filename, указывающая на файл для начальной загрузки. Кроме того, можно добавить запись next-server – IP-адрес сервера загрузки, если он не совпадает с адресом сервера DHCP. Так же, могут быть указаны опции. Пример секции конфигурирования хоста:

host vk-nout {
    hardware ethernet 00:23:8B:82:42:F2;
    fixed-address 192.168.0.99;
    next-server 192.168.0.100;
    filename "/pxelinux.0";
}

Поехали!

  1. Распаковываем tftpd32.exe, скажем, в С:TFTP
  2. Распаковываем файл pxelinux.0 (из архива syslinux’а), memdisk (из sysylinux.zip/memdisk) а
    так же (опционально) memtest (sysylinux.zip/memtest) в C:TFTP.
  3. Tуда же (C:TFTP) кладем образ любимой загрузочной дискетки (можно и не только дискетки – но об этом ниже).
    Например, dos.imz (для экономии места и/или ускорения загрузки можно даже сжатый (winimage) образ класть –
    imz, a можно и не сжатый ima). Образов может быть сколько угодно.
  4. Проверяем, что у нас в сети нету DHCP серверов. Например, если включен ICS (шара интернета), то его выключить
    на время экспериментов.

Послесловие

В статье делается упор на tftpd32, так как он бесплатен, не требует установки, и включает в себя 2 сервера в 1 (DHCP и TFTP), а также запускается под Windows любой версии. Но сам принцип – загрузка и запуск бинарника pxelinux (с последующей загрузкой нашего образа) – не привязан к tftpd32, а требует наличия в сети DHCP сервера с двумя дополнительными параметрами – 067 (имя загружаемого бинарника – pxelinux.0)

и 066 (IP адрес TFTP сервера который нам и выдает искомый бинарник), а также собственно TFTP сервер, на который ссылается DHCP. Какими системами, сервисами или железками это реализовано нам совершенно неважно, потому можно использовать любой находящийся в сети сервер (Linux, Windows, Novell). Ну а если его нет, то tftpd32, запущенный на любой машине. Главное – это добраться по сети до PXELINUX.

Предисловие

Прочитал статью с описанием способа RIS и решил поделится своим методом. Дело в том что по работе
мне приходится часто кидать образы на компьютеры в школах, к которым у детишек отношение весьма не доброе, а потому
большинство CD-ROM сломано, а с дисководом никогда не угадаешь заранее, считает дискетку или нет. Поэтому загрузка образов
дискет (и не только) через PXE мне очень близка.

Пробуем загрузиться по сети

Проследим за процессом загрузки с сервера с помощью программы tcpdump

pacman -S tcpdump

tcpdump -v '( 
    src host 0.0.0.0 and udp[247:4] = 0x63350101) or ( 
    dst host HabraBoot and dst port tftp) or ( 
    dst host HabraBoot and tcp[tcpflags] == tcp-syn)'

Первая строка «ловит» запрос DHCPDISCOVER от PXE клиента. В выводе, отфильтрованном второй строкой, будут перечислены имена всех файлов, запрашиваемых по TFTP. Третья строка показывает два tcp-syn запроса, отправляемых в самом начале подключения по протоколу NFS (первое соединение осуществляется обработчиком net, а второе переподключение происходит во время обработки файла fstab).

Создаём новую виртуальную машину, для краткости будем называть её «клиент». В настройках сети снова указываем тип подключения «Сетевой мост» и включаем машину. Сразу же нажимаем клавишу F12 на клавиатуре для выбора загрузочного устройства, а потом клавишу l, чтобы загрузиться по сети.

Дождитесь окончания загрузки. Если всё в порядке, то на сервере добавляем используемые службы в автозагрузку:

systemctl enable tftpd.socket tftpd.service dhcpd4 rpcbind nfs-server

Все серверы DHCP, TFTP и NFS мы запустили на одном загрузочном сервере. Делать так необязательно. Например, роутеры Mikrotik поддерживают Bootp и позволяют использовать себя в качестве TFTP — просто закачайте туда все нужные файлы и проверьте сетевые настройки.

Сейчас графическое окружение будет работать только в VirtualBox, потому что мы не устанавливали драйверы для «железных» видеокарт. Мы решим проблему автоматического подбора нужных драйверов в следующей статье. Заодно ускорим загрузку системы и сделаем из неё «живой образ».

Снова устанавливаем linux

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

pacman -S arch-install-scripts

Совершенно предсказуемое начало:

export root=/srv/nfs/diskless
mkdir -p $root

Установим только базовые пакеты, поэтому:

pacstrap -d -c -i $root base

Далее повторите все действия вплоть до установки загрузчика согласно предыдущей статье. Вот чек-лист:

Сравним загрузку с диска и загрузку по сети

В предыдущей статье мы рассматривали процесс загрузки Linux с точки зрения внутреннего накопителя. Сейчас мы представим происходящее глазами сетевой карты. Картинка из заголовка хорошо иллюстрирует события за исключением того, что все серверы в нашем случае будут работать на одном компьютере.

Сразу после включения компьютера, срабатывает код PXE (Preboot eXecution Environment, произносится пикси — спасибо вики), разместившийся непосредственно в ПЗУ сетевой карты. Его задача — найти загрузчик и передать ему управление.

Сетевой адаптер совершенно не представляет в какой сети сейчас находится, поэтому назначает себе адрес 0.0.0.0 и отправляет сообщение DHCPDISCOVER. К сообщению прикреплются паспортные данные, которые обязательно нам пригодятся:

Адаптер ожидает получить ответ от DHCP сервера по протоколу BOOTP (Bootstrap Protocol), где помимо нужного IP адреса, маски подсети и адреса шлюза, присутствует информация об адресе TFTP-сервера и названии файла загрузчика, который с него следует забрать. Сервер TFTP, в свою очередь, просто отдаёт любому желающему любые файлы, которые у него попросят.

После получения ответа и применения сетевых настроек, дальнейшее управление загрузкой передаётся полученному файлу, размер которого не может превышать 32 кБ, поэтому используется двухстадийная загрузка. Всё необходимое для отображения на экране загрузочного меню докачивается следом по тому же протоколу TFTP.

Далее загрузка приостанавливается на время отображения загрузочного меню, а потом по тому же протоколу TFTP докачиваются выбранные файлы vmlinuz и initramfs, которым передается дальнейшее управление загрузкой. На этом этапе уже нет вообще никакой разницы в механизме загрузки по сети или с внутреннего накопителя.

Устанавливаем dhcp сервер

Скачиваем пакет:

pacman -S dhcp

и приводим содержимое конфигурационного файла /etc/dhcpd.conf к следующему виду:

mv /etc/dhcpd.conf /etc/dhcpd.conf.old 
nano /etc/dhcpd.conf


# Разрешаем использование протокола BOOTP
allow booting;
allow bootp;

# Утверждаем, что сервер является авторитетным (обычно роутеры либо не авторитетны, либо BOOTP не поддерживают, поэтому их PXE слушать не будет)
authoritative;

# получаем архитектуру клиента (это обсуждалось выше)
option architecture code 93 = unsigned integer 16;

# работаем в такой подсети (исправляйте под себя)
subnet 192.168.1.0 netmask 255.255.255.0 {

# в этот класс попадут все те, кто пытается загружаться
class "pxe_client" {
match if exists architecture;
}

pool {
# Разным архитектурам отдаём разные файлы:
if option architecture = 7 {
filename "/grub/x86_64-efi/core.efi";
} else {
filename "/grub/i386-pc/core.0";
}

# Рекомендую указать адрес TFTP сервера, несмотря на то, что это необязательно, раз он там же, где DHCP
next-server 192.168.1.100;

# Здесь, как обычно (не забывайте исправлять под себя)
default-lease-time 600;
max-lease-time 7200;
option domain-name-servers 192.168.1.1;
option routers 192.168.1.1;
range 192.168.1.128 192.168.1.192;

# Обрабатываем запросы только тех, кто загружается
allow members of "pxe_client";
}

}

Как видите, DHCP-сервер будет отвечать только на те запросы DHCPDISCOVER, которые придут от PXE клиентов, а остальные просто проигнорируются.

Запускаем DHCP сервер:

systemctl start dhcpd4

Устанавливаем tftp сервер

Скачиваем и устанавливаем необходимый пакет:

pacman -S tftp-hpa

Нам нужно, чтобы TFTP сервер предоставлял доступ к файлам загрузчика, которые мы разместили в папке $root/boot. Для этого модифицируем запуск службы уже проверенным способом:

:/>  CDMA против GSM - Технология - 2022

Итоги:


Можно вполне использовать iSCSI для загрузки серверов, не имеющих своих дисков (актуально для виртуализации, самопильных систем хранения данных, серверов, которые не должны долго жить и т.п.).

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

Присутствует security-hole, поскольку /proc/cmdline доступен любому желающему в системе и этот любой желающий может получить доступ к экспортированному тому. Поэтому можно на таргете закрыть фаерволом все адреса, кроме необходимого.

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

Подготавливаем initramfs

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

Сначала установим пакет, в который входит нужный нам обработчик net, а также пакет утилит для работы с NFS (модуль nfsv4 и программа mount.nfs4):

pacman --root $root --dbpath $root/var/lib/pacman -S mkinitcpio-nfs-utils nfs-utils

Исправим обработчик net из папки hooks (вместо команды для монтирования nfsmount, теперь будем использовать mount.nfs4):

sed s/nfsmount/mount.nfs4/ "$root/usr/lib/initcpio/hooks/net" > "$root/etc/initcpio/hooks/net_nfs4"


С помощью установщика обработчика из папки install добавим модуль nfsv4 и программу mount.nfsv4 в iniramfs. Сначала копируем и переименовываем заготовку:

cp $root/usr/lib/initcpio/install/net $root/etc/initcpio/install/net_nfs4

Теперь исправляем только одну функцию build(), а всё остальное не трогаем:

nano $root/etc/initcpio/install/net_nfs4

build() {
    add_checked_modules '/drivers/net/'
    add_module nfsv4?

    add_binary "/usr/lib/initcpio/ipconfig" "/bin/ipconfig"
    add_binary "/usr/bin/mount.nfs4" "/bin/mount.nfs4"

    add_runscript
}

Добавляем обработчик в initramfs путём исправления строки в файле mkinitcpio.conf:

nano $root/etc/mkinitcpio.conf

HOOKS="base udev net_nfs4"

[править] подготовка клиентского ядра и initrd

Необходимо подготовить ядро, под управлением
которого будут работать клиентские станции.

При конфигурировании клиентского ядра обязательно нужно включить:

  • Поддержку сетевой карты
  • Поддержку NFS

Ниже будет рассмотренно, как это осуществить

Для начала необходимо выяснить, какой модуль ответственнен за сетевую карту. На работающей машине сделайте:

cat /etc/modprobe.conf | grep eth

допустим, мы получили alias eth0 pcnet32.
После этого, нам необходимо выяснить, как она включается в ядро.

find /usr/src/linux/ | grep pcnet32

Так мы узнаем, в каком каталоге лежат файлы, ответственные за модуль.
Для драйверов сетевых карт это

/usr/src/linux/drivers/net

Осталось только узнать define-variable для модуля.

cat /usr/src/linux/drivers/net/Makefile | grep pcnet32

В выводе будет что-то похожее на CONFIG_PCNET32.
Далеко не у всех модулей имя define-variable совпадает с именем модуля.
Осталось только

cd /usr/src/linux
make menuconfig

и, используя клавишу [/], ввести то, что после CONFIG_. Месторасположение нам укажут.
Можно, конечно, вручную поправить файл .config, но так можно нарушить зависимости.
Итак, сетевые карта включаются в Device Drivers -> Network Device Support -> Ethernet (10 or 100Mbit). Как ни странно, pcnet32 оказался AMD PCNet32 PCI support.

File Systems -> Netwok File Systems -> NFS file system support
  • Поддержка функций dhcp ядром
Networking -> Network Options -> IP: kernel level avtoconfiguration

и соответствующие протоколы к нему (bootp и DHCP, хотя, возможно, будет достаточно только второго). Подразумевается, что TCP/IP-стек будет включён в ядро. Это очень важный момент. Без этой функции ядро сразу после загрузки высвободит выделенный айпи адрес и предоставить насройку пользователю (в initrd, например), а так же ядро будет игнорировать параметр ip=dhcp.

В этой ситуации поможет только явное указание адреса, что будет пригодно для загрузки только одной машины (или обязывает к немедленной смене адреса после загрузки).
IP-адрес можно указать так: ip=клиент:сервер:шлюз:маска:имя:устройство, но согласитесь, ip=dhcp лучше.
Кроме того, в File Systems -> Network File Systems появится не менее важный пункт:

Root file system on NFS

Заодно можно выставить оптимизацию под конкретный процессор и отключить неиспользуемые модули. Например IrDA, BlueTooth или IDE-через-LPT.

Initramfs

В этом примере мы будем забирать образ корневой фс с веб-сервера, расположенного на нашем сервере сетевой загрузки, то есть на 10.0.0.1. Решение было таким просто потому, что в нашем initramfs была утилита wget. Чтобы не тянуть большой объем данных по сети, мы решили сжать образ.

SquashfsSquashfs — это сжимающая файловая система, которая включена в ядро с версии 2.6.29. С ее помощью можно заархивировать каталог, примонтировать на loop устройство и читать с него, для записи же необходимо провести процедуру добавления файлов в архив. Так как при обращении к squashfs, вы читаете из архива, то это дает дополнительную нагрузку на cpu.

 mksquashfs /mnt/rootfs/ rootfs.squashfs -noappend -always-use-fragments
 du -hs rootfs.squashfs 
 92M	rootfs.squashfs


Для более эфферктивного сжатия вы можете использовать опцию -comp, чтобы установить тип сжатия, по умолчанию используется gzip.

Далее надо научить init из initramfs забирать образ корня и помещать его в оперативную память.

init в initramfs — это скрипт на sh, который производит разбор опций из cmdline, монтирует фс, делает switch_root и запускает гланый init-процесс системы. Воспользуемся этим и допишем свои опции для cmdline. Напишем скрипт ram, который будет вызываться при значении опции boot=ram.

vim /usr/share/initramfs-tools/scripts/ram

#!/bin/bash
retry_nr=0

do_rammount()
{
        log_begin_msg "Configuring networking"
        configure_networking
        log_end_msg

        log_begin_msg "Downloading rootfs image"
        mkdir -p /tmp/squashfs
        wget ${rooturl} -O /tmp/squashfs/rootfs.squashfs
        log_end_msg

        log_begin_msg "Mounting rootfs image to /mnt/squashfs"
        mkdir -p /mnt/squashfs
        mount -t squashfs -o loop /tmp/squashfs/rootfs.squashfs /mnt/squashfs
        log_end_msg

        log_begin_msg "Mounting tmpfs and copy rootfs image"
        mkdir -p ${rootmnt}
        mount -t tmpfs -o size=1G none ${rootmnt}
        cp -r -v /mnt/squashfs/* ${rootmnt} || exit 2
        log_end_msg

        log_begin_msg "Umount squashfs"
        umount /mnt/squashfs || exit 2
        log_end_msg
}
mountroot()
{
        for x in $(cat /proc/cmdline); do
                case $x in
                rooturl=*)
                        export rooturl=${x#rooturl=}
                        ;;
                esac
        done

        log_begin_msg "Loading module squashfs"
        modprobe squashfs
        log_end_msg        # For DHCP
        modprobe af_packet

        wait_for_udev 10

        # Default delay is around 180s
        delay=${ROOTDELAY:-180}

        # loop until rammount succeeds
        do_rammount

        while [ ${retry_nr} -lt ${delay} ] && [ ! -e ${rootmnt}${init} ]; do
                log_begin_msg "Retrying rammount"
                /bin/sleep 1
                do_rammount
                retry_nr=$(( ${retry_nr}   1 ))
                log_end_msg
        done
}

Через параметр rooturl можно указывать откуда качать образ корневой фс. Для работы со squashfs необходимо подгрузить ее модуль в ядро. Указываем в /etc/initramfs-tools/initramfs.conf BOOT=ram и пересобираем initramfs

mkinitramfs -o /var/lib/tftpboot/initrd.img

Включаем машинку, на которой будем тестировать, и смотрим на происходящее. После успешной загрузки мы получили бездисковую систему, которая занимает в памяти около 300Мб, при этом мы может писать в нее, но после ребута, система вернется в свое первоначальное состояние.

В это примере, мы использовали squashfs просто для сжатия образа, но почему бы нам не попробовать примонтировать корневой раздел в squashfs и не посмотреть, что получится? Меняем наш скрипт, в функции do_rammount() оставляем только монтирование squashfs.

do_rammount()
{
        log_begin_msg "Configuring networking"
        configure_networking
        log_end_msg

        log_begin_msg "Downloading rootfs image"
        mkdir -p /tmp/squashfs
        wget ${rooturl} -O /tmp/squashfs/rootfs.squashfs
        log_end_msg

        log_begin_msg "Mounting rootfs image to /mnt/squashfs"
        mkdir -p /mnt/squashfs
        mount -t squashfs -o loop /tmp/squashfs/rootfs.squashfs ${rootmnt}
        log_end_msg

}

Пересобираем initramfs, запускаем, смотрим. Система загружается в режиме ro, но зато занимает в памяти всего около 180Мб.В каких-то случаях монтирование в режиме ro это хорошо, но нас это не устраивает, но и просто так тратить оперативную память нам тоже не хочется. Выход же был найден при помощи Aufs.

AufsAufs позволяет делать каскадно-объединённое монтирование файловых систем — одну в режиме только на чтение, а вторую в rw. Работает она в режиме copy-on-write, то есть все изменения записываются на rw систему и после этого чтение производится с нее же. Опять переписываем наш скрипт. В фукнцию mountroot() добавляем

        log_begin_msg "Loading module aufs"
        modprobe aufs
        log_end_msg

А фукнцию do_rammount() приводим к следующему виду:

do_rammount()
{
        log_begin_msg "Configuring networking"
        configure_networking
        log_end_msg

        log_begin_msg "Downloading rootfs image"
        mkdir -p /tmp/squashfs
        wget ${rooturl} -O /tmp/squashfs/rootfs.squashfs
        log_end_msg

        log_begin_msg "Mounting rootfs image to /mnt/ro"
        mkdir -p /mnt/ro
        mount -t squashfs -o loop /tmp/squashfs/rootfs.squashfs /mnt/ro
        log_end_msg

        log_begin_msg "Mounting tmpfs to /mnt/rw"
        mkdir -p /mnt/rw
        mount -t tmpfs -o size=1G none /mnt/rw
        log_end_msg

        log_begin_msg "Mounting aufs to /mnt/aufs"
        mkdir -p /mnt/aufs
        mount -t aufs -o dirs=/mnt/rw=rw:/mnt/ro=ro aufs /mnt/aufs
        log_end_msg

        [ -d /mnt/aufs/mnt/ro ] || mkdir -p /mnt/aufs/mnt/ro
        [ -d /mnt/aufs/mnt/rw ] || mkdir -p /mnt/aufs/mnt/rw

        mount --move /mnt/ro /mnt/aufs/mnt/ro #сдвигаем точку squashfs монтирования в aufs
        mount --move /mnt/rw /mnt/aufs/mnt/rw #сдвигаем точку монтирования tmpfs в aufs 

        mount --move /mnt/aufs ${rootmnt} #сдвигаем точку монтирования aufs в ${rootmnt}
}

Пересобираем initramfs, запускаем, смотрим. Система занимает в памяти 181Мб, при этом мы можем менять ее, писать, читать. Все изменения хранятся отдельно в /mnt/rw, а сама система хранится в /mnt/ro.

В результате мы получили систему, которая грузится по сети, занимает небольшой объем в памяти, при этом после каждой перезагрузки пропадают все изменения (поэтому надо заранее собирать все нужные продукты жизнедеятельности системы в надежное место).

Оставьте комментарий

Adblock
detector