centos7下搭建ipxe服务器

2024-01-03
5分钟阅读时长

pxe网络安装系统流程图

image-20241114164352527

其中pxe引导文件,pxelinux.0 只适用于 传统启动方式(Legency boot),而ipxe项目提供的ipxe.efi等文件 适配了 uefi boot启动模式和更新的网络硬件支持

1.安装ipxe

yum install -y gcc binutils make perl xz-devel mtools mkisofs syslinux 

2.关闭selinux和防火墙

systemctl stop firewalld && systemctl disable firewalld
sed -i '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config
setenforce 0

3.配置dhcp和tftp

安装dnsmasq

yum install -y dnsmasq

创建pxe工作目录

mkdir -p /pxe/http/iso  /pxe/http/tftp

将镜像上传到/pxe/http/iso

编辑/etc/dnsmasq.conf

# 关闭DNS解析
port=0

#Setup the server to be your authoritative DHCP server
dhcp-authoritative

#Set the DHCP server to hand addresses sequentially
dhcp-sequential-ip

# 设置DHCP分发IP端范围、地址掩码、IP地址有效时间
dhcp-range=192.168.1.60,192.168.1.80,255.255.255.0,12h
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,223.5.5.5


# 设置引导程序相对tftp根目录的路径
dhcp-match=set:bios,option:client-arch,0
dhcp-match=set:ipxe,175
dhcp-boot=tag:!ipxe,tag:bios,undionly.kpxe
dhcp-boot=tag:!ipxe,tag:!bios,ipxe.efi #如果引导失败用这个 snponly.efi
dhcp-boot=tag:ipxe,boot.ipxe


# 设置tftp服务
enable-tftp
tftp-lowercase
dhcp-no-override
tftp-root=/pxe/http/tftp  

启动dnsmasq服务

systemctl restart dnsmasq && systemctl status dnsmasq

4.挂载镜像

cd /pxe/http/iso && mkdir ubuntu centos7
mount CentOS-7-x86_64-Minimal-2009.iso centos7/
mount ubuntu-20.04.6-live-server-amd64.iso ubuntu

查看挂载情况

[root@kvm iso]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  100G  0 disk
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   99G  0 part
  └─centos-root 253:0    0   99G  0 lvm  /
loop0             7:0    0  973M  0 loop /pxe/http/iso/centos7
loop1             7:1    0  1.4G  0 loop /pxe/http/iso/ubuntu

5.配置http服务

wget https://hub.gitmirror.com/https://github.com/codeskyblue/gohttpserver/releases/download/1.1.4/gohttpserver_1.1.4_linux_amd64.tar.gz
tar xzf gohttpserver_1.1.4_linux_amd64.tar.gz -C /usr/bin/

配饰systemd服务

cat << EOF >/etc/systemd/system/gohttpserver.service
[Unit]
Description=Systemd gohttpserver
After=network.target

[Service]
User=root
# Execute `systemctl daemon-reload` after ExecStart= is changed.
ExecStart=/usr/bin/gohttpserver -r /pxe/http --addr :80 --auth-type http
[Install]
WantedBy=multi-user.target
EOF

启动gohttp服务器

systemctl daemon-reload
systemctl start gohttpserver
systemctl status gohttpserver 
systemctl enable gohttpserver

6.配置ipxe

下载ipxe文件

wget -P /pxe/http/tftp http://boot.ipxe.org/ipxe.pxe
wget -P /pxe/http/tftp http://boot.ipxe.org/snponly.efi
wget -P /pxe/http/tftp http://boot.ipxe.org/undionly.kpxe
wget -P /pxe/http/tftp http://boot.ipxe.org/ipxe.efi

配置/pxe/http/tftp/boot.ipxe

#!ipxe

set boot-url http://${next-server}

# Setup some basic convenience variables
set menu-timeout 5000

# Ensure we have menu-default set to something
isset ${menu-default} || set menu-default exit

######## MAIN MENU ###################
:start
menu Welcome to iPXE's Boot Menu
item
item --gap -- ------------------------- Utilities ------------------------------
item centos7       Install Centos7
item ubuntu-server Install ubuntu server
item --gap -- ------------------------------ Advanced ---------------------------------
item --key r reboot     [R] Reboot the Computer
item --key x exit       [X] Exit (boot local disk)
choose --default exit --timeout 30000 target && goto ${target}

########## UTILITY ITEMS ####################
:failed
echo Booting failed, dropping to shell
goto start

:reboot
reboot

:exit
exit

