使用 NGINX 基于 MAC 地址前缀匹配实现 iPXE 配置动态分发

 

iPXE 是非常好用的网络引导固件,可以实现强大灵活的网络引导(比如坏人的 tuna-ipxe 项目可以直接从镜像站启动多种 Linux 的安装器或者 Live 环境)。通常 iPXE 需要使用系统自带的 PXE 固件或者其他方式链式加载,并通过 DHCP option 等方式获取配置文件。

在实际部署中,经常会遇到不同型号的机器需要分发不同配置的情况。特别地,在使用(还是坏人的)desktop-builder 项目部署系统时,需要给不同型号的主机传入不同的 kernel cmdline,以正确利用不同的硬盘空闲空间情况(因为机房中同样型号的机器通常分区也是一致的)。我们知道,不同型号的机器通常具有不同的 MAC 地址前缀(前 24 位分配给设备厂商),因此即可实现配置动态分发。但 iPXE 没有字符处理功能,因此还需借助 NGINX 进行请求重写。

首先是静态的 main.ipxe(带有默认配置):

#!ipxe
set custom_var default_value
chain custom.ipxe?mac=${netX/mac}

kernel vmlinuz initrd=initrd.img foo=${custom_var}
initrd initrd.img

boot

请求 custom.ipxe 的时候带上了启动网卡的 MAC 地址,此时在 NGINX 中就可以进行前缀匹配和分发(重定向):

map $arg_mac $pxe_custom_file {
  "~^aa:bb:cc:.*$" client_type_1.ipxe;
  "~^dd:ee:ff:.*$" client_type_2.ipxe;
  "~^de:ad:be:.*$" client_type_3.ipxe;
  default client_dummy.ipxe;
}

server {
  location /custom.ipxe {
    rewrite ^/(.*)?(.*)$ /$pxe_custom_file?$1 redirect;
  }
}

然后在 map 配置的对应文件里面书写型号相关的配置:

#!ipxe
# client_type_1.ipxe
set custom_var foo

#!ipxe
# client_type_2.ipxe
set custom_var bar

#!ipxe
# client_type_2.ipxe
set custom_var baz


#!ipxe
# client_dummy.ipxe
# deliberately left empty - fallback to default value in main.ipxe

也可以选择把默认配置的设置从 main.ipxe 转移到 client_dummy.ipxe 中。当然,如果 MAC 前缀不足以区分时,就需要采用其他办法了。