利用KVM DIY自己的云镜像

简介

本次实验使用的环境为 openEuler 24.03 (LTS-SP2) 作为宿主机,利用KVM 去创建主机,然后打包为qcow2 镜像;

原理如下:(可以跳过原理直接看实验步骤)

首先在宿主机安装工具,然后创建一个空的 qcow2 磁盘,例如 20G,然后使用 /root 下的 openEuler ISO 作为安装源,通过 virt-install 启动虚拟机安装系统。安装过程不是手工操作,而是通过 Kickstart 文件自动完成:

  • 清空磁盘并自动分区;
  • 使用普通 XFS 根分区;
  • 配置 DHCP 网络;
  • 安装最小化系统;
  • 安装 cloud-init、SSH 和 XFS 工具;
  • 设置系统服务开机启动。
    这里使用普通分区而不是 LVM,主要是为了让 growpart 可以直接扩展根分区。如果使用 LVM,还需要额外处理物理卷、卷组和逻辑卷的扩容,流程会更复杂。
    原始 openEuler ISO 中缺少 cloud-utils-growpart。所以需要先下载对应的 RPM,然后用 xorriso 制作一个临时辅助 ISO,并设置卷标为 GROWPART。安装系统时,Kickstart 的 %post 阶段会找到这个辅助 ISO,把 RPM 复制到目标系统并安装。这个辅助 ISO 只是安装过程的临时介质,最终不会作为系统磁盘的一部分保留。
    安装完成后,写入 cloud-init 配置:
growpart:
  mode: auto
  devices: ['/']
  ignore_growroot_disabled: false

resize_rootfs: true

同时确认 growpart 和 resizefs 模块存在于 cloud-init 的模块列表中,并启用 cloud-init 服务。
使用阶段是把生成的 qcow2 镜像交给云平台或虚拟化平台。当创建虚拟机时,平台可能把磁盘从原来的 20G 扩大到 50G、100G 等。系统第一次启动时,cloud-init 会按以下顺序处理:

读取云平台元数据或 seed ISO
        |
        v
cloud-init 初始化
        |
        v
growpart 扩展根分区
        |
        v
resizefs 扩展 XFS 文件系统
        |
        v
系统直接使用新增空间

例如原镜像中的根分区是 20G,创建虚拟机时磁盘调整为 50G,整个扩容过程可以拆成下面几步来看:

  • 原始磁盘:qcow2 虚拟容量 20G,根分区 /dev/vda1 约占满整块盘,XFS 文件系统大小约 20G。
  • 扩容后磁盘:云平台或 qemu-img resize 把磁盘扩大到 50G,此时多出来的 30G 只是"裸空间",分区表和文件系统都还没有感知到。
  • growpart:读取分区表,把根分区 /dev/vda1 的结束扇区推到接近磁盘末尾,分区大小变成约 50G。这一步只改分区表,不动文件系统。
  • resizefs:根据分区的新大小,调用 xfs_growfs 把 XFS 文件系统扩展到整个分区,最终 df -h / 显示约 50G。

可以用下面的命令逐段确认每一步的效果:

# 扩容前:磁盘 20G,分区和文件系统都约 20G
lsblk /dev/vda
df -h /

# 扩容后、cloud-init 执行前:磁盘 50G,但分区仍是 20G
lsblk /dev/vda

# cloud-init 执行后:分区和文件系统都接近 50G
lsblk /dev/vda
df -h /
growpart /dev/vda 1 --dry-run   # 无输出说明分区已扩展到磁盘末尾

growpart 只负责扩大分区,不能扩大文件系统;resizefs 负责扩大文件系统。两个模块必须配合使用,否则可能出现"磁盘已经变大,但 df -h 看到的根文件系统仍然没有变大"的情况。常见原因是 growpart 未安装、/etc/cloud/cloud.cfg 中模块被注释掉,或者根分区不在磁盘末尾导致无法直接扩展。

实验步骤

1. 准备宿主机,并配置基础环境

首先准备一台主机,我用的是openEuler, 同时需要开启虚拟化

[root@localhost ~]# cat /etc/os-release 
NAME="openEuler"
VERSION="24.03 (LTS-SP2)"
ID="openEuler"
VERSION_ID="24.03"
PRETTY_NAME="openEuler 24.03 (LTS-SP2)"
ANSI_COLOR="0;31"

[root@localhost ~]# lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda                  8:0    0  111G  0 disk 
├─sda1               8:1    0    1M  0 part 
├─sda2               8:2    0    1G  0 part /boot
└─sda3               8:3    0  110G  0 part 
  ├─openeuler-root 253:0    0   70G  0 lvm  /
  ├─openeuler-swap 253:1    0  4.2G  0 lvm  [SWAP]
  └─openeuler-home 253:2    0 35.8G  0 lvm  /home
sr0                 11:0    1  4.4G  0 rom  

[root@localhost ~]# free -h
               total        used        free      shared  buff/cache   available
Mem:           7.8Gi       691Mi       3.3Gi       2.6Mi       4.0Gi       7.1Gi

2. 将 然后软件包上传至 /root/ 目录下

百度网盘下载链接

[root@localhost KVM]# ls
build-openeuler-qcow2.sh  logs        packages
growpart-rpm.iso          ks-cloud-init.cfg         
openeuler-cloud.qcow2
openEuler-23.09-x86_64-dvd.iso # 将需要制作的 ISO 一起上传到KVM中

3. 执行脚本

cd /root/KVM
chmod 770 build-openeuler-qcow2.sh 
./build-openeuler-qcow2.sh 

构建成功后 密码是000000
友情提示 该脚本基于宿主机:openeuler 24.03 目标镜像:openeuler23.09 制作,使用其他系统或者制作其他镜像可能会出bug,可以将脚本,宿主机环境,目标镜像发给大模型进行二次编译

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