QEMU 虚拟机(Kylin V10)磁盘扩容教程(LVM 分区 + XFS/ext4 文件系统)

适用场景

  • 基于 QEMU 运行的 ARM 架构 Kylin V10 虚拟机(含 LVM 逻辑卷管理)
  • 虚拟磁盘格式为 qcow2,需从宿主机扩展磁盘后,在虚拟机内同步扩容根分区
  • 覆盖XFS(Kylin V10 默认)和ext4两种文件系统场景

前置说明

  1. 核心逻辑:磁盘扩容需分「宿主机扩展虚拟磁盘文件」和「虚拟机内扩展分区 / LVM / 文件系统」两步,缺一不可。
  2. 数据安全:操作前务必在宿主机备份虚拟磁盘(避免分区修改失误导致数据丢失),备份命令:
   # 宿主机执行,替换路径为实际虚拟磁盘路径
   cp /data/arm_kylin_10.0.2.15_node001/kylin_v10_sp3_arm64.qcow2 /data/arm_kylin_10.0.2.15_node001/kylin_v10_sp3_arm64_backup.qcow2
  1. 关键工具:
  • 宿主机:qemu-img(扩展 qcow2 文件)
  • 虚拟机:fdisk(分区管理)、pvresize/lvextend(LVM 扩容)、xfs_growfs/resize2fs(文件系统扩容)

第一步:宿主机操作 —— 扩展虚拟磁盘文件

注:启动/停止/安装脚本

root@i-kg2tav5y:/data/arm_kylin_10.0.2.15_node001# cat start_kylin.sh
#!/bin/bash

ISO_FILE="/data/iso/Kylin-Server-V10-SP3-2403-Release-20240426-arm64.iso"
DISK_FILE="kylin_v10_sp3_arm64.qcow2"
MEM_SIZE="8G"
CPU_CORES="4"
SSH_PORT="2222"
VNC_DISPLAY="1"
PID_FILE="qemu_vm.pid"

# 函数:正常启动虚拟机(从硬盘启动,不加载ISO)
start_vm() {
    if [ -f "$PID_FILE" ]; then
        local pid=$(cat "$PID_FILE")
        if ps -p "$pid" > /dev/null; then
            echo "虚拟机已在运行(PID: $pid),无需重复启动。"
            return 0
        else
            echo "发现残留PID文件,但进程不存在,已清理。"
            rm -f "$PID_FILE"
        fi
    fi

    if [ ! -f "$DISK_FILE" ]; then
        echo "错误:未找到虚拟磁盘文件 $DISK_FILE,请先使用 install 模式安装系统。"
        return 1
    fi

    echo "正在启动虚拟机(从硬盘启动)..."
    qemu-system-aarch64 \
      -machine virt \
      -cpu cortex-a72 \
      -smp "$CPU_CORES" \
      -m "$MEM_SIZE" \
      -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
      -device virtio-gpu-pci,id=vgpu \
      -vnc :"$VNC_DISPLAY",display=vgpu \
      -nographic \
      -serial none \
      -device usb-ehci,id=usb-controller \
      -device usb-tablet,bus=usb-controller.0 \
      -device usb-kbd,bus=usb-controller.0 \
      -boot order=c,menu=on \
      -device virtio-blk-device,drive=disk0 \
      -drive file="$DISK_FILE",if=none,id=disk0,format=qcow2 \
      -device virtio-net-device,netdev=net0 \
      -netdev user,id=net0,hostfwd=tcp::$SSH_PORT-:22 \
      -accel tcg,thread=single &
    echo $! > "$PID_FILE"
    echo "虚拟机启动成功,进程ID已写入 $PID_FILE。"
}

# 函数:安装模式启动(加载ISO镜像)
install_vm() {
    if [ -f "$PID_FILE" ]; then
        local pid=$(cat "$PID_FILE")
        if ps -p "$pid" > /dev/null; then
            echo "虚拟机已在运行(PID: $pid),请先停止再进行安装。"
            return 0
        else
            echo "发现残留PID文件,但进程不存在,已清理。"
            rm -f "$PID_FILE"
        fi
    fi

    if [ ! -f "$ISO_FILE" ]; then
        echo "错误:未找到ISO文件 $ISO_FILE,请检查文件是否存在。"
        return 1
    fi

    if [ ! -f "$DISK_FILE" ]; then
        echo "创建虚拟磁盘文件: $DISK_FILE"
        qemu-img create -f qcow2 "$DISK_FILE" 50G
    fi

    echo "以安装模式启动虚拟机(从ISO启动)..."
    qemu-system-aarch64 \
      -machine virt \
      -cpu cortex-a72 \
      -smp "$CPU_CORES" \
      -m "$MEM_SIZE" \
      -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
      -device virtio-gpu-pci,id=vgpu \
      -vnc :"$VNC_DISPLAY",display=vgpu \
      -nographic \
      -serial none \
      -device usb-ehci,id=usb-controller \
      -device usb-tablet,bus=usb-controller.0 \
      -device usb-kbd,bus=usb-controller.0 \
      -boot order=d,menu=on \
      -device virtio-blk-device,drive=disk0 \
      -drive file="$DISK_FILE",if=none,id=disk0,format=qcow2 \
      -device virtio-blk-device,drive=cdrom0 \
      -drive file="$ISO_FILE",if=none,id=cdrom0,media=cdrom \
      -device virtio-net-device,netdev=net0 \
      -netdev user,id=net0,hostfwd=tcp::$SSH_PORT-:22 \
      -accel tcg,thread=single &
    echo $! > "$PID_FILE"
    echo "安装模式启动成功,进程ID已写入 $PID_FILE。"
    echo "请通过VNC连接进行系统安装,完成后请先停止虚拟机,再用start模式启动。"
}

