2023-02-20
В расширяющихся серверных кластерах для ускорения процесса ввода новых хостов зачастую применяют установку операционной системы по сети. Такой способ также позволяет использовать централизованный сервер установки ОС для хранения и управления их загрузочными конфигурациями. Ниже я постараюсь кратко описать основные принципы, по которым работает установка ОС по сети.
За установку ОС по сети со стороны клиента отвечает PXE, или PreBoot eXecution Environment – среда, обеспечивающая загрузку компьютера без использования локального носителя. Для обеспечения загрузки по PXE используются протоколы DHCP и TFTP, а PXE-код реализован в большинстве современных сетевых карт.
Загрузка по PXE в общем виде состоит из следующих этапов:
DHCP-сервер должен быть настроен соответствующим образом, чтобы распознать запрос от PXE-клиента. Например, в dnsmasq для этого существует опция dhcp-boot
:
$ man dnsmasq
...
-M, --dhcp-boot=[tag:<tag>,]<filename>,[<servername>[,<server address>|<tftp_servername>]]
...
$ cat /etc/dnsmasq.conf
...
dhcp-boot=tag:normalarch,/var/images/pxelinux.0
dhcp-boot=/var/images/pxelinux.0,cobbler-server,192.168.1.17
dnsmasq сам может выступать в роли TFTP-сервера (для этого в конфиге должна быть активирована опция enable-tftp
). В таком случае после получения запроса от клиента dnsmasq отправит бутлоадер, путь к которому является обязательным значением опции dhcp-boot
, в примере выше это /var/images/pxelinux.0
. Если кроме пути к бутлоадеру также указан адрес и/или хостнейм стороннего TFTP-сервера, то в ответ клиент получит именно их. В примере выше указано, что TFTP-сервер живёт по адресу 192.168.1.17 и имеет хостнейм cobbler-host
. dnsmasq также позволяет варьировать значения dhcp-boot
в зависимости от значений переданных в запросе DHCP-опций (tag:normalarch
). Для этого см. dhcp-match
в доках dnsmasq.
Для управления загрузочными конфигурациями можно использовать отдельные решения, например сервер установки Cobbler, который и будет выступать в роли TFTP-сервера, предоставляя клиентам необходимые для загрузки файлы.
В качестве примера предположим, что DHCP-сервер имеет адрес 192.168.1.16, TFTP-сервер - 192.168.1.17, а клиенту будет назначен адрес 192.168.1.101. Сняв дамп сетевого трафика на DHCP-сервере во время PXE-загрузки хоста, можно увидеть, как приходит DHCP-запрос от клиента, не подключённого к сети (IP-адрес 0.0.0.0
). В ответ посылается широковещательный пакет с адресом TFTP-сервера:
$ tcpdump -nnpi any port 67 or port 68 or port 69
...
23:29:18.603274 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from aa:bb:cc:dd:ee:ff, length 300
23:29:18.603274 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from aa:bb:cc:dd:ee:ff, length 300
23:29:18.604143 IP 192.168.1.16.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 340
23:29:18.604152 IP 192.168.1.16.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 340
Вскоре на TFTP-сервере начнётся отправка данных клиенту. Так как TFTP основан на UDP, то в дампе трафика фигурирует этот протокол. Передача начинается с отправки запроса на чтение (read request, RRQ):
$ tcpdump -nnpi any host 192.168.1.101
...
23:29:43.509633 IP 192.168.1.101.49155 > 192.168.1.17.69: 149 RRQ "/images/diskless/initramfs.gz" octet tsize 0 blksize 1408
23:29:43.720371 IP 192.168.1.101.49155 > 192.168.1.17.38292: UDP, length 4
23:29:43.720371 IP 192.168.1.101.49155 > 192.168.1.17.38292: UDP, length 4
23:29:43.720383 IP 192.168.1.17.38292 > 192.168.1.101.49155: UDP, length 1412
23:29:43.720385 IP 192.168.1.17.38292 > 192.168.1.101.49155: UDP, length 1412
После загрузки с TFTP-сервера бутлоадер PXELINUX помещает ядро в память и распаковывает initrd/initramfs (о том, что это – ниже). Ядро системы выполняет необходимые задачи, в том числе связанные с памятью и аппаратной частью сервера, и затем передаёт управление init-процессу. init выполняет задачи на прикладном уровне, например монтирует файловые системы.
На иллюстрации выше: стандартная схема загрузки CentOS. В нашем случае вместо загрузчика GRUB2 используется PXELINUX.
initrd (Initial RAM Disk) призван решить множество проблем и узких мест в связке kernel - init. Например, для монтирования корневой файловой системы в отдельных случаях init могут понадобиться специальные модули и драйверы, вшивать которые в образ ядра нецелесообразно. Или, например, если каталог /usr
монтируется в отдельной файловой системе, программы и драйверы, читающие и записывающие файлы в /usr
не могут быть использованы, пока каталог не будет примонтирован. А если для монтирования /usr
нужны программы и драйверы, зависящие от /usr
, то круг замкнётся и система не загрузится.
initrd - это образ корневой файловой системы, который распаковывается ядром как блочное устройство в память перед монтированием настоящей корневой ФС. initrd содержит в себе необходимые инструменты для подготовки файловых систем прежде чем управление будет передано init. Ядро вызывает установочный скрипт, обычно называемый linuxrc
, который выполняет необходимые действия, а затем вызывает init на реальной корневой ФС.
У initrd есть ряд недостатков, которые решает initramfs. initrd - полноценное блочное устройство, имеющее фиксированный размер и требующее собственную файловую систему (драйвер которой, к тому же, должен быть зашит в ядро). initramfs использует преимущества упрощённой файловой системы tmpfs, которая позволяет размещать файлы в памяти непосредственно. initramfs представляет собой, по сути, архив файлов, который распаковывается в память, что значительно проще операций с блочным устройством.
Для бездисковых систем initramfs может стать основной корневой файловой системой. В состав архива можно включить bootstrap-скрипт, который автоматически запустится и настроит CentOS после загрузки. Для обычных систем установку CentOS может упростить использование kickstart-конфигов для встроенного установщика Anaconda. В kickstart-конфиге можно прописать большое количество опций, например, указать, на какой именно диск устанавливать систему; разбирать синтаксис kickstart в этом посте я не буду. Бутлоадеру необходимо указать на использование kickstart-конфига, прописав путь к нему.
Например, конфигурации PXELINUX хранятся на TFTP-сервере, в том числе и в Cobbler, в каталоге /var/lib/tftpboot/pxelinux.cfg
. В файле default
этого каталога можно увидеть следующее:
LABEL EL7
kernel /images/centos-7.2-x86_64/vmlinuz
MENU LABEL EL7
append initrd=/images/centos-7.2-x86_64/initrd.img ksdevice=bootif kssendmac text ks=http://192.168.1.17/cblr/svc/op/ks/profile/EL7
ipappend 2
Параметр ks=
как раз указывает на путь к kickstart-конфигу, который будет загружен и исполнен при установке CentOS 7.