通过 PXE 批量安装 CentOS

# 概述

PXE(Preboot Execution Environment) 用于从 BIOS/EFI 启动计算机,也可以安装系统,流程如下。

  • 客户端从 Network 启动,发送 DHCP 请求。
  • DHCP 服务器发送一个带有 next-server 信息的响应。
  • 客户端发送 DHCPREQUEST/DHCPINFORM 请求。
  • DHCP 服务器发送 TFTP 服务器地址和所需的文件名。
  • 客户端从 TFTP 服务器下载这个文件,一般是很小的引导文件。
  • pxelinux/grub 读取配置文件,下载相关文件。
  • 进入安装程序,下载 Anaconda 的 Kickstart 自动应答脚本,按预设自动安装。

# 环境准备

手动安装一台机器(本例中使用 CentOS 7.8 Minimal),安装时选择非图形界面,这样装好后在$HOME目录下会生成 Kickstart 文件,保存起来作为模板。

指定一台机器作为 PXE Server。为方便起见,先关闭防火墙(可以手动放行 tftp 和 http 端口)和 SELinux(会阻止网络访问本地文件)。

systemctl stop firewalld.service
systemctl disable firewalld.service
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0

提前下载好安装镜像 (opens new window)放在$HOME目录备用,文件名为CentOS-7-x86_64-Minimal-2003.iso

Optional: 可用 Dnsmasq 替代 dhcp 和 tftp-server,具体参见 Ubuntu 篇

interface=eth0
bind-interfaces
dhcp-range=172.16.119.1,172.16.119.254
dhcp-boot=uefi/shim.efi
dhcp-host=172.16.119.1

enable-tftp
tftp-root=/var/lib/tftpboot

# DHCP Server

服务器从 Network 启动时,会加载网卡内置的 DHCP Client,寻找网段中的 DHCP Server 分配 IP,顺便获取 TFTP Server 的 IP。

网段中只允许存在一个 DHCP Server,如果你的网关是静态 IP,那么可以自己搭一个,否则需要更改网关配置或者关掉已有 DHCP Server 再自己搭。PXE Server 的网关最好不要和路由器在同一个网段。

安装 DHCP Server 为 PXE 设备分配 IP,dhcpd的配置文件位于/etc/dhcp/dhcpd.conf

yum install dhcp -y

集群内有两种配置的服务器,一种系统装在 NVMe SSD 中(仅支持 UEFI 引导),故需从 UEFI PXE 启动。另一种的系统盘是 SATA SSD,因为管理口设置 UEFI PXE 失败(或许是个 BUG),就用 Legacy PXE 启动。

为了一次性装完所有机器,可以在 DHCP Server 配置中加入判断,区分客户端是普通 DHCP,Legacy PXE 还是 UEFI PXE。

option pxe-system-type code 93 = unsigned integer 16;

subnet 172.16.22.0 netmask 255.255.255.0 {
  range 172.16.22.2 172.16.22.254;
  option routers 172.16.22.1;
  option subnet-mask 255.255.255.0;

  next-server 172.16.22.1;

  if option pxe-system-type = 00:07 {      
    filename "uefi/shim.efi";
  } else if option pxe-system-type = 00:09 {
    filename "uefi/shim.efi";
  } else {
    filename "pxelinux.0";
  }
}

shim 是一个 EFI 应用程序,它可以尝试运行各种 EFI 引导,如果检测到 UEFI PXE 就从这里启动。

SYSLINUX(pxelinux.0) 是 Linux 的启动加载器,可以简化 Linux 的首次安装,Legacy PXE 启动就用这个。

next-server 提示 TFTP Server 的 IP 地址,一般是本机。

# TFTP Server

PXE 支持基于 UDP 的 TFTP 协议,在上一步中定义的引导镜像(shim & pxelinux.0),使用 TFTP 服务器提供。

yum install xinetd tftp-server –y

xinetd 是 TFTP 的守护进程,只需启动 xinetd 就能拉起 TFTP。默认根目录在/var/lib/tftpboot,后面会把引导文件放这儿。

systemctl start xinetd
systemctl enable xinetd

# HTTP Server

TFTP 传输基于小块(512KB)的 UDP 协议,只适合传输小型文件。软件包等大文件还是用 HTTP 下载,比如 NGINX。

yum install epel-release
yum install nginx

CentOS 下,默认配置文件在/etc/nginx/nginx.conf,可以添加autoindex on打开文件索引。root 字段定义了网络根目录,网络安装组件都放这儿。

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  _;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
        autoindex on;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

# GRUB2 网络启动

# 启动镜像

准备 CentOS 7 的 UEFI 启动镜像,可以从 RPM 获取。

yum install grub2-efi-x64 shim-x64

建立一个专门存放 uefi 启动文件的目录,也就是刚才写在 DHCP Server 配置中的路径。

mkdir /var/lib/tftpboot/uefi

复制相关文件,修改文件权限。