:centos7
initrd ${boot-url}/iso/centos7/images/pxeboot/initrd.img
kernel ${boot-url}/iso/centos7/images/pxeboot/vmlinuz 
imgargs vmlinuz initrd=initrd.img inst.ks=${boot-url}/ks/ks-c7.cfg inst.repo=${boot-url}/iso/centos7
boot || goto failed
goto start

:ubuntu-server
kernel ${boot-url}/iso/ubuntu/casper/vmlinuz
initrd ${boot-url}/iso/ubuntu/casper/initrd
imgargs vmlinuz initrd=initrd url=${boot-url}/iso/ubuntu-20.04.6-live-server-amd64.iso cloud-config-url=/dev/null ip=dhcp fsck.mode=skip --
boot || goto failed
goto start

ipxe.dsk 是写入软驱用作引导盘的镜像,也可以用作虚拟机的软驱启动;

ipxe.efi 网启UEFI引导,文件比较大大约就是uefi下的ipxe.pxe,EFI引导推荐先用这个有问题就换snponly.efi; ipxe.iso 是写入光盘用作引导盘的镜像,也可以用作虚拟机的光驱启动;

ipxe.lkrn kernel相当于一个linux系统,功能更加完善,比如支持命令行操作,支持initrd等,;一般用在被GRUB,PXELINUX启动;

ipxe.pxe 网启传统引导,文件较大包含驱动多,靠自身来驱动网卡,速度快但是有概率网卡不被支持;

ipxe.usb 是写入U盘启动用的,用dd命令写;

snponly.efi 网启UEFI引导,文件小不自带驱动,大约就是uefi下的undionly.kpxe ;

undionly.kpxe 网启传统引导,文件小不自带驱动,靠UNDI通用接口或者pxe来驱动网卡,运行速度慢但是驱动几乎100%支持,但是pxe等驱动跟需要引导的系统又有可能存在兼容等问题。。

7.测试

image-20241114164404438

虚拟机测试时如遇到no space left on device 报错,请调大内存,因为ipxe引导的镜像时加载到内存里的

ipxe可手动选择自动灌装多种系统,也可以直接默认,指定boot.ipxe配置文件中choose --default exit --timeout 30000 target && goto ${target} 的target为lable name

8.配置自动安装系统脚本

Centos7

创建ks目录,注意该目录和boot.pxe配置文件相关,因此无法改变,如果自定义请一并修改boot.ipxe

mkdir /pxe/http/ks /pxe/http/init

编辑 /pxe/http/ks/ks-c7.cfg

#platform=x86, AMD64, 或 Intel EM64T
#version=DEVEL
# Install OS instead of upgrade
install
# Keyboard layouts
keyboard 'cn'

network --bootproto=dhcp

# Root password 可调用python模块生成加密后的密码 python -c 'import crypt,getpass;pw="admin";print(crypt.crypt(pw))'
rootpw --iscrypted $6$cAYWJLiTQ1P6FnlX$09dPD7qwdfzWYIPfCteBUL9Guhcnc7YqOfJEwYrDwN1dU1z7SSrgPXWTxGzG8P/KexwutVANvUi7P.FGzpO7x/


# System language
lang zh_CN.UTF-8
# System authorization information
auth  --useshadow  --passalgo=sha512

# Use graphical install
graphical

firstboot --disable
# SELinux configuration
selinux --disabled

# Firewall configuration
firewall --disabled
# Halt after installation
#poweroff
reboot

# System timezone
timezone Asia/Shanghai


%include /tmp/part-include
%pre

disk=$(while read line;do awk 'BEGIN{} {if ($2 == "0" && $4 == "nvme0n1") print $4} END{}';done < /proc/partitions)
size=$(while read line;do awk 'BEGIN{} {if ($2 == "0" && $4 == "nvme0n1") print $3} END{}';done < /proc/partitions)
if [ -z "$disk" ];then
    disk=$(while read line;do awk 'BEGIN{} {if ($2 == "0" && $4 == "sda") print $4} END{}';done < /proc/partitions)
    size=$(while read line;do awk 'BEGIN{} {if ($2 == "0" && $4 == "sda") print $3} END{}';done < /proc/partitions)
    if [ -z "$disk" ];then
        disk=$(while read line;do awk 'BEGIN{} {if ($2 == "0" && $4 == "vda") print $4} END{}';done < /proc/partitions)
        size=$(while read line;do awk 'BEGIN{} {if ($2 == "0" && $4 == "vda") print $3} END{}';done < /proc/partitions)
    fi
