3

IPXE kickstart安装CentOS的方法

 3 months ago
source link: https://bajie.dev/posts/20240118-ipxe_install/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

IPXE Kickstart安装CentOS的方法

2024-01-18 6 分钟阅读

这些年IDC物理机装机的大法也在不断衍进,从最早的手动装一堆tftp/dhcp/syslinux/httpd,到cobbler的一统江湖,到现在的dnsmasq轻量级安装,nocps安装,一直在不断进化着。

因为cobbler实在太重,不得不专门起一个kvm虚机来运行,完全不喜欢啊。所以一直也在研究终极安装服务器的大法。

折腾服务器无数回,找出了个自己比较喜欢的方式。

首先介绍一下背景知识:

  • PXE 可以通过网络给计算机安装操作系统。 PXE协议大致上结合了DHCP和TFTP。

  • gPXE gPXE是PXE的一个开源实现(更早的实现是Etherboot)。通过gPXE能让网卡直接支持网络启动,而不依赖于网卡自带的PXE固件。同时相比PXE,gPXE支持更多的协议。 传统的PXE只能通过TFTP进行传输,而gPXE支持HTTP,iSCSI和ATA over Ethernet(AoE),甚至支持wifi链接。

  • iPXE iPXE表示 it doesn’t PXE。iPXE是gPXE的原班人马写的(他们从Etherboot开始),作为官方的gPXE的替代品。 gPXE扩展的功能在iPXE中都得到支持。 之所以不再使用gPXE是由于存在版权纠纷,iPXE从2010年4月开始,基于同一个代码库开始开发。

  • PXELINUX Syslinux是一个优秀的系统启动加载器(bootloader),可引导自硬盘、光盘、和通过PXE的网络启动。 PXELINUX派生自Syslinux,用来使支持PXE的网卡从网络引导启动Linux。PXELINUX程序不是烧在网卡里,而是存储在TFTP服务器上。

  • Chainloading iPXE 可以把iPXE当作固件刷进计算机网卡的ROM里替换掉自带的PXE,但更为常见的是通过chainloading的方式进入iPXE。

有点晕是吧,总结一下,pxe包含了gpxe/ipxe/pxelinux,ipxe是最新的,gpxe/ipxe/pxelinux可以通过chain的方式顶替网卡原生的pxe。

推荐的装机方式:

客户机启动网卡自带的固件pxe,然后去服务器拉一个gpxe/ipxe,然后启动这个gpxe/ipxe,再去服务器拉具体的启动文件,这种就是chain方式了。我们就可以用到http/iscsi/wifi等各种先进方式启动了。

我们第一步先要准备一个gpxe的boot文件。

解释一下,文件后缀有.pxe/.kpxe/.kkpxe,这是个递进关系,.pxe是最原生的网卡驱动,.kpxe包含了调用原生网卡的UNDI驱动(无网卡驱动),.kkpxe更进一步,包含了UNDI+PXE原生网卡的驱动。

当然选择.kpxe了,我们的目的就是通过这个ipxe调用原生网卡上的驱动即可,如果是你自己要烧网卡的bootroom片子,就得选择所有驱动了。

这样我们会得到一个 gpxe-1.0.1-undionly.kpxe 的文件,保存备用。

然后我们来设置Dnsmasq:

log-dhcp

dhcp-no-override

enable-tftp  
tftp-root = /tftpboot

dhcp-range=tftp,172.16.36.100,172.16.36.105

dhcp-match=gpxe,175  
dhcp-boot=net:#gpxe,gpxe-1.0.1-undionly.kpxe,gxe/bootserver,172.16.36.1  
dhcp-boot=http://172.16.8.1/ks/boot.txt  

注意:gpxe-1.0.1-undionly.kpxe是放在/tftpboot/gpxe/之下的

上面有很多玄机,dhcp-range是随便设一个地址池,因为最终实际是gpxe来决定地址,所以第一次dhcp得到的地址反而不重要了。dhcp-no-override一定要有,否则gpxe有bug,无法启动。