cp -p /boot/efi/EFI/centos/*.efi /var/lib/tftpboot/uefi/
chmod 755 /var/lib/tftpboot/uefi/*.efi

Optional: 或者从 ISO 镜像复制过来也行,适用于非 CentOS 宿主机。

mkdir /centos
mkdir $HOME/uefi_tmp
mount -t iso9660 CentOS-7-x86_64-Minimal-2003.iso /centos -o loop,ro
cp -pr /centos/Packages/shim-version-architecture.rpm $HOME/uefi_tmp
cp -pr /centos/Packages/grub2-efi-version-architecture.rpm $HOME/uefi_tmp

Extract the packages:

cd $HOME/uefi_tmp
rpm2cpio shim-version-architecture.rpm | cpio -dimv
rpm2cpio grub2-efi-version-architecture.rpm | cpio -dimv

复制 EFI 启动镜像到 TFTP 目录。

cp $HOME/uefi_tmp/boot/efi/EFI/centos/shim.efi /var/lib/tftpboot/
cp $HOME/uefi_tmp/boot/efi/EFI/centos/grubx64.efi /var/lib/tftpboot/

# GRUB 引导

GRUB 的配置文件grub.cfg需要放在和grubx64.efi相同的目录。在本例中,创建/var/lib/tftpboot/uefi/grub.cfg配置文件。

在下面的栗子中,linuxefi字段定义的 Vmlinuz 是 Linux 内核可执行文件。Vmlinuz 是一个压缩的 Linux 内核,它将 OS 加载到内存中,这样服务器就可以启动了。inst.ks字段定义的是等会要搞的 Kickstart 自动安装配置文件。initrdefi字段指向 Initrd 镜像,它可以通过引导加载器初始化 RAM 磁盘,然后将其挂载为根文件系统,并从中运行 CentOS 安装程序。

除了inst.ks放在 Nginx,别的文件用 TFTP 托管。

set default="0"

function load_video {
  insmod efi_gop
  insmod efi_uga
  insmod video_bochs
  insmod video_cirrus
  insmod all_video
}

load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod ext2
set timeout=6

menuentry 'Install CentOS Linux 7.8' --class fedora --class gnu-linux --class gnu --class os {
  linuxefi CentOS-7.8/vmlinuz ip=dhcp inst.ks=http://172.16.22.1:80/supermicro.cfg
  initrdefi CentOS-7.8/initrd.img
}

# SYSLINUX 引导

Syslinux 一个是能够通过 PXE 从设备/CD/网络启动的引导加载程序集合。在本例中用于 Legacy PXE。

安装 syslinux,复制引导镜像到 TFTP 根目录。

yum -y install syslinux
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/

创建 pxelinux 的配置文件。

mkdir /var/lib/tftpboot/pxelinux.cfg
vim /var/lib/tftpboot/pxelinux.cfg/default

在这个栗子中,依然能看到 vmlinuz & initrd & ks 熟悉的身影,如需修改可参照上一步。

default vesamenu.c32
prompt 1
timeout 6

display boot.msg

label linux
  menu label ^Install system
  menu default
  kernel CentOS-7.8/vmlinuz
  append initrd=CentOS-7.8/initrd.img ip=dhcp ks=http://172.16.22.1/supermicro.cfg

# Kickstart

建议先用U盘在非图形界面手动安装一台,复制 $HOME 目录下的anaconda-ks.cfg文件作为参考。

以下配置中,系统将从网络安装,url定义了网络源,最好使用内网地址。rootpw指定了root账户密码。系统装在nvme1n1中,并使用 LVM 自动分区。

#version=DEVEL
install
# System authorization information
auth --enableshadow --passalgo=sha512
# Use text mode install
text
# Run the Setup Agent on first boot
firstboot --enable
ignoredisk --only-use=nvme1n1
# Keyboard layouts
keyboard --vckeymap=us --xlayouts=''
# System language
lang en_US.UTF-8
# Use network installation
url --url="http://172.16.22.1/CentOS-7.8"
# Reboot after installation
reboot

# Network information
network --bootproto=dhcp --device=eno1 --onboot=off --ipv6=auto --no-activate
network --bootproto=dhcp --device=eno2 --onboot=off --ipv6=auto
network --bootproto=static --device=enp33s0 --onboot=yes --ip 172.16.1.10 --netmask 255.255.0.0 --gateway 172.16.255.254 --ipv6=auto --nameserver 114.114.114.114
# Firewall configuration
firewall --disable

#Root password
rootpw --plaintext "123@def"
# SELinux configuration
selinux --disabled
# System services
services --enabled="chronyd"
# Do not configure the X Window System
skipx
# System timezone
timezone Asia/Shanghai --isUtc
# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=nvme1n1
autopart
# Partition clearing information
clearpart --all --initlabel --drives=nvme1n1

%packages
@core
chrony
kexec-tools

%end

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end

# 开始安装

可尝试通过 IPMI 工具使客户端进入 PXE 模式。后续可通过修改 Kickstart 文件自动配置静态 IP,以实现全自动装机。

概述
环境准备
DHCP Server
TFTP Server
HTTP Server
GRUB2 网络启动
启动镜像
GRUB 引导
SYSLINUX 引导
Kickstart
开始安装