fi

# partition
if [ $size -lt 2000000000 ];then
cat > /tmp/part-include << EOF
# System bootloader configuration
bootloader --location=mbr --boot-drive=$disk

# Partition clearing information
clearpart --all --initlabel --drives=$disk

# Disk partitioning information
#part /boot/efi --fstype="efi" --ondisk=$disk --size=600 --fsoptions="umask=0077,shortname=winnt"
#part biosboot --fstype="biosboot" --ondisk=$disk --size=1
part /boot --fstype="ext4" --ondisk=$disk --size=1024
part /     --fstype="xfs" --grow --ondisk=$disk --size=1
EOF
else
cat > /tmp/part-include << EOF
# System bootloader configuration
bootloader --location=mbr --boot-drive=$disk

# Partition clearing information
clearpart --all --initlabel --drives=$disk

# Disk partitioning information
#part /boot/efi --fstype="efi" --ondisk=$disk --size=600 --fsoptions="umask=0077,shortname=winnt"
part biosboot --fstype="biosboot" --ondisk=$disk --size=1
part /boot    --fstype="ext4" --ondisk=$disk --size=1024
part /        --fstype="xfs" --grow --ondisk=$disk --size=1
EOF
fi

if [ -d /sys/firmware/efi ] ; then
        sed -i 's/^[^#].*biosboot*/#&/g' -i /tmp/part-include
        sed -i '/^#.*efi/s/^#//g'   -i /tmp/part-include
fi

%end

%packages
@^minimal
@core
chrony
kexec-tools

%end

#%post   #脚本段,可以放脚本或命令,需要根据实际位置修改脚本
%post --log=/var/log/kickstart-post.log
wget http://192.168.1.22/init/init.sh
sh init.sh
rm init.sh -f
%end

ubuntu

创建目录

mkdir -p /pxe/http/autoinstall
cd /pxe/http/autoinstall
touch meta-data user-data vendor-data

在autoinstall目录分别创建meta-data、user-data、vendor-data文件,内容一样

#cloud-config
autoinstall:
  version: 1
  identity:
    hostname: ubuntu
    password: $6$cAYWJLiTQ1P6FnlX$09dPD7qwdfzWYIPfCteBUL9Guhcnc7YqOfJEwYrDwN1dU1z7SSrgPXWTxGzG8P/KexwutVANvUi7P.FGzpO7x/
    realname: ubuntu
    username: ubuntu
  network:
    network:
      version: 2
      ethernets:
        id0:
          match:
            macaddress: BC:24:11:A4:99:10
          dhcp4: true
  ssh:
    install-server: true
    allow-pw: true
  storage:
    layout:
        name: lvm
  apt:
    preserve_sources_list: false
  packages:
    - openssh-server
  late-commands:
    - echo 'SELINUX=disabled' > /target/etc/selinux/config
    - ufw disable

这里在不知网卡名的情况下,用mac地址匹配获取dhcp地址,兼容BOIS和UEFI

如果机器有多块盘,storage可以指定下

非LVM

BOIS版

    config:
    - {ptable: gpt, path: /dev/sda, wipe: superblock-recursive, preserve: false, name: '', grub_device: true, type: disk, id: disk-sda}
    - {device: disk-sda, size: 536870912, wipe: superblock, flag: bios_grub, number: 1, preserve: false, grub_device: false, type: partition, id: partition-0}
    - {device: disk-sda, size: -1, wipe: superblock, flag: '', number: 2, preserve: false, type: partition, id: partition-1}
    - {fstype: ext4, volume: partition-1, preserve: false, type: format, id: format-1}
    - {device: format-1, path: /, type: mount, id: mount-1}

UEFI版

    - {ptable: gpt, path: /dev/sda, wipe: superblock-recursive, preserve: false, name: '', grub_device: false, type: disk, id: disk-sda}
    - {device: disk-sda, size: 536870912, wipe: superblock, flag: boot, number: 1,preserve: false, grub_device: true, type: partition, id: partition-0}
    - {fstype: fat32, volume: partition-0, preserve: false, type: format, id: format-0}
    - {device: disk-sda, size: -1, wipe: superblock, flag: '', number: 2,preserve: false, type: partition, id: partition-1}
    - {fstype: ext4, volume: partition-1, preserve: false, type: format, id: format-1}
    - {device: format-1, path: /, type: mount, id: mount-1}
    - {device: format-0, path: /boot/efi, type: mount, id: mount-0}