在家里尝试了下跑通PXE装机流程,纯流水帐记录,能跑就行。

先说句题外话,我家里是用PVE起的虚拟机,需要注意的是创建VM时网卡型号不能选VirtIO,可能跑DHCP会有问题,选Intel E1000E是可以用的。另外如果要测试UEFI,只要把BIOS类型选成OVMF(UEFI)即可,不需要创建EFI Disk。

整个PXE流程里,主要涉及这几个玩意:

  • DHCP Server:给新来的机器分配ip,仙人指路到tftp下pxe需要的东西
  • TFTP Server:用于提供efi文件(UEFI模式)或者pxelinux(Legacy模式),以及相应的引导配置文件
  • HTTP Server:用于提供ubuntu的安装.iso和autoinstall用的user-data文件,没啥特殊要求,用nginx或者caddy都行,或者直接python起一个。
  • autoinstall:Ubuntu官方的无人值守安装工具,通过一个YAML文件描述安装过程中所有要填的配置项,从而实现完全自动化安装。

dnsmasq 配置

安装dnsmasq用作dhcp server,这个玩意自带了tftp,省事了。
我是直接把家里主路由的DHCP关了,让这家伙独自工作的。如果网络中有其他DHCP server,好像要用Proxy模式,目前还没研究。

apt update
apt install dnsmasq 

mkdir /srv/tftp

vim /etc/dnsmasq.conf
# 加一行上游dns resolver
server=server=8.8.8.8

# 编辑pxe配置内容
vim /etc/dnsmasq.d/pxe.conf

pxe.conf文件内容,需要根据对应网络设备和情况来配置网卡,网段等信息

interface=eth0
bind-interfaces
dhcp-range=10.4.0.100,10.4.0.200,255.0.0.0,12h
dhcp-option=option:router,10.0.0.1

enable-tftp
tftp-root=/srv/tftp

dhcp-match=set:bios,option:client-arch,0

dhcp-match=set:uefi64,option:client-arch,7
dhcp-match=set:uefi64,option:client-arch,9

dhcp-boot=tag:bios,pxelinux.0
dhcp-boot=tag:uefi64,bootx64.efi

启动dnsmasq服务,因为可能systemd resolved这个家伙已经把53端口给占了,所以先把它干掉再起dnsmasq。

systemctl stop systemd-resolved

systemctl restart dnsmasq

# 关了防火墙,免得捣乱
systemctl stop ufw

TFTP Server文件准备

UEFI 模式

下载个ubuntu iso然后mount

mount -o loop ubuntu-22.04.5-live-server-amd64.iso /mnt

# 下面的目录在tftp里都是固定的,不能随意改,不然可能找不到文件
cp /mnt/casper/{vmlinuz,initrd} /srv/tftp/

apt download shim-signed
dpkg-deb --fsys-tarfile shim-signed*deb | tar x ./usr/lib/shim/shimx64.efi.signed.latest -O > /srv/tftp/bootx64.efi

apt download grub-efi-amd64-signed
dpkg-deb --fsys-tarfile grub-efi-amd64-signed*deb | tar x ./usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed -O > /srv/tftp/grubx64.efi

apt download grub-common
dpkg-deb --fsys-tarfile grub-common*deb | tar x ./usr/share/grub/unicode.pf2 -O > /srv/tftp/unicode.pf2

# grub.cfg放在哪和发行版相关,这玩意应该是焊死在grubx64.efi里的,所以随便放个目录,会导致grub会找不到cfg文件,没法正常引导后续安装
mkdir /srv/tftp/grub

# 编写grub配置文件内容
vim /srv/tftp/grub/grub.cfg

/srv/tftp/grub/grub.cfg 文件内容如下,注意以下几点:

  1. ds=nocloud-net后面的;前面有个转义符不能忘记
  2. s=参数后面填的是http server中有user-data这个文件的目录路径
  3. 命令结尾有---
set default="0"
set timeout=0

if loadfont unicode ; then
  set gfxmode=auto
  set locale_dir=$prefix/locale
  set lang=en_US
fi
terminal_output gfxterm

set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
if background_color 44,0,30; then
  clear
fi

function gfxmode {
        set gfxpayload="${1}"
        if [ "${1}" = "keep" ]; then
                set vt_handoff=vt.handoff=7
        else
                set vt_handoff=
        fi
}

set linux_gfx_mode=keep

export linux_gfx_mode

menuentry 'Ubuntu 22.04.5' {
        gfxmode $linux_gfx_mode
        linux /vmlinuz $vt_handoff ip=dhcp url=http://10.4.0.12:8000/ubuntu-22.04.5-live-server-amd64.iso autoinstall ds=nocloud-net\;s=http://10.4.0.12:8000/ ---
        initrd /initrd
}

Legacy BIOS 模式

wget http://archive.ubuntu.com/ubuntu/dists/focal/main/installer-amd64/current/legacy-images/netboot/pxelinux.0
mkdir -p /srv/tftp
mv pxelinux.0 /srv/tftp/

apt install -y syslinux-common
cp /usr/lib/syslinux/modules/bios/ldlinux.c32 /srv/tftp/

mkdir /srv/tftp/pxelinux.cfg

# 编写pxelinux配置
vim /srv/tftp/pxelinux.cfg/default

/srv/tftp/pxelinux.cfg/default 文件内容,需要注意

  1. ds=nocloud-net后面的;前面没有转义符
  2. s=参数后面填的是http server中有user-data这个文件的目录路径
  3. 命令结尾有---
DEFAULT install
LABEL install
  KERNEL vmlinuz
  INITRD initrd
  APPEND root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.4.0.12:8000/ubuntu-22.04.5-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://10.4.0.12:8000/ ---

HTTP Server文件准备

先把ubuntu-22.04.5-live-server-amd64.iso放到这个目录下。

然后添加一些autoinstall的配置文件进来。

touch meta-data

vim user-data

user-data文件内容,手写或者从一个安装完的机器/var/log/installer/autoinstall-user-data抄一个过来,配置文件的内容编写参考 https://canonical-subiquity.readthedocs-hosted.com/en/latest/reference/autoinstall-reference.html
注意必须有#cloud-config开头,安装程序才能正确识别和加载

#cloud-config
autoinstall:
  version: 1
  locale: "en_US.UTF-8"
  keyboard:
    layout: "us"
    variant: ""
  identity:
    hostname: "new-machine"
    username: "eric"
    # 用"openssl passwd -6"生成一个
    password: "$6$WTiT9hNmg735gtCQ$db6Mkz3V.DF/ymHFR3R1t6/QZ4Gj87v5SladOxKqaxr2XgzQVYcwuXP3I.iBOifNY46EJDEW03zeh.qpNBm.k1"
  storage:
    layout:
      name: direct
  network:
    version: 2
    ethernets:
      eth0:
        dhcp4: true
  ssh:
    install-server: true
    allow-pw: true
  packages:
    - vim
    - curl
  late-commands:
    - echo "Autoinstall complete" > /target/root/autoinstall.log

把http server起来

python -m http.server

安装

让机器从网络启动,它在DHCP成功后会自己跑完PXE流程,加载完内核,引导ubuntu安装iso,并通过autoinstall跑完整个安装流程,整个过程不需要任何人工介入。

dnsmasq在有请求时可以看到日志,通过命令查看

journalctl -u dnsmasq -f