PXE自动化安装Ubuntu 24.04的配置文件
之前都是通过PXE来自动化安装Redhat系列的,例如:Rocky9、Rocky10、CentOS7、银河麒麟 Kylin-V10、Kylin-V11、OpenEuler 24.03等。现在安装Ubuntu系列的跟红帽的不太一样,所以在这里介绍下。
创建三个文件
redhat系列:编写kickstart文件,文件名自定义,后缀是.cfg即可。
Ubuntu 24.04:需要创建三个文件,文件名是固定的,启动内核的时候系统会自动去找。通过下面日志可以验证。
10.0.0.123 - - [05/Sep/2025:13:54:35 +0800] "GET /iso/ubuntu-24.04.2-live-server-amd64.iso HTTP/1.1" 200 3213064192 "-" "Wget" 10.0.0.123 - - [05/Sep/2025:13:54:53 +0800] "GET /ks/ubuntu2404/meta-data HTTP/1.1" 200 30 "-" "Cloud-Init/24.4-0ubuntu1~24.04.2" 10.0.0.123 - - [05/Sep/2025:13:54:53 +0800] "GET /ks/ubuntu2404/user-data HTTP/1.1" 200 5562 "-" "Cloud-Init/24.4-0ubuntu1~24.04.2" 10.0.0.123 - - [05/Sep/2025:13:54:53 +0800] "GET /ks/ubuntu2404/vendor-data HTTP/1.1" 200 - "-" "Cloud-Init/24.4-0ubuntu1~24.04.2"
# 1.创建 meta-data
cat << EOF > meta-data
instancd-id:focal-autoinstall
EOF
# 2.创建 vendor-data
touch vendor-data
# 3.创建 user-data,这个是核心的文件,其他两个文件存在即可,vendor-data不需要写内容
touch user-data
# 里面的内容就是下面两个目录的。如果用lvm分区就复制 lvm版本的user-data 2.如果用普通分区的,就复制普通分区的user-data内容
# 我得lvm分区如下,根据需求可以改成自己的
[root@ubuntu-server-2404 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 100G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 99G 0 part
├─vg0-lv--swap 252:0 0 2G 0 lvm
├─vg0-lv--root 252:1 0 46G 0 lvm /
└─vg0-lv--data 252:2 0 50G 0 lvm /data
sr0 11:0 1 1024M 0 rom
[root@ubuntu-server-2404 ~]#
上传Ubuntu 24.04的iso镜像到http服务器
[root@PXE-Rocky-810 ~]# ll /var/www/html/iso/
total 3137760
-rw-r--r-- 1 root root 3213064192 Aug 28 17:54 ubuntu-24.04.2-live-server-amd64.iso
[root@PXE-Rocky-810 ~]#
lvm版本的user-data
#cloud-config
autoinstall:
version: 1
locale: en_US.UTF-8
timezone: Asia/Shanghai
keyboard:
layout: us
network:
version: 2
ethernets:
ens33:
dhcp4: true
source:
id: ubuntu-server
search_drivers: false
drivers:
install: false
kernel:
package: linux-generic
apt:
fallback: offline-install
mirror-selection:
primary:
- arches: [amd64]
uri: https://mirrors.aliyun.com/ubuntu/
- arches: [arm64]
uri: https://mirrors.aliyun.com/ubuntu-ports
security:
- arches: [amd64]
uri: https://mirrors.aliyun.com/ubuntu/
- arches: [arm64]
uri: https://mirrors.aliyun.com/ubuntu-ports
preserve_sources_list: false
storage:
config:
# --- 第1步:定义磁盘 ---
- ptable: gpt
path: /dev/sda
wipe: superblock-recursive
preserve: false
name: ''
grub_device: true
id: disk-sda
type: disk
# --- 第2步:定义分区 ---
# BIOS启动分区 - 修正配置
- device: disk-sda
size: 1048576 # 1M
flag: bios_grub
number: 1
preserve: false
grub_device: false
id: partition-0
type: partition
# /boot 分区
- device: disk-sda
size: 1073741824 # 1G
wipe: superblock
number: 2
preserve: false
grub_device: false
id: partition-1
type: partition
# LVM 物理卷分区
- device: disk-sda
size: -1 # 剩余所有空间
wipe: superblock
number: 3
preserve: false
grub_device: false
id: partition-2
type: partition
# --- 第3步:格式化 /boot 分区 ---
- fstype: ext4
volume: partition-1
preserve: false
id: format-0
type: format
# --- 第4步:定义LVM卷组 ---
- name: vg0
devices:
- partition-2
preserve: false
id: lvm_volgroup-0
type: lvm_volgroup
# --- 第5步:定义LVM逻辑卷 ---
# Swap 逻辑卷
- name: lv-swap
volgroup: lvm_volgroup-0
size: 2147483648B # 2G
wipe: superblock
preserve: false
path: /dev/vg0/lv-swap
id: lvm_partition-0
type: lvm_partition
# Root 逻辑卷
- name: lv-root
volgroup: lvm_volgroup-0
size: 49392123904B # 46G
wipe: superblock
preserve: false
path: /dev/vg0/lv-root
id: lvm_partition-1
type: lvm_partition
# Data 逻辑卷
- name: lv-data
volgroup: lvm_volgroup-0
size: 53687091200B # 50G
wipe: superblock
preserve: false
path: /dev/vg0/lv-data
id: lvm_partition-2
type: lvm_partition
# --- 第6步:格式化LVM逻辑卷 ---
# 格式化 swap
- fstype: swap
volume: lvm_partition-0
preserve: false
id: format-1
type: format
# 格式化 root
- fstype: ext4
volume: lvm_partition-1
preserve: false
id: format-2
type: format
# 格式化 data
- fstype: ext4
volume: lvm_partition-2
preserve: false
id: format-3
type: format
# --- 第7步:挂载 ---
# 挂载 root (必须最先挂载)
- path: /
device: format-2
id: mount-2
type: mount
# 挂载 boot
- path: /boot
device: format-0
id: mount-0
type: mount
# 挂载 data
- path: /data
device: format-3
id: mount-3
type: mount
identity:
hostname: ubuntu-server-2404
username: admin
password: "$6$N2/cWyyb47BdwNKH$slGINzTOLENrD6..QOTSSdhTuH.JGkmuo2VtkevZBT0nPCzfoazUAQF6MGe2Xxs1Tvkdhou1dRJv1hOlG72aA."
ssh:
allow-pw: true
install-server: true
late-commands:
- "echo 'root:root' | chroot /target chpasswd"
- curtin in-target --target=/target -- sh -c 'echo "PermitRootLogin yes" >> /etc/ssh/sshd_config'
- |
cat << 'EOF' >> /target/root/.bashrc
PS1='\[\e[1;32m\][\u@\H \W]\$\[\e[0m\] '
export HISTTIMEFORMAT='%F %T '
EOF
- |
cat << 'EOF' > /target/root/.vimrc
set nu
syntax on
set pastetoggle=<F2>
autocmd InsertLeave * set nopaste
autocmd InsertEnter * set paste
set ignorecase
set tabstop=2
set shiftwidth=2
set nohlsearch
set expandtab
set backspace=indent,eol,start
set listchars=tab:>-,eol:$,space:.
autocmd FileType * setlocal formatoptions-=cro
" Bash 脚本模板
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,"#")
call setline(3,"#*******************************************************")
call setline(4,"#Author: xingyuyu")
call setline(5,"#Date: ".strftime("%Y-%m-%d"))
call setline(6,"#Filename: ".expand("%"))
call setline(7,"#Copyright (C): ".strftime("%Y")." All rights reserved")
call setline(8,"#********************************************************")
call setline(9,"")
endif
endfunc
autocmd BufNewFile *.sh exec ":call SetTitle()"
autocmd BufNewFile * normal G
au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
set viminfo='10,\"100,:20,%,n~/.viminfo
EOF
# apt:
# geoip: true
# preserve_sources_list: false
普通分区的user-data
#cloud-config
autoinstall:
version: 1
locale: en_US.UTF-8
timezone: Asia/Shanghai
keyboard:
layout: us
network:
version: 2
ethernets:
ens33:
dhcp4: true
source:
id: ubuntu-server
search_drivers: false
drivers:
install: false
kernel:
package: linux-generic
apt:
disable_components: []
fallback: offline-install
geoip: true
mirror-selection:
primary:
- uri: https://mirrors.aliyun.com/ubuntu
- uri: https://mirrors.tuna.tsinghua.edu.cn/ubuntu
- country-mirror
- arches: &id001
- amd64
- i386
uri: http://archive.ubuntu.com/ubuntu/
- arches: &id002
- s390x
- arm64
- armhf
- powerpc
- ppc64el
- riscv64
uri: http://ports.ubuntu.com/ubuntu-ports
preserve_sources_list: false
security:
- arches: *id001
uri: http://security.ubuntu.com/ubuntu/
- arches: *id002
uri: http://ports.ubuntu.com/ubuntu-ports
storage:
config:
- type: disk
id: disk-sda
path: /dev/sda
ptable: gpt
wipe: superblock-recursive
preserve: false
grub_device: true
- type: partition
id: partition-0
device: disk-sda
size: 1M
flag: bios_grub
number: 1
preserve: false
- type: partition
id: partition-1
device: disk-sda
size: 1G
number: 2
preserve: false
- type: partition
id: partition-2
device: disk-sda
size: 50G
number: 3
preserve: false
- type: partition
id: partition-3
device: disk-sda
size: -1
number: 4
preserve: false
- type: format
id: format-boot
fstype: ext4
volume: partition-1
preserve: false
- type: format
id: format-root
fstype: ext4
volume: partition-2
preserve: false
- type: format
id: format-data
fstype: ext4
volume: partition-3
preserve: false
- type: mount
id: mount-boot
device: format-boot
path: /boot
- type: mount
id: mount-root
device: format-root
path: /
- type: mount
id: mount-data
device: format-data
path: /data
identity:
hostname: ubuntu-server-2404
username: admin
password: "$6$N2/cWyyb47BdwNKH$slGINzTOLENrD6..QOTSSdhTuH.JGkmuo2VtkevZBT0nPCzfoazUAQF6MGe2Xxs1Tvkdhou1dRJv1hOlG72aA."
ssh:
allow-pw: true
authorized-keys: []
install-server: true
late-commands:
- "echo 'root:root' | chroot /target chpasswd"
- curtin in-target --target=/target -- sh -c 'echo "PermitRootLogin yes" >> /etc/ssh/sshd_config'
- curtin in-target --target=/target -- apt-get -y update
- |
cat << 'EOF' >> /target/root/.bashrc
PS1='\[\e[1;32m\][\u@\H \W]\$\[\e[0m\] '
export HISTTIMEFORMAT='%F %T '
EOF
- |
cat << 'EOF' > /target/root/.vimrc
set nu
syntax on
set pastetoggle=<F2>
autocmd InsertLeave * set nopaste
autocmd InsertEnter * set paste
set ignorecase
set tabstop=2
set shiftwidth=2
set nohlsearch
set expandtab
set backspace=indent,eol,start
set listchars=tab:>-,eol:$,space:.
autocmd FileType * setlocal formatoptions-=cro
" Bash 脚本模板
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,"#")
call setline(3,"#*******************************************************")
call setline(4,"#Author: xingyuyu")
call setline(5,"#Date: ".strftime("%Y-%m-%d"))
call setline(6,"#Filename: ".expand("%"))
call setline(7,"#Copyright (C): ".strftime("%Y")." All rights reserved")
call setline(8,"#********************************************************")
call setline(9,"")
endif
endfunc
autocmd BufNewFile *.sh exec ":call SetTitle()"
autocmd BufNewFile * normal G
au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
set viminfo='10,\"100,:20,%,n~/.viminfo
EOF
pxelinux.cfg/default内容
有关Redhat系列的这里不多做说明,重点说一下Ubuntu 24.04的配置。
Ubuntu 24.04 自动安装内核参数详解
内核参数完整示例
root=/dev/ram0 ip=dhcp url=http://10.0.0.109/iso/ubuntu-24.04.2-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://10.0.0.109/ks/ubuntu2404/ cloud-config-url=/dev/null
参数详细解释
1.
root=/dev/ram0
官方含义: 指定根文件系统的位置
- 作用: 告诉内核将
/dev/ram0
(内存磁盘)作为根文件系统挂载点- 为什么固定: Live安装模式下,系统首先加载到内存中运行,所有文件系统操作都在内存中进行
- 技术原理: 这是Linux内核的标准参数,用于指定initramfs解压后的根文件系统位置
2.
ip=dhcp
这个需要有dhcp服务器来自动分发ip地址官方含义: 配置网络接口的IP获取方式
- 作用: 指示系统通过DHCP协议自动获取IP地址、子网掩码、网关和DNS设置
- 格式:
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
- dhcp选项: 简化写法,等同于
ip=:::::<interface>:dhcp
- 重要性: 网络配置是自动安装的前提,需要访问HTTP服务器获取配置文件
3.
url=http://10.0.0.109/iso/ubuntu-24.04.2-live-server-amd64.iso
官方含义: 指定安装镜像的网络位置
- 作用: 告诉安装程序从指定URL下载Ubuntu安装镜像
- 支持协议: http://、https://、ftp://
- 工作原理: 安装程序会先下载此镜像到内存,然后挂载为安装源
- 注意: 这个URL必须可访问,且指向完整的Ubuntu ISO镜像文件
4.
autoinstall
官方含义: 启用Ubuntu自动安装模式
- 作用: 激活subiquity安装器的自动模式,跳过交互式安装界面
- 历史: 替代了传统的preseed机制
- 要求: 必须配合datasource(如nocloud-net)提供配置文件
- 固定原因: 这是Ubuntu官方定义的固定关键字,用于识别自动安装模式
5.
ds=nocloud-net
官方含义: 指定cloud-init数据源类型
- ds: 是datasource的缩写
- nocloud-net: 表示使用NoCloud数据源的网络模式
- 区别:
nocloud
:从本地文件系统读取配置(如CD/USB)nocloud-net
:从网络HTTP服务器获取配置- 技术实现: cloud-init根据此参数决定从哪里获取meta-data、user-data等配置
6.
;s=http://10.0.0.109/ks/ubuntu2404/
官方含义: 指定配置文件的基础URL(seedfrom)
s=: 是seedfrom的缩写
分号分隔: 与ds参数用分号连接,形成完整的datasource配置
URL结构:
cloud-init会在此URL下查找:
meta-data
:实例元数据user-data
:用户配置数据network-config
:网络配置(可选)工作流程:
GET http://10.0.0.109/ks/ubuntu2404/meta-dataGET http://10.0.0.109/ks/ubuntu2404/user-dataGET http://10.0.0.109/ks/ubuntu2404/network-config
7.
cloud-config-url=/dev/null
官方含义: 禁用额外的cloud-config配置源
- 作用: 将cloud-config配置源重定向到空设备,实际上禁用了它
- 为什么需要:
- 避免cloud-init尝试从其他位置获取配置
- 防止配置冲突和不确定的行为
- 确保只使用nocloud-net数据源的配置
- 测试重要性: 缺少此参数可能导致cloud-init行为不确定,安装失败
完整工作流程
- 内核启动:
root=/dev/ram0
指定内存根文件系统- 网络配置:
ip=dhcp
自动获取网络配置- 镜像下载:
url=...
下载安装镜像- 自动模式:
autoinstall
启用无人值守安装- 配置获取:
ds=nocloud-net;s=...
从HTTP服务器获取配置文件- 配置隔离:
cloud-config-url=/dev/null
确保配置源单一常见问题排查
如果缺少某个参数会怎样?
- 缺少
root=/dev/ram0
: 内核可能无法正确挂载根文件系统- 缺少
ip=dhcp
: 无网络连接,无法下载镜像和配置- 缺少
autoinstall
: 进入交互式安装界面- 缺少
ds=nocloud-net
: cloud-init无法找到配置数据源- 缺少
cloud-config-url=/dev/null
: 可能产生配置冲突HTTP服务器目录结构
/var/www/html/ ├── iso/ │ └── ubuntu-24.04.2-live-server-amd64.iso └── ks/ └── ubuntu2404/ ├── meta-data ├── user-data └── vendor-data
参考文档
- Ubuntu Autoinstall官方文档
- Cloud-init NoCloud数据源文档
- Linux内核启动参数文档
default menu.c32
timeout 600
menu title Install Linux System
LABEL ubuntu2404-root-enabled
MENU LABEL Auto Install ^Ubuntu 24.04
KERNEL ubuntu2404/vmlinuz
INITRD ubuntu2404/initrd
APPEND root=/dev/ram0 ip=dhcp url=http://10.0.0.109/iso/ubuntu-24.04.2-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://10.0.0.109/ks/ubuntu2404/ cloud-config-url=/dev/null
label kylin-V11-2503
menu label Auto Install ^Kylin-V11-2503
kernel Kylin-V11-2503/vmlinuz
append initrd=Kylin-V11-2503/initrd.img inst.repo=http://10.0.0.109/kylin/V11-2503/os/x86_64/ inst.ks=http://10.0.0.109/ks/Kylin-V11-2503.cfg ip=dhcp net.ifnames=0 biosdevname=0
label kylin-V10-SP3-2403
menu label Auto Install ^Kylin-V10-SP3-2403
kernel Kylin-V10-SP3-2403/vmlinuz
append initrd=Kylin-V10-SP3-2403/initrd.img inst.repo=http://10.0.0.109/kylin/V10-SP3-2403/os/x86_64/ inst.ks=http://10.0.0.109/ks/Kylin-V10-SP3-2403.cfg ip=dhcp net.ifnames=0 biosdevname=0
label openEuler2403
menu label Auto Install ^OpenEuler 24.03
kernel openEuler2403/vmlinuz
append initrd=openEuler2403/initrd.img inst.repo=http://10.0.0.109/openEuler/2403/os/x86_64/ inst.ks=http://10.0.0.109/ks/openEuler2403.cfg ip=dhcp net.ifnames=0 biosdevname=0
label rocky10
menu label Auto Install Rocky Linux ^10
kernel rocky10/vmlinuz
append initrd=rocky10/initrd.img inst.repo=http://10.0.0.109/rocky/10/os/x86_64/ inst.ks=http://10.0.0.109/ks/rocky10.cfg ip=dhcp net.ifnames=0 biosdevname=0
label rocky96
menu label Auto Install Rocky Linux ^9.6
kernel rocky96/vmlinuz
append initrd=rocky96/initrd.img inst.repo=http://10.0.0.109/rocky/96/os/x86_64/ inst.ks=http://10.0.0.109/ks/rocky96.cfg ip=dhcp net.ifnames=0 biosdevname=0
label rocky810
menu label Auto Install Rocky Linux ^8.10
kernel rocky810/vmlinuz
append initrd=rocky810/initrd.img inst.repo=http://10.0.0.109/rocky/810/os/x86_64/ inst.ks=http://10.0.0.109/ks/rocky810.cfg ip=dhcp net.ifnames=0 biosdevname=0
#label rocky95
# menu label Auto Install Rocky Linux ^9.5
# kernel rocky95/vmlinuz
# append initrd=rocky95/initrd.img inst.ks=http://10.0.0.109/ks/rocky95.cfg
#
#label kylin-v10sp3
# menu label Auto Install Kylin-v10-sp3 ^10
# kernel kylin10/vmlinuz
# #append initrd=kylin10/initrd.img inst.ks=http://192.168.124.189/ks/kylin10.cfg
# append initrd=kylin10/initrd.img inst.ks=http://10.0.0.109/ks/kylin10.cfg
label redhat9.2
menu label Auto Install ^Red Hat Enterprise Linux 9.2
kernel redhat9/vmlinuz
append initrd=redhat9/initrd.img inst.repo=http://10.0.0.109/redhatEnterprise/9/os/x86_64/ inst.ks=http://10.0.0.109/ks/redhat9.cfg ip=dhcp net.ifnames=0 biosdevname=0
#label rocky9
# menu label Auto Install Rocky Linux ^9
# kernel rocky9/vmlinuz
# append initrd=rocky9/initrd.img inst.ks=http://10.0.0.109/ks/rocky9.cfg
#
#label rocky93
# menu label Auto Install Rocky Linux ^9.3
# kernel rocky93/vmlinuz
# append initrd=rocky93/initrd.img inst.ks=http://10.0.0.109/ks/rocky93.cfg
#
#label rocky94
# menu label Auto Install Rocky Linux ^9.4
# kernel rocky94/vmlinuz
# append initrd=rocky94/initrd.img inst.ks=http://10.0.0.109/ks/rocky94.cfg
#
#label rocky8
# menu label Auto Install Rocky Linux ^8.6
# kernel rocky8/vmlinuz
# append initrd=rocky8/initrd.img inst.ks=http://10.0.0.109/ks/rocky8.cfg
#
#label centos8
# menu label Auto Install CentOS Linux ^8
# kernel centos8/vmlinuz
# append initrd=centos8/initrd.img ks=http://10.0.0.109/ks/centos8.cfg
#label centos7
# menu label Auto Install CentOS Linux ^7
# kernel centos7/vmlinuz
# append initrd=centos7/initrd.img ks=http://192.168.124.189/ks/centos722.cfg
#
#label centos6
# menu label Auto Install CentOS Linux ^6
# kernel centos6/vmlinuz
# append initrd=centos6/initrd.img ks=http://10.0.0.109/ks/centos6.cfg
#
label manual
menu label ^Manual Install Rocky Linux 8.10
kernel rocky810/vmlinuz
append initrd=rocky810/initrd.img
inst.repo=http://10.0.0.109/rocky/810/os/x86_64/
label rescue
menu label ^Rescue a Rocky Linux system 8.10
kernel rocky810/vmlinuz
append initrd=rocky810/initrd.img
inst.repo=http://10.0.0.109/rocky/810/os/x86_64/ rescu
label local
menu default
menu label Boot from ^local drive
localboot 0xffff