PXE网络安装系统之基于dnsmasq的环境搭建

一、PXE 环境概述

1.1 PXE 简介

PXE (preboot execute environment,预启动执行环境) 是由 Intel 公司设计的协议,它可以使计算机通过网络启动。当计算机通电启动时,首先执行一些硬件检测指令,紧接着就是系统引导程序,由 BIOS 把集成在网卡中的 PXE client 调入内存执行,并显示出命令菜单,用户选择后,PXE client将放置在远端的操作系统通过网络下载到本地运行。除了可以通过网络直接运行操作系统外,也可以用于通过网络来将系统安装到本地。在运维中工作中,通过 PXE 来为机房服务器批量部署系统是非常方便的。

1.2 PXE 运行环境

PXE 对运行环境没有什么特别的需求,只需能提供 dhcp、tftp、ftp/http 等 PXE 所需服务的操作系统即可。通常在 Linux 环境下搭建 PXE 服务系统。

本文使用 dnsmasq 这个小巧玲珑的软件提供 tftp 和 dhcp 服务,使用 Nginx 来提供 http 服务

1.3 PXE 启动/安装系统原理

当计算机通电启动时,首先执行一些硬件检测指令,检测通过后紧接着就是执行系统引导程序,由 BIOS 把集成在网卡中的 PXE client 调入内存执行,并显示出命令菜单,提供给用户选择操作系统的引导方式。比如 DELL 的服务器在出现开机 LOGO 画面后通过键入 F12 来进入 PXE 引导,Vmware 新创建的虚拟机在第一次启动的时候如果没有装载光驱或者ISO镜像,则会尝试通过网络引导。如果是笔记本或者台式机可以在开机的时候进入引导菜单,然后选择通过网卡设备启动。

Tips: 计算机操作系统常见的引导方式有:

  • 本地硬盘(系统盘)
  • 光驱/U盘
  • PXE(网络引导)

当主机进入 PXE 引导界面后,PXE client 会向网络中的 dhcp 服务器请求IP地址,dhcp 服务器发现是 PXE client 的请求,会为其分配IP 并和 引导程序的访问地址(dhcp 服务中的 dhcp-boot 配置项指定)一并返回给 PXE client。这个引导程序一般是名为 pxelinux.0 的文件,这个文件是通过 tftp 协议发送给 PXE client 的。当客户端成功获取到引导文件和引导文件的相关配置文件后就成功加载出引导菜单。这个菜单是通过更改 pxelinux.0 的配置文件来设置的。

如果在30秒内没做任何选择则默认从本地磁盘启动,这样就避免了某些将PXE启动作为第一启动项的服务器重启后误进入重装系统环境。在进入PXE 选择菜单(操作系统引导菜单)后,当选择了某个系统引导菜单项的时候,比如 Install CentOS7.9 for vmware 则向服务器获取根据配置文件中指定的 CentOS 内核文件和启动参数。当需要的数据都准备好后,系统则开始启动 Linux 内核,接下来的操作就跟普通的安装系统一样了,只不过需要的数据都是通过网络获取的。比如安装 CentOS 过程中需要的所有 rpm 包都是通过 ftp/http 服务从指定的 CentOS 镜像站点获取的。

如何通过 PXE 来同时安装成百上千台服务器?

在安装系统的过程中,总会遇到各种需要交互设置的地方,比如给硬盘分区,选择语言,创建用户等交互设置操作。在市面上大部分的系统安装镜像都支持通过 Kickstart 设置自动应答的方式来代替在安装过程中需要人工交互的系统安装设置操作。就像是所有问题及其答案都先写成一个文件,然后在提问的时候先从文件中找答案一样。自动应答文件(一般为ks.cfg 文件),此文件通常是在启动 Linux 内核的时候通过启动参数的方式告诉内核。

二、PXE 环境的搭建

2.1 dnsmasq 服务的安装与配置

我们使用 dnsmasq 软件来提供 tftp 和 dhcp 服务。

首先从Linux发行版的官方仓库中找找有没有 dnsmasq 的软件包,有的话,可以使用 yum(red hat类发行版)、apt(debian 类发行版)等系统包管理工具安装。

如果没有可以下载编译:

1
2
3
4
wget http://www.thekelleys.org.uk/dnsmasq/dnsmasq-2.79.tar.xz
tar xf dnsmasq-2.79.tar.xz
cd dnsmasq-2.79 && make
cp src/dnsmasq /usr/local/bin/