# 函数:停止虚拟机
stop_vm() {
    if [ ! -f "$PID_FILE" ]; then
        echo "未找到虚拟机进程ID文件,可能虚拟机未启动。"
        return 1
    fi

    local pid=$(cat "$PID_FILE")
    if ps -p "$pid" > /dev/null; then
        echo "正在停止虚拟机(PID: $pid)..."
        kill "$pid"
        # 等待进程退出(最多等待10秒)
        for i in {1..10}; do
            if ! ps -p "$pid" > /dev/null; then
                echo "虚拟机已停止。"
                rm -f "$PID_FILE"
                return 0
            fi
            sleep 1
        done
        echo "强制终止虚拟机进程..."
        kill -9 "$pid"
        rm -f "$PID_FILE"
        echo "虚拟机已强制停止。"
    else
        echo "PID文件存在,但进程不存在,已清理PID文件。"
        rm -f "$PID_FILE"
    fi
}

# 函数:查看虚拟机状态
status_vm() {
    if [ -f "$PID_FILE" ]; then
        local pid=$(cat "$PID_FILE")
        if ps -p "$pid" > /dev/null; then
            echo "虚拟机正在运行(PID: $pid)。"
        else
            echo "PID文件存在,但进程不存在,已清理。"
            rm -f "$PID_FILE"
            echo "虚拟机未运行。"
        fi
    else
        echo "虚拟机未运行。"
    fi
}

# 主逻辑:根据参数执行操作
case "$1" in
    start)
        start_vm
        ;;
    install)
        install_vm
        ;;
    stop)
        stop_vm
        ;;
    restart)
        stop_vm
        start_vm
        ;;
    status)
        status_vm
        ;;
    *)
        echo "用法: $0 {start|install|stop|restart|status}"
        echo "  install: 从ISO启动,用于系统安装"
        echo "  start:   从硬盘启动,正常使用系统"
        echo "  stop:    停止虚拟机"
        echo "  restart: 重启虚拟机"
        echo "  status:  查看虚拟机状态"
        exit 1
        ;;
esac
root@i-kg2tav5y:/data/arm_kylin_10.0.2.15_node001#
  1. 停止虚拟机(确保磁盘无写入,避免损坏):
   # 进入宿主机的虚拟机配置目录(替换为实际路径)
   cd /data/arm_kylin_10.0.2.15_node001
   # 用脚本停止虚拟机
   ./start_kylin.sh stop
   # 验证是否已停止(输出“虚拟机未运行”即为成功)
   ./start_kylin.sh status
  1. 扩展 qcow2 虚拟磁盘
  • 语法:qemu-img resize 虚拟磁盘文件 新增容量+13G表示新增 13G,100G表示总容量 100G)
  • 示例(将磁盘从 50G 扩展到 100G,新增 50G): qemu-img resize kylin_v10_sp3_arm64.qcow2 +50G
  • 验证扩展结果(查看 “virtual size” 是否为目标容量): qemu-img info kylin_v10_sp3_arm64.qcow2
  1. 启动虚拟机(进入下一步操作):
   ./start_kylin.sh start
   # 通过SSH或VNC登录虚拟机(用户为root)
   ssh -p 2222 root@宿主机IP

第二步:虚拟机内操作 —— 扩容分区与 LVM(通用步骤)

2.1 确认磁盘状态(定位未分配空间)

登录虚拟机后,先查看磁盘当前分区情况,确认宿主机扩展的空间已被识别:

# 查看磁盘分区结构(vda总容量应已扩展,如100G,但vda3仍为原大小,如48.4G)
lsblk /dev/vda
# 查看GPT分区表(若有“GPT PMBR大小不符”警告,需后续修复)
fdisk -l /dev/vda
  • 预期结果:/dev/vda总容量 = 目标容量(如 100G),/dev/vda3(LVM 物理分区)未扩展,存在 “未分配空间”。

2.2 修复 GPT 分区表(解决 “大小不符” 警告)

fdisk -l /dev/vda提示 “GPT PMBR 大小不符”“备份 GPT 表不在磁盘末尾”,需先修复分区表:

# 进入fdisk交互模式(操作/dev/vda)
fdisk /dev/vda
# 1. 输入p查看分区表(确认vda3的起始扇区,如3328000,后续不可修改!)
p
# 2. 无需修改分区,直接输入w保存(fdisk会自动修复GPT表)
w
# 3. 刷新分区表(无需重启)
partprobe /dev/vda
# 4. 再次查看,确认警告消失
fdisk -l /dev/vda

