开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情”
基于 Ubuntu Server 的 PXE 自动装机环境的搭建说明
文档说明
本文档,将介绍通过在 Ubuntu 18.04.5 Server 系统上,搭建一套 PXE 自动装机环境(基于DHCP + TFTP + Subiquity),用于批量安装 Ubuntu 20.04.4 Live Server 系统。
基本信息
- PXE Server:
- 系统:Ubuntu 18.04.5
- IP地址:10.0.0.4
- 网络:仅环境部署时需要公网访问
- 硬件配置:常规即可,无特殊需求,根据装机数量适当调整
- Node:
- 系统:无操作系统(自行准备 Ubuntu 20.04.4 live server 镜像)
- IP地址:根据 PXE Server DHCP 动态分配
- 网络:需要跟 PXE Server 在同一交换机下
- 硬件配置:内存需 >= 6G(用于加载系统镜像文件)
- 引导方式:UEFI(引导方式默认不是 UEFI 的主板,需在 BIOS 中设置 Boot 的模式为 UEFI ,禁用 security boot,并且允许从网络启动)
手动部署环境
1. 系统准备
测试环境:
- 在 VMWare 中创建一个系统为 Ubuntu 18.04.5 的虚机,并添加两块网卡:
- 一块为 VMnet1,模式 NAT,用于访问公网下载依赖包
- 一块为 VMnet2,模式仅主机,并在虚拟网络编辑器中,将网卡对应子网地址设置为
10.0.0.0,掩码255.255.255.0,用于模拟二层交换机。
- 虚机系统装好后,配置 PXE Server 的静态IP
root@server:/etc/netplan# cat 02-netcfg.yaml
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
ens34:
addresses: [10.0.0.4/24]
gateway4: 10.0.0.1
root@server:/etc/netplan# netplan apply
# 双网卡模式,为避免虚机 NAT 访问公网失败,需要手动清理下新网卡的默认路由
root@server:/etc/netplan# ip route del default via 10.0.0.1
生产环境:
- 可以考虑通过以下两种方式进行操作:
- 现场找一台物理服务器上手动安装(IPMI or U盘启动) Ubuntu 18.04.5 Server 系统来部署 PXE Server,部署环境时需要能访问公网,部署完成后可再接入内网进行批量安装。
- 提前在自己的 esxi 虚机上部署 PXE Server 并打包成镜像,现场找一台物理服务器上安装 esxi 虚拟化,并将 PXE Server 镜像导入使用(待验证)
系统准备好之后,想要通过脚本快速部署 PXE Server 环境,请查看自动部署环境这一步。若想了解详细的安装过程,则继续往下看。
2. 软件安装
需要通过 apt-get 安装以下软件包:
root@server:~# apt-get -y install tftpd-hpa apache2 isc-dhcp-server whois
- tftpd-hpa :用来给 Node 提供引导及驱动文件
- apache2 :用来给 Node 提供镜像、应答文件以及一些自定义的文件脚本等
- isc-dhcp-server:用来给 Node 分配可用的IP地址
3. 配置 tftp server (apache)
配置 tftp 配置,启动 apache 服务:
root@server:~# cat > /etc/apache2/conf-available/tftp.conf <<EOF
<Directory /var/lib/tftpboot>
Options +FollowSymLinks +Indexes
Require all granted
</Directory>
Alias /tftp /var/lib/tftpboot
EOF
root@server:~# a2enconf tftp
root@server:~# systemctl restart apache2
目录:
/var/lib/tftpboot/作为 tftp 的主要上传目录
4. 镜像及引导文件准备
将 Ubuntu 20.04.4 Live Server 系统镜像上传或下载到 /var/lib/tftpboot/目录
root@server:~# wget https://old-releases.ubuntu.com/releases/focal/ubuntu-20.04.4-live-server-amd64.iso -O /var/lib/tftpboot/ubuntu-20.04.4-live-server-amd64.iso
准备内核文件、虚拟文件系统:
root@server:~# mount /var/lib/tftpboot/ubuntu-20.04.4-live-server-amd64.iso /mnt/
root@server:~# cp /mnt/casper/vmlinuz /var/lib/tftpboot/
root@server:~# cp /mnt/casper/initrd /var/lib/tftpboot/
root@server:~# umount /mnt
准备网络引导程序(Grub2)
root@server:~# wget http://archive.ubuntu.com/ubuntu/dists/focal/main/uefi/grub2-amd64/current/grubnetx64.efi.signed -O /var/lib/tftpboot/grubx64.efi
准备 Grub 配置
root@server:~# mkdir -p /var/lib/tftpboot/grub
root@server:~# cat > /var/lib/tftpboot/grub/grub.cfg <<EOF
default=autoinstall
timeout=0
timeout_style=menu
menuentry "Focal Live Installer - automated" --id=autoinstall {
echo "Loading Kernel..."
linux /vmlinuz ip=dhcp url=http://10.0.0.4/tftp/ubuntu-20.04.4-live-server-amd64.iso autoinstall ds=nocloud-net\;s=http://10.0.0.4/tftp/
echo "Loading Ram Disk..."
initrd /initrd
}
menuentry "Focal Live Installer" --id=install {
echo "Loading Kernel..."
linux /vmlinuz ip=dhcp url=http://10.0.0.4/tftp/ubuntu-20.04.4-live-server-amd64.iso
echo "Loading Ram Disk..."
initrd /initrd
}
EOF
5. 配置 DHCP
配置 DHCP 的地址池,可根据内网情况对应修改(注意生产环境下的网络隔离,避免误重装):
root@server:~# cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.bak
root@server:~# cat > /etc/dhcp/dhcpd.conf <<EOF
ddns-update-style none;
subnet 10.0.0.0 netmask 255.255.255.0 {
option routers 10.0.0.1;
option domain-name-servers 114.114.114.114;
option subnet-mask 255.255.255.0;
range dynamic-bootp 10.0.0.200 10.0.0.220; # Node 地址池
default-lease-time 21600;
max-lease-time 43200;
next-server 10.0.0.4; # pxe server IP
filename "grubx64.efi"; # 网络引导程序
}
EOF
root@server:~# systemctl restart isc-dhcp-server
6. 准备自动应答文件 (cloud.init config)
准备meta-data文件:
root@server:~# cat > /var/lib/tftpboot/meta-data <<EOF
instance-id: autoinstall
EOF
准备user-data文件:
root@server:/var/lib/tftpboot# cat > user-data <<'EOF'
#cloud-config
autoinstall:
version: 1
apt:
primary:
- arches: [default]
uri: http://mirrors.aliyun.com/ubuntu
# The passwords are all 000000
user-data:
timezone: Asia/Shanghai
disable_root: false
chpasswd:
list: |
root:$6$UenIfx4J$MXuFvAbjNjwotUl6CtEtwC.1SnlPqMkBd7oHg02XZ1iNk97eMglUrRO1hQUVvOZEf3M/aEhgyrQ/gTDx4fizz/
identity:
hostname: node
password: $6$m/xrHiECoB3upm$qVLuNKyH67prn/uOKlM9soMSIugK.Bzy8jU.TpYDQhLRDvTQtn1ga6Hv0musEMbIUZNV1AmIwM6r/59ZfRA8X0
username: test
keyboard: {layout: us, variant: ''}
locale: en_US.UTF-8
ssh:
install-server: true
storage:
grub:
reorder_uefi: False
config:
- {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}
late-commands:
- curtin in-target --target=/target -- wget -P /root/ http://10.0.0.4/tftp/bash/init.sh
- curtin in-target --target=/target -- wget -P /root/ http://10.0.0.4/tftp/bash/network.sh
- curtin in-target --target=/target -- bash /root/init.sh
EOF
- user-data 文件是进行系统自动安装的应答文件,如果对系统安装有特殊需求,可以对此文件进行修改。当某些需求不知道如何修改配置时,可以先手动安装一次 ubuntu 20.04.4,在 /var/log/installer/ 目录下会生成一个 autoinstall-user-data,在根据手动安装的系统配置进行修改。
- 也可以参考官方文档资料:ubuntu.com/server/docs…
6. 准备初始化脚本
我们还可以通过脚本,对安装好的系统进行初始化操作,下面是两个网络上找到的脚本,可以根据实际情况进行修改使用:
- init.sh:用于在系统成功重启之前,在安装成功并安装了所有更新和软件包之后运行的初始化脚本。
- network.sh:用于快速修改网络配置。在装好的系统上执行此脚本,输入IP,即可将动态地址换成静态地址。
root@server:~# mkdir /var/lib/tftpboot/bash
root@server:~# cd /var/lib/tftpboot/bash/
root@server:/var/lib/tftpboot/bash# vim init.sh
root@server:/var/lib/tftpboot/bash# vim network.sh
init.sh:
#!/bin/bash
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart sshd
systemctl stop ufw.service
systemctl disable ufw.service
echo -e "NTP=ntp1.aliyun.com\nFallbackNTP=ntp.ubuntu.com" >> /etc/systemd/timesyncd.conf
systemctl restart systemd-timesyncd
cat >> /etc/security/limits.conf << EOF
* soft nofile 655350
* hard nofile 655350
* soft nproc 655350
* hard nproc 655350
root soft nofile 655350
root hard nofile 655350
root soft nproc 655350
root hard nproc 655350
EOF
rm -rf /root/init.sh
network.sh:
#!/bin/bash
cd /etc/netplan
cp *.yaml network.yaml.bak
read -p "please ip address: " IP
Gateway=`echo $IP | awk -F '.' '{print $1"."$2"."$3".2"}'`
sed -i 's#critical: true#addresses: ['${IP}'/24]#' *.yaml
sed -i '/dhcp-identifier: mac/d' *.yaml
sed -i '0,/dhcp4: true/{s/dhcp4: true/gateway4: '${Gateway}'/}' *.yaml
netplan apply
cd
自动部署环境
1. 创建 autoinstall 目录
root@server:~# mkdir autoinstall
2. 上传系统镜像
将 Ubuntu 20.04.4 Live Server 系统镜像上传或下载到 /root/autoinstall目录
root@server:~# wget https://old-releases.ubuntu.com/releases/focal/ubuntu-20.04.4-live-server-amd64.iso -O /root/autoinstall/ubuntu-20.04.4-live-server-amd64.iso
生产环境,可以提前下载好镜像,然后通过挂载 U盘的方式上传到 autoinstall 目录(安装脚本上传同此方法)。
Ubuntu 系统识别 exFat 格式 U盘 的方法:
apt-get install exfat-fuse exfat-utilsmount /dev/sdb1 /mnt
3. 准备自动安装脚本
将 autoinstall.sh、init.sh、network.sh 三个脚本,根据实际情况修改,并上传到 /root/autoinstall目录。
- autoinstall.sh:
#!/bin/bash
# pxe server IP 相关
pxe_default_server='10.0.0.4'
# root 密码和普通用户 test 密码
root_passwd=`mkpasswd -m sha-512 '123456'`
test_passwd=`mkpasswd -m sha-512 '123456'`
# dhcp 相关
dhcp_subnet_ip='10.0.0.0'
dhcp_pxe_gateway='10.0.0.1'
dhcp_subnet_mask='255.255.255.0'
dhcp_ip_range='10.0.0.200 10.0.0.220'
# Install pkg
apt-get -y install tftpd-hpa apache2 isc-dhcp-server whois
# tftp
cat > /etc/apache2/conf-available/tftp.conf <<EOF
<Directory /var/lib/tftpboot>
Options +FollowSymLinks +Indexes
Require all granted
</Directory>
Alias /tftp /var/lib/tftpboot
EOF
a2enconf tftp
systemctl restart apache2
cp ubuntu-20.04.4-live-server-amd64.iso /var/lib/tftpboot/
mount /var/lib/tftpboot/ubuntu-20.04.4-live-server-amd64.iso /mnt/
cp /mnt/casper/vmlinuz /var/lib/tftpboot/
cp /mnt/casper/initrd /var/lib/tftpboot/
umount /mnt
wget http://archive.ubuntu.com/ubuntu/dists/focal/main/uefi/grub2-amd64/current/grubnetx64.efi.signed -O /var/lib/tftpboot/grubx64.efi
mkdir /var/lib/tftpboot/bash
cp init.sh /var/lib/tftpboot/bash
cp network.sh /var/lib/tftpboot/bash
mkdir -p /var/lib/tftpboot/grub
cat > /var/lib/tftpboot/grub/grub.cfg <<'EOF'
default=autoinstall
timeout=0
timeout_style=menu
menuentry "Focal Live Installer - automated" --id=autoinstall {
echo "Loading Kernel..."
linux /vmlinuz ip=dhcp url=http://${pxe_default_server}/tftp/ubuntu-20.04.4-live-server-amd64.iso autoinstall ds=nocloud-net\;s=http://${pxe_default_server}/tftp/
echo "Loading Ram Disk..."
initrd /initrd
}
menuentry "Focal Live Installer" --id=install {
echo "Loading Kernel..."
linux /vmlinuz ip=dhcp url=http://${pxe_default_server}/tftp/ubuntu-20.04.4-live-server-amd64.iso
echo "Loading Ram Disk..."
initrd /initrd
}
EOF
sed -i 's#${pxe_default_server}#'${pxe_default_server}'#g' /var/lib/tftpboot/grub/grub.cfg
cat > /var/lib/tftpboot/meta-data <<EOF
instance-id: focal-autoinstall
EOF
cat > /var/lib/tftpboot/user-data <<'EOF'
#cloud-config
autoinstall:
version: 1
apt:
primary:
- arches: [default]
uri: http://mirrors.aliyun.com/ubuntu
user-data:
timezone: Asia/Shanghai
disable_root: false
chpasswd:
list: |
root:${root_passwd}
identity:
hostname: node
password: ${test_passwd}
username: test
keyboard: {layout: us, variant: ''}
locale: en_US.UTF-8
ssh:
install-server: true
storage:
grub:
reorder_uefi: False
config:
- {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}
# packages:
# - linux-generic-hwe-20.04-edge
late-commands:
- curtin in-target --target=/target -- wget -P /root/ http://${pxe_default_server}/tftp/bash/init.sh
- curtin in-target --target=/target -- wget -P /root/ http://${pxe_default_server}/tftp/bash/network.sh
- curtin in-target --target=/target -- bash /root/init.sh
EOF
sed -i 's#${root_passwd}#'${root_passwd}'#' /var/lib/tftpboot/user-data
sed -i 's#${test_passwd}#'${test_passwd}'#' /var/lib/tftpboot/user-data
sed -i 's#${pxe_default_server}#'${pxe_default_server}'#g' /var/lib/tftpboot/user-data
cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.bak
cat > /etc/dhcp/dhcpd.conf <<EOF
ddns-update-style none;
subnet ${dhcp_subnet_ip} netmask ${dhcp_subnet_mask} {
option routers ${dhcp_pxe_gateway};
option domain-name-servers 114.114.114.114;
option subnet-mask 255.255.255.0;
range dynamic-bootp ${dhcp_ip_range};
default-lease-time 21600;
max-lease-time 43200;
next-server ${pxe_default_server};
filename "grubx64.efi";
}
EOF
systemctl restart tftpd-hpa apache2 isc-dhcp-server
[[ $? == 0 ]] && echo "PXE Server 安装完成!"
- init.sh
#!/bin/bash
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart sshd
systemctl stop ufw.service
systemctl disable ufw.service
echo -e "NTP=ntp1.aliyun.com\nFallbackNTP=ntp.ubuntu.com" >> /etc/systemd/timesyncd.conf
systemctl restart systemd-timesyncd
cat >> /etc/security/limits.conf << EOF
* soft nofile 655350
* hard nofile 655350
* soft nproc 655350
* hard nproc 655350
root soft nofile 655350
root hard nofile 655350
root soft nproc 655350
root hard nproc 655350
EOF
rm -rf /root/init.sh
- network.sh:
#!/bin/bash
cd /etc/netplan
cp *.yaml network.yaml.bak
read -p "please ip address: " IP
Gateway=`echo $IP | awk -F '.' '{print $1"."$2"."$3".2"}'`
sed -i 's#critical: true#addresses: ['${IP}'/24]#' *.yaml
sed -i '/dhcp-identifier: mac/d' *.yaml
sed -i '0,/dhcp4: true/{s/dhcp4: true/gateway4: '${Gateway}'/}' *.yaml
netplan apply
cd
4. 执行脚本自动安装
在autoinstall目录,执行 autoinstall.sh脚本进行自动安装:
root@server:~/autoinstall# bash autoinstall.sh
....安装过程省略
PXE Server 安装完成!
装机环节
测试环境
- 如果使用 VMware 测试,请修改虚拟机的引导方式为UEFI(默认为BIOS)。
- 打开虚拟机设置,选择选项,点击高级,找到固件类型,选择UEFI。
- 给虚拟机添加 VMnet2 网卡,模拟 PXE Server 和 虚拟机 Node 在同一交换机下。
- 使用 VMware 测试,建议分配给虚拟机内存大点(必须大于镜像文件,像20.04.4,建议6G)。因为在安装过程中,是需要将镜像文件拷贝到内存的,如果虚拟机的内存不足会报错。
生产环境
- 如果使用物理机,需在 BIOS 中设置 Boot 的模式为 UEFI ,禁用 security boot,并且允许从网络进行引导启动。
- 待装机的物理机需要和 PXE Server 服务器在同一交换机下。
- 物理机的内存一般都大于6G,不排除个别类型服务器内存过小,影响自动装机过程。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情”