只需要将 dnsmasq 的二进制文件放到系统环境变量就可以了,接下来给它提供一个配置文件来告诉它要启动哪些服务。使用 /etc/dnsmasq.conf 或 源码目录下有一个官方提供的配置文件(dnsmasq.conf)模板,不过并不需要这么多的配置。在这些模板文件的基础上设置如下配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# disable dns
port=0

# enable dhcp
dhcp-range=192.168.4.10,192.168.4.200,12h   #  给客户端分配的IP地址池一定要是自己网段的
dhcp-option=3,192.168.4.254                 # DHCP 服务器的IP
dhcp-option=option:dns-server,114.114.114.114,119.29.29.29  # DNS 服务 (cat /etc/resolv.conf)
# dhcp-boot=pxelinux.0      # 前面讲解的 PXE 启动的原理 中说道的 pxelinux.0  文件
dhcp-boot=undionly.kpxe     # 此处我们使用 undionly.kpxe (下面再进行介绍)

# enable tftp
enable-tftp
tftp-root=/var/tftp         # 指定 tftp 服务的文件路径

启动 dnsmasq 服务:

1
2
3
4
dnsmasq -C dnsmasq.conf -d
# 或
systemctl enabl dnsmasq.service
systemctl start dnsmasq.service

现在基础的 dhcp 和 tftp 服务已经搭建完成了,dhcp 监听在 udp 67 端口,tftp 监听在 udp 69,使用前最好关闭服务器的 selinux 和 iptables。

2.2 安装 Nginx

也不一定非要使用 Nginx,只要是能提供通过 HTTP 协议对文件进行访问服务的程序都可以。

同样,如果可以从发行版的官方仓库安装就非常省事了,或者手动编译也可以:

1
2
3
4
5
wget http://nginx.org/download/nginx-1.14.0.tar.gz
tar xf nginx-1.14.0.tar.gz
cd nginx-1.14.0
./configure --prefix=/usr/local/nginx --without-http_rewrite_module
make -j4 && make install

因为用不到 Nginx 的 rewrite 规则,而且这个模块依赖 pcre 库,所以就去掉了,接下来简单的配置下 Nginx。

 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
# vim /usr/local/nginx/conf/nginx.conf
vim /etc/nginx/nginx.conf

# 然后写入以下内容:
worker_processes  4;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    autoindex       on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /var/www/pxeroot;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

启动 nginx 运行即可。

2.3 安装 ipxe 引导文件

为什么这里又出现了 ipxe 引导文件呢?

理论上来说,只是用 pxelinux.0 就可以引导各种系统,但是 pxelinux.0 只支持使用 tftp 协议来加载需要的文件。 tftp 在使用 UDP 传输数据,为了保证文件的完整性,tftp 自己实现了一套数据校验机制,但是却大大降低了文件传输效率,在某些未知情况下 tftp 在局域网内居然只有 KB 级别的传输速率。于是,一些支持 http 、ftp、nfs 等文件传输协议的引导程序诞生了,ipxe 就是其中一种。

ipxe 提供的引导文件针对不同使用场合又分好几种,比如 .pxe.kpxe.kkpxe 等格式的引导文件。比较常见的是 .pxe.kpxe,其中的区别可以看这里:http://etherboot.org/wiki/gpxe_imagetypes。

这里使用 undionly.kpxe 引导文件,采用链式加载的方法加载 pxelinux.0,这样就可以实现既使用 ipxe 提供的网络协议支持,还可以使用 pxelinux.0 提供的引导界面了。

编译 undionly.kpxe:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
git clone git://git.ipxe.org/ipxe.git
cd ipxe/src

# 创建 embed.ipxe 并写入如下内容:
root@debian:/var/tftp# cat embed.ipxe
#!ipxe
dhcp
chain tftp://${next-server}/menu.ipxe   # 其中 ${next-server} 会自动解析为 dhcp 服务器的地址,tftp 也搭建在这个地址上。

# 当通过 dhcp 获取到IP地址后,通过 tftp 协议请求 menu.ipxe 文件,
# 然后 ipxe 会解析和执行文件里的内容,这个文件可以说就是 ipxe 的配置文件了。

# 接着编译出 undionly.kpxe,这样 undionly.kpxe 才会默认就加载同目录下的 menu.ipxe 文件:
make bin/undionly.kpxe EMBED=embed.ipxe
cp bin/undionly.kpxe /var/tftp/

