PXE((Preboot eXecution Environment)是一种通过网络来实现网络部署操作系统或者网络加载操作系统的技术,主要的流程为:

  1. 通过DHCP引导内核或者启动文件

  2. 通过Web、SMB或者FTP共享文件下载系统安装文件;

  3. 通过KS文件实现无人值守,自动设置、自动装机。
    其基本思路和网络流量走向如下图:

DHCP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 安装dhcp server
dnf install -y dhcp-server

# 增加配置文件
cat > /etc/dhcp/dhcpd.conf<<'EOF'
option domain-name "sujx.net";
option domain-name-servers 192.168.10.2;
default-lease-time 864000;
max-lease-time 1000000;
authoritative;

option space pxelinux;
option pxelinux.magic code 208 = string;
option pxelinux.configfile code 209 = text;
option pxelinux.pathprefix code 210 = text;
option pxelinux.reboottime code 211 = unsigned integer 32;
option architecture-type code 93 = unsigned integer 16;

subnet 192.168.10.0 netmask 255.255.255.0 {
range dynamic-bootp 192.168.10.100 192.168.10.200;
option broadcast-address 192.168.10.255;
option routers 192.168.10.2;

class "pxeclients" {
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
next-server 192.168.10.10;

if option architecture-type = 00:07 {
filename "BOOTX64.EFI";
}
else {
filename "pxelinux.0";
}
}
}
EOF

# 新增一个网络接口
nmcli connection add type ethernet autoconnect yes con-name eth0 ifname ens34
nmcli con mod eth0 ipv4.method man ipv4.add 192.168.10.10/24 ipv4.gate 192.168.10.2

#修改DHCP监听到ens34接口
sed -i 's/$DHCPDARGS/ens34/g' /etc/systemd/system/dhcpd.service
# 开启DHCP服务
systemctl daemon-reload
systemctl enable --now dhcpd

# 检查状态
grep -w dhcp /etc/services
ss -anup | egrep '67|68'

引导环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装必备软件
dnf install -y tftp-server syslinux httpd

# 开启服务
systemctl enable --now tftp.socket
systemctl enable --now httpd

# 开启防火墙
firewall-cmd --permanent --add-service={http,https,tftp,ssh,dns,dhcp}
firewall-cmd --permanent --add-port={67/tcp,4011/udp}
firewall-cmd --reload

# 将引导程序复制到指定位置
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
cp /usr/share/syslinux/{menu.c32,vesamenu.c32,ldlinux.c32,libcom32.c32,libutil.c32} /var/lib/tftpboot/

添加系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 复制安装ISO镜像
mkdir /var/lib/tftpboot/rockylinux
mkdir -p /var/pxe/rockylinux

mount -t iso9660 -o loop,ro ./Rocky-9.4-x86_64-dvd.iso /media
cp /media/images/pxeboot/{vmlinuz,initrd.img} /var/lib/tftpboot/rockylinux/
cp -rf /media/* /var/pxe/rockylinux/

umount /media

# 配置HTTPD
cat > /etc/httpd/conf.d/pxeboot.conf <<'EOF'
# create new
Alias /rockylinux /var/pxe/rockylinux
<Directory /var/pxe/rockylinux>
Options Indexes FollowSymLinks
# access permission
Require ip 127.0.0.1 192.168.10.0/24
</Directory>
EOF

# 重启http服务
systemctl enable --now httpd

# 新建配置文件
mkdir /var/lib/tftpboot/pxelinux.cfg
cat > /var/lib/tftpboot/pxelinux.cfg/default <<'EOF'
default menu.c32
prompt 0
timeout 60

menu title PXE Boot Menu
label RockyLinux 9 Installer
kernel rockylinux/vmlinuz
append initrd=rockylinux/initrd.img inst.repo=http://192.168.10.10/rockylinux devfs=nomount ip=dhcp

label RockyLinux 9 AutoInstaller
kernel rockylinux/vmlinuz
append initrd=rockylinux/initrd.img inst.repo=http://192.168.10.10/rockylinux devfs=nomount inst.ks=http://192.168.10.10/ks/rockylinux.cfg ip=dhcp

label local
menu label Boot from ^local drive
localboot 0xffff

EOF

UEFI配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 配置UEFI主机
mkdir rpm
dnf -y install --downloadonly --downloaddir=/root/rpm shim grub2-efi-x64
cd rpm
rpm2cpio shim-x64-*.rpm | cpio -dimv
rpm2cpio grub2-efi-x64-*.rpm | cpio -dimv
cp ./boot/efi/EFI/BOOT/BOOTX64.EFI /var/lib/tftpboot/
cp ./boot/efi/EFI/rocky/grubx64.efi /var/lib/tftpboot/

# cp /boot/efi/EFI/BOOT/BOOTX64.EFI /var/lib/tftpboot/
# cp /boot/efi/EFI/rocky/grubx64.efi /var/lib/tftpboot/

chmod 644 /var/lib/tftpboot/{BOOTX64.EFI,grubx64.efi}

cat> /var/lib/tftpboot/grub.cfg <<'EOF'
set timeout=10
menuentry 'Install RockyLinux 9' {
linuxefi rockylinux/vmlinuz inst.stage2=http://192.168.10.10/rockylinux inst.ks=http://192.168.10.10/ks/rockylinux.cfg quiet ip=dhcp
initrdefi rockylinux/initrd.img
}
EOF

自动部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
cd ~
cat > ./autodeploy-ks.cfg <<'EOF'
# Generated by Anaconda 34.25.4.9
# Generated by pykickstart v3.32
#version=RHEL9
# Use graphical install
graphical
url --url="http://192.168.10.10/rockylinux/BaseOS"
repo --name="AppStream" --baseurl="http://192.168.10.10/rockylinux/AppStream"

# Disable Initial Setup on first boot
# firstboot --disable
%addon com_redhat_kdump --enable --reserve-mb='256M'
%end

# Keyboard layouts
keyboard --xlayouts='us'
# System language
lang en_US.UTF-8 --addsupport=zh_CN.UTF-8
# SELinux configuration
selinux --disabled
# Firewall configuration
firewall --enabled --ssh

# Network information
network --bootproto=dhcp --device=ens32 --ipv6=auto --no-activate
network --hostname=localhost.localdomain

# Use CDROM installation media
# cdrom

# Reboot after installation
reboot

%packages
@^server-product-environment

%end

# Run the Setup Agent on first boot
firstboot --enable

# Generated using Blivet version 3.6.0
ignoredisk --only-use=sda
autopart
# Partition clearing information
clearpart --none --initlabel

timesource --ntp-disable
# System timezone
timezone Asia/Shanghai --utc

# Root password
rootpw --iscrypted --allow-ssh $6$6FRYYQuLcWAjRZug$2JB0nfGZUmzLeFMoHe5nOtnVgPg26i1m11SlZznmMpUUuchfElnayOr33DUtyOJc2wlSdUNGbhGnS4oQwMix..
user --groups=wheel --name=sujx --password=$6$SpUxyt94uTfxaRxo$bwG5VkJ2QmpWYmnbixKf3MA.MftzaQ4HPCaphzAXGuul0Pej1S8wcQbsf.wpEpkcVYE7V2VtZSwp4YrAP7S3Z1 --iscrypted --uid=1000 --gecos="su jingxuan" --gid=1000
EOF

mkdir /var/www/html/ks
cp autodeploy-ks.cfg /var/www/html/ks/rockylinux.cfg
chown -R apache:apache /var/www/html/ks