2.3 扩展 LVM 物理分区(vda3)

需将vda3扩展到 “未分配空间”,核心是保留 vda3 的起始扇区(避免 LVM 数据丢失):

# 重新进入fdisk交互模式
fdisk /dev/vda

# 1. 删除原vda3分区(仅删除分区表记录,不删除数据)
d  # 输入d删除分区
3 # 输入分区号3(对应vda3)

# 2. 新建vda3分区(扩展到未分配空间)
n  # 输入n新建分区
p  # 输入p选择“主分区”
3 # 输入分区号3(保持原编号,避免LVM识别异常)
   # 起始扇区:直接按回车(默认使用原起始扇区,如3328000,关键!)
   # 结束扇区:直接按回车(默认占用全部未分配空间)
N # 提示“是否移除LVM签名”,输入N保留(否则LVM数据失效)

# 3. (可选)修改分区类型(GPT下可能显示为Linux filesystem,不影响功能)
t  # 输入t修改分区类型
3 # 输入分区号3
8e# 输入8e(LVM分区类型码)
p  # 输入p验证:vda3大小=扩展后容量(如98.4G),类型可为Linux filesystem

# 4. 保存分区表并退出
w
# 5. 刷新分区表
partprobe /dev/vda
# 6. 验证vda3已扩展(大小应为扩展后容量,如98.4G)
lsblk /dev/vda

2.4 扩展 LVM 物理卷(PV)

LVM 需先识别vda3的新增空间,通过pvresize更新物理卷:

# 扩展vda3对应的LVM物理卷
pvresize /dev/vda3
# 验证结果(查看PFree列,应有新增空间,如50G)
pvs
  • 预期结果:/dev/vda3PFree(剩余空间)= 宿主机新增的容量(如 50G)。

2.5 扩展 LVM 逻辑卷(LV)

将新增的 LVM 空间全部分配给根分区对应的逻辑卷(如klas-root):

# 查看逻辑卷名称(根分区对应的LV通常为klas-root或centos-root)
lvs
# 扩展逻辑卷:将所有剩余空间(+100%FREE)分配给klas-root
lvextend -l +100%FREE /dev/mapper/klas-root
# 验证结果(查看LV Size列,klas-root容量应已扩展,如96.3G)
lvs

第三步:按文件系统类型扩容(二选一)

先确认根分区的文件系统类型,再选择对应工具:

# 查看根分区(/)的文件系统类型(Type列)
df -T /

3.1 场景 1:XFS 文件系统(Kylin V10 默认)

XFS 需使用xfs_growfs工具,且必须指定根分区挂载点(/),不可指定设备路径:

# 扩容XFS文件系统(/为根分区挂载点)
xfs_growfs /
# 验证结果(根分区容量应=扩展后容量,如97G)
df -h /
  • 成功标志:输出 “data blocks changed from XXX to XXX”,df -h /显示容量已扩展。

3.2 场景 2:ext4 文件系统

ext4 需使用resize2fs工具,必须指定逻辑卷设备路径(如/dev/mapper/klas-root):

# 扩容ext4文件系统(指定逻辑卷设备路径)
resize2fs /dev/mapper/klas-root
# 验证结果(根分区容量应=扩展后容量,如97G)
df -h /
  • 成功标志:输出 “done”,df -h /显示容量已扩展,无 “超级块错误” 提示。

第四步:最终验证

执行以下命令,确认全流程扩容成功:

# 1. 查看磁盘分区(vda3已扩展)
lsblk /dev/vda
# 2. 查看LVM状态(物理卷、逻辑卷容量正常)
pvs && lvs
# 3. 查看根分区容量(已扩展到目标大小)
df -h /
  • 预期结果:根分区(/)容量 = 宿主机扩展后的总容量(如 100G 扣除引导分区后约 97G),使用率下降。

常见问题与解决方案

  1. 问题 1:resize2fs 报错 “超级块中的幻数有错”
  • 原因:用 ext4 工具扩容 XFS 文件系统,工具不匹配。
  • 解决:改用xfs_growfs /
  1. 问题 2:fdisk 修改 vda3 后,类型仍显示为 Linux filesystem
  • 原因:GPT 分区表对 LVM 类型的显示兼容性问题,不影响 LVM 功能。
  • 解决:无需处理,只要pvs能识别/dev/vda3即可。
  1. 问题 3:扩展后 df -h 仍显示原容量
  • 原因:未执行文件系统扩容步骤(漏了xfs_growfsresize2fs)。
  • 解决:补充执行对应文件系统的扩容命令。

注意事项

  1. 起始扇区不可错:删除 vda3 后新建时,起始扇区必须与原扇区一致(如 3328000),否则 LVM 数据丢失。
  2. 工具必须匹配:XFS 用xfs_growfs(挂 – 载点),ext4 用resize2fs(设备路径),不可混用。
  3. 操作顺序不可乱:宿主机扩展磁盘 → 虚拟机修复 GPT → 扩展 vda3 → LVM 扩容 → 文件系统扩容,步骤不可逆。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