其次匹配gpxe,凡是175的都是gpxe,为什么要匹配呢?看下面,有两个dhcp-boot启动选项,#pxe,#表示不是,这行意思是:不是gpxe启动的话用/tftp/gpxe/gpxe-1.0.1-undionly.kpxe来启动,dhcp的server是172.16.36.1。第二行如果是gpxe启动的话,就chain到[http://172.16.8.1/ks/boot.txt]去启动

呵呵,如果不这么设置,就用一行的话:

dhcp-boot=gpxe-1.0.1-undionly.kpxe,gxe/bootserver,172.16.36.1  

就会陷入死循环,首先pxe启动,抓了个gpxe,gpxe又启动抓了个gpxe,又抓gpxe,循环往复没玩没了。所以必须标记gpxe,并跳出这个循环。

我们在172.16.8.1上面建立/centos7的yum安装源,同时建立/ks目录。准备boot.txt,boot2.php,boot3.php,centos7.ks四个文件,下面一个一个解释:

首先是boot.txt

cat boot.txt  
#!gpxe

chain http://172.16.8.1/ks/boot2.php?uuid=\${uuid}&mac=\${mac}&busid=\${busid}&ip=\${ip}&hostname=\${hostname:uristring}&serial=\${serial:uristring}&asset=\${asset:uristring}&manufacturer=\${manufacturer:uristring}&product=\${product:uristring}

大家看上面,boot.txt是个gpxe脚本,实际是让gpxe向boot2.php传输了一些数据过来,有机器的uuid/mac/busid/hostname/serial/product等等。给个具体的例子,从access.log看到实际发过来的请求如下:

"GET /ks/boot2.php?uuid=%5C44454c4c-5600-1054-8042-b1c04f433532&mac=%5Cec%3Af4%3Abb%3Ad9%3A96%3A40&busid=%5C01%3A80%3A86%3A15%3A21&ip=%5C172.16.36.100&hostname=%5C&serial=%5C1VTBC52&asset=%5C&manufacturer=%5CDell%20Inc.&product=%5CPowerEdge%20R730 HTTP/1.0" 200 46 "-" "gPXE/1.0.1" "-"

看上面,有很多信息,网卡的物理地址,还有serial,对应dell就是svc tag号,还有机器类别PowerEdge R730,这是个好东西啊。

我们购买机器的时候肯定有序列号,上架到机房的时候,可以让idc抄下来机柜和序列号,然后我们让网管规划好ip,再这里就可以利用serial来确定机器应该按哪个模板安装。

再看模板文件,centos7.ks

#version=DEVEL
auth --enableshadow --passalgo=sha512  
url --url=http://172.16.8.1/centos7  
text  
firstboot --enable  
ignoredisk --only-use=sda  
keyboard --vckeymap=us --xlayouts='us'  
lang en_US.UTF-8  
selinux --disabled

services --enabled="chronyd"

network  --bootproto=static --device=em1 --noipv6 --nodns --onboot=yes --gateway={gateway} --ip={ip} --nameserver=172.16.8.1 --netmask={netmask}  
network  --bootproto=dhcp --device=em2 --noipv6 --nodns --onboot=no  
network  --bootproto=dhcp --device=em3 --noipv6 --nodns --onboot=no  
network  --bootproto=dhcp --device=em4 --noipv6 --nodns --onboot=no  
network  --hostname={hostname}

#grub-crypt --sha-512
# root  pass is password
rootpw --iscrypted $6$0Y.SH935/jvt0X.D$lCte9H/KiFeGbTGrrcuXGZXmnq3Rk4Crz8nAvCgH.Pf2SNmoUdh.g5WGWJqtVO4QTyqvnXc/6FyVjptWIaM4w1  
timezone Asia/Shanghai --isUtc

bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=sda  
clearpart --all --drives=sda

part /boot --fstype ext4 --size=500 --ondisk=/dev/sda  
part swap --size=8192 --ondisk=/dev/sda  
part / --fstype ext4 --size=1024 --grow --ondisk=/dev/sda

%packages
@compat-libraries
@core
wget  
net-tools  
chrony  
bridge-utils  
%end