其中编译步骤需要 lzma.h 这个头文件(yum install xz-devel)。编译好的 undionly.kpxe 可以保存下来下次搭建环境的时候直接用,如果服务是搭建在 Windows 系统上也可以使用这个编译好的 undionly.kpxe 文件。

将编译好的 undionly.kpxe 文件 copy 到 tftp-root 目录 /var/tftp 下 并在 tftp-root 目录下创建 menu.ipxe 文件,配置接下来的文件都通过 http 协议来访问,并且链接到 pxelinux.0。

1
2
3
4
5
6
7
8
root@debian:/var/tftp# ls -lh
-rw-r--r-- 1 root root 119 Aug 29 18:35 menu.ipxe
-rw-r--r-- 1 root root 70K Aug 29 18:13 undionly.kpxe
root@debian:/var/tftp# cat menu.ipxe
#!ipxe
set 210:string http://192.168.3.129/pxefiles/
set 209:string pxelinux.cfg/default
chain ${210:string}pxelinux.0

其中 set 210:string 定义了请求的文件的主目录,因为之前创建的 /var/www/pxeroot 为 http 的根目录,/var/www/pxeroot/pxefiles/ 目录中存放 pxelinux.0 及相关的数据文件。其中的服务器IP地址需要替换为 http 服务的实际的服务器IP。

set 209:string 则定义了 pxelinux.0 直接加载 pxelinux.cfg/default 这个配置文件,否则 pxelinux.0 会阶梯性的查找配置文件,如果都没找到最后默认才加载 pxelinux.cfg/default。

2.4 安装 pxelinux.0 引导文件

接下来的操作就是在 /var/www/pxefiles/ 目录下进行了,因为 ipxe 启动后剩下的文件都是通过 http 协议访问的。

pxelinux.0 可以通过发行版的 syslinux 包来获取,或者也可从官网下载,这里采用从官方下载的方式:

1
2
3
4
5
6
wget https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/Testing/3.86/syslinux-3.86-pre4.tar.xz
tar xf syslinux-3.86-pre4.tar.xz
cd syslinux-3.86-pre4
cp com32/menu/vesamenu.c32 /var/www/pxeroot/pxefiles/
cp core/pxelinux.0 /var/www/pxeroot/pxefiles/
cp memdisk/memdisk /var/www/pxeroot/pxefiles/

syslinux 最新版是16年发布的 6.04,但是使用中发现无法引导 ESXI,而且 pxelinux.0 引导后还要加载好几个 .c32 文件,所以采用老一点的 3.86 版本。 接着给 pxelinux.0 提供配置文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
cd /car/www/pxeroot/pxefiles/
mkdir pxelinux.cfg
vim pxelinux.cfg/default    # 写入以下内容:

default vesamenu.c32
timeout 300

menu title Welcome to PXE server!
menu background logo.jpg
menu color border 0 #ffffffff #00000000
menu color sel 7 #ffffffff #ff000000
menu color title 0 #ffffffff #00000000
menu color tabmsg 0 #ffffffff #00000000
menu color unsel 0 #ffffffff #00000000
menu color hotsel 0 #ff000000 #ffffffff
menu color hotkey 7 #ffffffff #ff000000
menu color scrollbar 0 #ffffffff #00000000

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

这里为了界面美观使用了一张背景图片: logo.jpg,图片需要是一张 640*480 像素的 jpg 图片,并根据图片的主题颜色调整下页面边框、文字等颜色,如果不需要使用背景图片的话可以将 menu background 和 menu color 的配置项都删掉或者注释掉。

其中 timeout 300 会在引导界面 30秒 无操作就启动下面 label local 中定义为 menu default 的条目。

到这一步已经可以尝试将虚拟机或者主机通过 PXE 启动,看看是否可以加载出 PXE 引导界面了。当出现 上面 pxelinux.cfg/default 文件中 配置的 PXE 菜单(menu title 为 Welcome to PXE server!)即说明 PXE 网络启动 环境已经部署好了。

接下来在该 PXE 环境下配置所需的操作系统安装镜像 即可使用 PXE 通过网络安装 操作系统。

三、配置系统安装镜像

3.1 系统安装镜像简介

即使是通过网络安装,也是需要系统的安装镜像(常见的Linux 系统发行版 都会有 ISO 安装镜像包)。先将需要安装的系统 ISO镜像下载到本地,当然如果对自己网速很自信的话是可以直接通过公网来安装系统的。