IPXE
Материал из noname.com.ua
iPXE
Начальный сетевой PXE загрузчик iPXE Внезапно, эта статья — продолжение предыдущих статей «Настройка PXE окружения» и «PXE-загрузка с использованием dnsmasq». Здесь я опишу начальный pxe-загрузчик (network bootloader) ipxe, который очень элитен и тот, кто в него умеет элитен также. Некоторое отступление про ipxe. Вышеупомянутые статьи описывают что такое PXE и как оно вообще работает, если вы не — то читать. Одним из элементов PXE является начальный pxe-загрузчик, читаемый из ROM сетевой карты или по сети с TFTP-сервера. Его работа — загрузить с TFTP-сервера и отобразить загрузочное меню в каком-либо виде, загрузить выбранный код (например, ядро операционной системы) и запустить его. Этим он похож на MBR, которая только и делает, что находит активный загрузочный диск и читает с него загрузочный код. pxelinux.0 — довольно простой загрузчик, который умеет показать загрузочное меню в каком-то виде, загрузить выбранное по TFTP и запустить. gpxe — более продвинутый загрузчик, умеет в DNS, HTTP, iSCSI и подобное, появился как результат проекта Etherboot. ipxe — существенно переработанный форк gpxe, с собственной системой меню, команд и с поддержкой довольно экзотических протоколов, таких как AoE и HTTP. Что будет важно в следующей статье — он умеет san-boot, то есть умеет представлять LUN розданный по сети или с хранилища как локальный диск данной машины с доступом через функции BIOS-a. Это значит, что код, не имеющий понятия о сети или SAN, такой как GRUB или MSDOS, может видеть и иметь доступ к такому диску. Для начала настроим простую конфигурацию PXE с ipxe и проверим, что она работает, чтобы в дальнейшем извращать всяко. Полигон для извращений следующий. Свежая минимальная инсталляция RHEL 6.6 с выключенными SELinux и файрволлом, которая будет работать как pxe-сервер. На этом сервере — три сетевых интерфейса, eth2 смотрит в интернеты, eth0 и eth1 — в локальную сеть. Есть инсталляционный диск с дистрибутивом RHEL 6.6, который мы собираемся устанавливать на другие сервера по PXE, диск смонтирован в, допустим, /media. Путь к корню TFTP-сервера — /var/lib/pxeboot, этот путь — произвольный, у нас будет такой. Установим необходимый пакет dnsmasq для DHCP и TFTP сервера. В самом конце конфиг-файла /etc/dnsmasq.conf раскомментируем опцию conf-file, чтобы положить настройки относящиеся к PXE в отдельный файл /etc/dnsmasq.pxe.conf. Так же можно раскомментировать только опцию conf-dir и складывать конфиг-файлы с любым именем в каталог /etc/dnsmasq.d. Также установим всякую фигню, которая нужна, но не устанавливается в минимальной инсталляции. [root@serv ~]# yum install dnsmasq wget man man-pages [root@serv ~]# grep -v -e '^#' -e '^$' /etc/dnsmasq.conf conf-file=/etc/dnsmasq.pxe.conf Скачаем сам ipxe. В пакетах его нет, поэтому качаем с его сайта http://ipxe.org/ с вот этой страницы, вот ссылка на сам файл. Все ссылки рабочие на момент написания статьи, если что, вот локальная копия, билд dea6. Номер версии ipxe уже долгое время 1.0.0+, а номер патча/билда — начало id последнего коммита в git-репозитории проекта. Так что простого способа узнать какая версия старее или новее нет — надо клонировать себе git-репо ipxe и проверять какой коммит раньший. [root@serv ~]# wget http://boot.ipxe.org/undionly.kpxe Подготовим каталог /var/lib/pxeboot — корень TFTP-сервера. [root@serv ~]# mkdir -p /var/lib/pxeboot/ [root@serv ~]# mv undionly.kpxe /var/lib/pxeboot/ # первичный pxe-загрузчик ipxe [root@serv ~]# cp /media/images/pxeboot/vmlinuz /var/lib/pxeboot/ # ядро Linux [root@serv ~]# cp /media/images/pxeboot/initrd.img /var/lib/pxeboot/ # загрузочный ram-диск Далее — конфиг dnsmasq, включающий DHCP и TFTP сервисы. Создадим простой конфиг-файл /etc/dnsmasq.pxe.conf с учётом того, что этому серверу статически назначены IP-адреса 12.0.0.10/24 и 13.0.0.10/24 на интерфейсы eth0 и eth1 (да, я знаю, что они белые и их, типа, нельзя использовать во внутренней сети, но мне пофиг). [root@serv ~]# cat /etc/dnsmasq.pxe.conf interface=eth0,eth1 dhcp-range=12.0.0.200,12.0.0.250,255.255.255.0,24h dhcp-range=13.0.0.200,13.0.0.250,255.255.255.0,24h enable-tftp tftp-root=/var/lib/pxeboot dhcp-boot=undionly.kpxe После этого запускаем dnsmasq. [root@serv ~]# service dnsmasq start Starting dnsmasq: [ OK ] [root@serv ~]# tail -30 /var/log/messages Oct 66 66:00:03 serv dnsmasq[1266]: started, version 2.48 cachesize 150 Oct 66 66:00:03 serv dnsmasq[1266]: compile time options: IPv6 GNU-getopt DBus no-I18N DHCP TFTP "--bind-interfaces with SO_BINDTODEVICE" Oct 66 66:00:03 serv dnsmasq-dhcp[1266]: DHCP, IP range 13.0.0.200 -- 13.0.0.250, lease time 1d Oct 66 66:00:03 serv dnsmasq-dhcp[1266]: DHCP, IP range 12.0.0.200 -- 12.0.0.250, lease time 1d Oct 66 66:00:03 serv dnsmasq-tftp[1266]: TFTP root is /var/lib/pxeboot Oct 66 66:00:03 serv dnsmasq[1266]: reading /etc/resolv.conf Oct 66 66:00:03 serv dnsmasq[1266]: using nameserver 66.66.66.66#53 Oct 66 66:00:03 serv dnsmasq[1266]: read /etc/hosts - 6 addresses Пробуем загрузиться по PXE на втором сервере. Второй сервер должен запросить у dnsmasq-а IP и скачать по TFTP файл undionly.kpxe, вот что по этому поводу должны написать в лог: [root@serv ~]# tail -30 /var/log/messages Oct 66 66:21:43 serv dnsmasq-dhcp[1266]: DHCPDISCOVER(eth0) 66:66:66:66:66:66 Oct 66 66:21:43 serv dnsmasq-dhcp[1266]: DHCPOFFER(eth0) 12.0.0.200 66:66:66:66:66:66 Oct 66 66:21:45 serv dnsmasq-dhcp[1266]: DHCPREQUEST(eth0) 12.0.0.200 66:66:66:66:66:66 Oct 66 66:21:45 serv dnsmasq-dhcp[1266]: DHCPACK(eth0) 12.0.0.200 66:66:66:66:66:66 Oct 66 66:21:45 serv dnsmasq-tftp[1266]: TFTP sent /var/lib/pxeboot/undionly.kpxe to 12.0.0.200 Oct 66 66:21:45 serv dnsmasq-tftp[1266]: TFTP error 0 TFTP Aborted received from 12.0.0.200 Oct 66 66:21:45 serv dnsmasq-tftp[1266]: TFTP failed sending /var/lib/pxeboot/undionly.kpxe to 12.0.0.200 Oct 66 66:21:45 serv dnsmasq-tftp[1266]: TFTP sent /var/lib/pxeboot/undionly.kpxe to 12.0.0.200 На самом же втором сервере (PXE-клиенте) должны написать что-нибудь вроде: CLIENT MAC ADDR: 66 66 66 66 66 66 GUID: 66666666-6666-6666-6666-666666666666 CLIENT IP: 12.0.0.200 MASK: 255.255.255.0 DHCP IP: 12.0.0.10 GATEWAY IP: 12.0.0.10 PXE->EB: !PXE at 9E55:0070, entry point at 9E55:0106 UNDI code segment 9E55:0BDE, data segment 98BF:5960 (610-637kB) UNDI device is PCI 02:02.0, type DIX+802.3 610kB free base memory after PXE unload iPXE initialising devices...ok iPXE 1.0.0+ (dea6) -- Open Source Network Boot Firmware -- http://ipxe.org Features: HTTP iSCSI DNS TFTP AoE bzImage ELF MBOOT PXE PXEXT Menu Press Ctrl-B for the iPXE command line... Если написали что-то подобное, то ура, самое сложное сделано и кто-то внезапно не совсем неудачник и лузер. И теперь, если не нажать Ctrl-B происходит интересная штука — бесконечный цикл. А именно: - Сетевая карта, умеющая в PXE (этот код расположен в её ROM), посылает в локальную сеть DHCP-запрос, получает IP и указание, что надо скачать c TFTP-сервера и запустить код из файла /var/lib/pxeboot/undionly.kpxe - Сетевая карта скачивает этот код и передаёт ему управление - Код из undionly.kpxe тоже запрашивает DHCP-сервер, получает IP и, внезапно, то же самое указание, что надо скачать и запустить /var/lib/pxeboot/undionly.kpxe - Сервер застрял в бесконечном цикле, потому что ipxe, как сказано ему DHCP-сервером, загружает ipxe, который загружает ipxe, который угадайте что Поэтому надо как-то сказать DHCP-серверу, чтобы он говорил PXE-клиенту загружать код ipxe (файл undionly.kpxe) только на первый DHCP запрос (от сетевой карты), а на DHCP запрос от самого ipxe говорил загружать что-то другое, например меню загрузки. К счастью, систему PXE и сам ipxe писали ни разу не идиоты, и такая возможность есть, так как ipxe добавляет в свой DHCP-запрос специальную опцию 175, наличие которой может проверить DHCP-сервер (ну, то есть, должен уметь, dnsmasq это умеет, какой-то другой DHCP-сервер, возможно, нет). Итак, в файле /etc/dnsmasq.pxe.conf закомментируем строчку «dhcp-boot=undionly.kpxe» и напишем вот эти магические заклинания: [root@serv ~]# cat /etc/dnsmasq.pxe.conf ... # dhcp-boot=undionly.kpxe dhcp-match=ipxe,175 # пометить запрос тэгом net:ipxe если в запросе была опция 175 (encapsulate ipxe) dhcp-boot=net:#ipxe,undionly.kpxe # здесь #ipxe значит "не ipxe", то есть тэг не установлен dhcp-boot=bootmenu.ipxe # если тэг был установлен, сказать скачать этот файл Не забыть сказать dnsmasq-у перечитать свой конфиг: [root@serv ~]# service dnsmasq restart Shutting down dnsmasq: [ OK ] Starting dnsmasq: [ OK ] Теперь при загрузке по PXE на втором сервере (PXE-клиенте) ipxe должен послать свой DHCP-запрос и после инициализации написать: iPXE 1.0.0+ (dea6) -- Open Source Network Boot Firmware -- http://ipxe.org Features: HTTP iSCSI DNS TFTP AoE bzImage ELF MBOOT PXE PXEXT Menu net0: 66:66:66:66:66:66 using undionly on UNDI-PCI02:02.0 (open) [Link:up, TX:0 TXE:0 RX:0 RXE:0] Configuring (net0 66:66:66:66:66:66)... ok net0: 12.0.0.200/255.255.255.0 gw 12.0.0.10 Next server: 12.0.0.10 Filename: bootmenu.ipxe tftp://12.0.0.10/bootmenu.ipxe... No such file or directory No more network devices Что ни разу не удивительно, потому что файла bootmenu.ipxe у нас как бы нет, но тем не менее, это значит, что внезапно кто-то чуть меньше неудачник. Поэтому напишем своё загрузочное меню ipxe, с которым будем далее извращаться. Начнём с простого: загрузка ядра и initrd RHEL 6.6: [root@serv ~]# cat /var/lib/pxeboot/bootmenu.ipxe #!ipxe kernel vmlinuz initrd initrd.img boot Так как это установочный initrd, после загрузки начнётся процесс установки RHEL 6.6. Разумеется для установки потребуются все остальные установочные файлы и для этого, разумеется, нужно будет поднять HTTP или NFS сервер, где они будут лежать, а инсталлятор сможет их оттуда взять. Здесь мы заниматься этим не будем, здесь мы играемся с ipxe, стремящимся пацанам смотреть раздел «Настройка HTTP и DNS-серверов для установки ОС используя kickstart» в статье «Настройка PXE окружения». У ipxe адски крутая система команд, интересующимся смотреть документацию и примеры, особенно пример элитного загрузочного меню здесь (вот локальная копия). Здесь мы напишем простое меню, с загрузкой RHEL 6.6, memtest-a и, just for lulz, с загрузкой из интернетов. Для последней опции, разумеется интернеты должны быть на интерфейсе, на котором мы получили настройки IP по DHCP и сайт, предоставляющий этот сервис, должен работать и быть доступен. Memtest должен быть специальной версией http://boot.ipxe.org/memtest.bin (вот локальная копия), скачайте его и положите в /var/lib/pxeboot/. [root@serv ~]# wget -O /var/lib/pxeboot/memtest.bin http://boot.ipxe.org/memtest.bin [root@serv ~]# cat /var/lib/pxeboot/bootmenu.ipxe #!ipxe # Main menu :start menu Welcome to iPXE's Boot Menu item item install Install RHEL 6.6 item memtest Run Memtest86+ item inetboot Boot Linux from the internets item item shell Enter iPXE shell item config Enter iPXE config item reboot Reboot item item exit Exit (boot local disk) choose --default install --timeout 60000 target && goto ${target} || goto cancelled # Utility menu items :cancelled echo Menu selection was cancelled :shell echo Type exit to get the back to the menu shell set menu-timeout 0 goto start :failed echo Booting failed, dropping to shell goto shell :config config goto start :reboot reboot :exit exit # Menu items :install kernel vmlinuz initrd initrd.img boot :memtest kernel memtest.bin boot :inetboot chain http://boot.ipxe.org/demo/boot.php Теперь при загрузке по PXE на втором сервере должно показываться это меню и все его пункты должны, внезапно, работать, а если нет — то угадайте, что (подсказка: в ответе есть слово «неудачник»).