%post
yum -y erase NetworkManager  
cat <<EOF >/etc/sysconfig/network-scripts/ifcfg-br0  
DEVICE=br0  
TYPE=Bridge  
BOOTPROTO=static  
ONBOOT=yes  
IPADDR={ip}  
NETMASK={netmask}  
GATEWAY={gateway}  
EOF  
cat <<EOF > /etc/modprobe.d/bonding.conf  
alias bond0 bonding  
BONDING_OPTS="miimon=100 mode=1 primary=em1"  
EOF  
cat <<EOF > /etc/sysconfig/network-scripts/ifcfg-bond0  
DEVICE=bond0  
ONBOOT=yes  
USERCTL=no  
BRIDGE=br0  
EOF  
cat <<EOF > /etc/sysconfig/network-scripts/ifcfg-em1  
DEVICE=em1  
USERCTL=no  
ONBOOT=yes  
MASTER=bond0  
SLAVE=yes  
BRIDGE="br0"  
EOF  
cat <<EOF > /etc/sysconfig/network-scripts/ifcfg-em2  
DEVICE=em2  
USERCTL=no  
ONBOOT=yes  
MASTER=bond0  
SLAVE=yes  
BRIDGE="br0"  
EOF  
%end

reboot  

注意上面,{ip}、{netmask}、{gateway}、{hostname}是待定的。

然后看看boot2.php:

<?php  
$dns='172.16.8.1';
$base7='http://172.16.8.1/centos7';
$ks7='http://172.16.8.1/ks/boot3.php';

echo "#!gpxe\n";


switch ($_REQUEST['mac']) {

  case '\ec:f4:bb:d9:96:40':
    $ip="172.16.36.2:172.16.37.254:255.255.254.0:myhost-16-36-2";
    $ipa=explode(':',$ip);
    echo "ifopen net0\n";
    echo "set net0/ip $ipa[0]\n";
    echo "set net0/netmask $ipa[2]\n";
    echo "set net0/gateway $ipa[1]\n";
    echo "set net0/dns $dns\n";
    echo "set base-url $base7\n";
    echo "kernel \${base-url}/images/pxeboot/vmlinuz\n";
    echo "imgargs vmlinuz inst.ks=$ks7?file=centos7.ks&ip=$ipa[0]&mask=$ipa[2]&gateway=$ipa[1]&hostname=$ipa[3] ksdevice=bootif inst.vnc inst.vncpassword=password inst.sshd\n";
    echo "initrd \${base-url}/images/pxeboot/initrd.img\n"; 
    echo "boot\n";
    break;

  case '00:11:22:33:44:55':
    # boot from iSCSI
    echo "set initiator-iqn iqn.2007-08.com.example.initiator:initiator\n";
    # see http://ipxe.org/sanuri for the syntax
    echo "sanboot iscsi:san.example.com:6:3260:0:iqn.2007-08.com.example.san:sometarget\n";
    break;

  case '\00:77:21🆎cd:ee':
    # boot boot.salstar.sk's super cool boot menu      
    echo "chain http://boot.salstar.sk\n";
    break;

  default:
    # exit iPXE and let machine go on with BIOS boot sequence
    echo "exit\n";
    break;
}

?> 

注意上面,我们是通过网卡的物理地址来判断模板的,用svc tag号更好。

第四个文件:boot3.php

<?php

$origin_str = file_get_contents($_REQUEST['file']);

$update_str = str_replace("{ip}", $_REQUEST['ip'], $origin_str);
$update_str = str_replace('{netmask}', $_REQUEST['mask'], $update_str);
$update_str = str_replace('{gateway}', $_REQUEST['gateway'], $update_str);
$update_str = str_replace('{hostname}', $_REQUEST['hostname'], $update_str);

echo $update_str;  
?>

boot3.php的功能就是替换掉模板文件里的ip等,然后返回一个正确的ks文件。

这下就完美了,我们基本就需要修改ks下的boot2.php和centos7.ks,就可以控制远程安装了。

dhcp和tftp,就用dnsmasq和那一个gxpe就够了,省了大事了。

还有更好玩的: 网卡原生pxe–>gpxe–>pxelinux.0

大家尽情想象吧。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK