通过PXE的方式实现Ubuntu 24.04 自动安装

发布于:2025-09-06 ⋅ 阅读:(14) ⋅ 点赞:(0)

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行为不确定,安装失败

完整工作流程

  1. 内核启动: root=/dev/ram0指定内存根文件系统
  2. 网络配置: ip=dhcp自动获取网络配置
  3. 镜像下载: url=...下载安装镜像
  4. 自动模式: autoinstall启用无人值守安装
  5. 配置获取: ds=nocloud-net;s=...从HTTP服务器获取配置文件
  6. 配置隔离: 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

网站公告

今日签到

点亮在社区的每一天
去签到