资讯动态

openEuler内核虚拟化实验:KVM原理与virsh实操全解析

发布时间:2026/10/22 18:50:55 来源:尧图企业网站定制
这周实验课刚好推进到第九章主题是openEuler下的内核虚拟化。很多人听到“虚拟化”三个字总觉得是运维岗才会碰的东西但操作系统理论课把这个题目放进来其实是想让你把前面学的特权级、系统调用、中断、进程调度全部串起来——KVM就是那个能让你直观看到CPU时间片怎么被“出租”、内存怎么被“隔离”、设备怎么被“虚拟”的绝佳案例。这篇文章是我按实际带实验的顺序整理出来的从原理拆解、环境搭建到创建虚拟机、分配资源、排查报错全部是能直接照着操作的内容。不管是还没做这个实验的同学还是想自己搭一套KVM环境玩玩的开发者都可以参照这份流程走一遍。1. 实验目标与内核虚拟化入门1.1 这个实验到底在做什么先搞清楚这门课为什么要把虚拟化放在操作系统实验里。第九章的理论部分重点讲了两件事一是虚拟机监视器如何通过CPU的虚拟化扩展Intel的VT-x、AMD的SVM实现特权级隔离二是虚拟机本质上仍然是进程只不过是被内核特殊“包裹”过的进程。实验部分要求你在openEuler系统上把这套机制亲手用起来。落到具体操作上实验一共就三件事安装KVM相关组件、创建一台虚拟机、用命令行完成生命周期管理。听起来不难但实际做一遍你会发现之前学过的“用户态/内核态切换”在这里有了新含义——QEMU进程在用户态模拟设备KVM模块在内核态处理CPU敏感指令客户机的内核跑在所谓的Guest Mode里。理论课上用一张图讲清楚的内容实验课上你得用一条条命令、一个个报错来重新理解。我给这个实验定的验收标准是不看笔记的情况下能用virt-install参数说出每个选项对应虚拟化原理的哪个部分能用virsh完成虚拟机的创建、暂停、恢复、销毁和快照回滚。能做到这两点说明第九章的核心知识是真的进脑子了而不只是会敲命令。1.2 KVM、QEMU、libvirt各司其职很多初学者第一次接触这三件套的时候会懵一会说KVM是虚拟化一会说QEMU是虚拟化libvirt又来插一脚。它们其实分层很清楚。KVM是内核模块它的核心作用是把CPU的硬件虚拟化能力暴露给用户态。装好KVM之后系统里会出现一个/dev/kvm设备文件用户态程序通过ioctl系统调用跟它打交道。KVM自己只管CPU和内存的虚拟化不管设备模拟——也就是说没有QEMU的KVM是“有房但没家具”的状态。QEMU负责设备模拟。网卡、磁盘、串口、显卡这些硬件都是QEMU在用户态用软件模拟出来的。你给虚拟机分配一块virtio磁盘实际上是QEMU在宿主机的文件系统上开了一个大文件然后把这个文件“伪装”成一块硬盘给客户机用。生活化的类比是KVM是房东QEMU是装修队房东提供产权和空间装修队负责把毛坯房变成能住人的样子。libvirt则是统一管理接口。有了它你不需要直接跟QEMU的命令行参数打交道而是用virsh、virt-manager这些工具下发XML配置libvirt帮你翻译成QEMU能懂的东西。实验中90%的操作其实都是通过libvirt完成的只有少数场景需要直接qemu-img操作磁盘镜像。展开说一句明白这个分层对你的实验意义很大报错排查时如果问题出在CPU虚拟化那是KVM层的事如果出在设备或者镜像多半是QEMU层的事如果配置下发不对那就要检查libvirt的XML。1.3 为什么用openEuler做实验载体选openEuler作为实验平台有几个实际考量。首先是软件源里直接有完整的虚拟化组件一条dnf命令就能装齐不需要像某些发行版那样手动加第三方源这对实验课来说省掉了一大半环境问题。其次是它的内核版本比较新对KVM的支持很完善而且官方文档里针对虚拟化有专门章节学生遇到问题能自己查资料。另外openEuler的osinfo数据库支持也做得不错。创建虚拟机时virt-install有一个--os-variant参数用来指定客户机操作系统类型如果这个参数不认识openEuler安装时会报错。但如果你的虚拟机操作系统选的是某个通用Linux发行版影响也不大。我建议拿到实验机之后先跑一条osinfo-query os | grep -i open看看当前版本的osinfo数据库里有没有openEuler条目这样可以少踩一个坑。从学习价值上讲openEuler的默认配置比较“朴素”没有太多花哨的封装KVM、QEMU、libvirt之间各层次的关系暴露得很清楚。相比之下一些自带图形化管理面板的发行版反而容易让学生只点鼠标不思考。2. 实验环境准备与坑位预警2.1 硬件检查先确认CPU愿意“配合”虚拟化实验最怕的就是CPU压根不支持硬件虚拟化或者支持了但BIOS里没开。这一步没做好后面所有操作都会报同一个错/dev/kvm不存在。检查方法很简单登进openEuler之后执行grep -Ec (vmx|svm) /proc/cpuinfo lscpu | grep -i 虚拟化第一行返回的数字如果大于0说明CPU带有虚拟化扩展标志第二行能看到具体的虚拟化类型。如果是Intel CPU对应vmxAMD对应svm。数字为0或者lscpu查不到虚拟化字样大概率要去BIOS里开启Intel VT-x或者AMD-V功能。还有一个容易忽略的点如果是自己装的物理机系统里开了嵌套虚拟化但没开透传也会出现KVM初始化异常。实验课的机器一般是物理机或者已经配置好的云主机这块问题不大但如果你是拿家里电脑练手一定要确认VMware或者别的虚拟机软件里勾选了“向客户机暴露虚拟化指令”这类选项。内存方面建议至少8GB我见过4GB内存的机器跑两台虚拟机宿主机直接开始疯狂swap实验卡得没法看。磁盘需要预留至少40GB因为客户机安装完系统之后还要做快照实验空间太小会出现“磁盘镜像虚胖”的问题后面章节细说。2.2 安装组件一条dnf命令的事确认硬件没问题后安装虚拟化组件。openEuler下的包名和CentOS系比较接近我用的是这组sudo dnf install -y qemu-kvm qemu-img libvirt virt-install virt-manager bridge-utils这里稍微解释一下每个包的作用qemu-kvm是KVM配套的QEMU用户态程序qemu-img是磁盘镜像管理工具libvirt提供管理守护进程和客户端工具virt-install是命令行创建虚拟机的工具virt-manager是图形界面管理工具bridge-utils是网桥工具。安装完成后依次执行sudo systemctl enable --now libvirtd sudo systemctl status libvirtd ls -l /dev/kvmlibvirtd是libvirt的守护进程所有virsh命令都要经过它。第三条命令确认/dev/kvm设备存在这是KVM模块正常加载的标志。如果ls提示找不到文件先手动加载模块试试sudo modprobe kvm_intel或者根据CPU厂商换成kvm_amd。加载还是失败的话回到上一节检查BIOS设置。还有一个新手必踩的权限坑直接用普通用户执行virsh list会报“Failed to connect socket to /var/run/libvirt/virtlogd-sock”或者权限不足的错误。解决办法是把当前用户加入libvirt用户组然后重新登录一次会话sudo usermod -aG libvirt $(whoami)2.3 网络方案默认NAT还是手动桥接libvirt默认会创建一个名为default的NAT网络虚拟机的网卡通过它访问外网宿主机充当网关做地址转换。这个方案对实验够用但有两个缺点第一外部主机无法直接访问虚拟机只能从宿主机SSH进去再跳转第二NAT的性能和延迟都不如桥接。如果你只是想完成实验验收直接下面几步确认default网络存在即可virsh net-list --all sudo virsh net-start default sudo virsh net-autostart default想做桥接的话需要把宿主机物理网卡加入一个网桥。以NetworkManager为例先创建桥接连接再把物理网卡挂进去sudo nmcli connection add type bridge ifname br0 con-name br0 sudo nmcli connection add type ethernet slave-type bridge con-name br0-port1 ifname ens33 master br0这里ens33要替换成你实际的物理网卡名用ip addr查看。配置完成后虚拟机指定网络为bridge:br0就能获得和宿主机同一网段的IP外部可以直接访问。桥接配置相对折腾一点但做通之后对理解虚拟网络很有帮助而且后续做VNC远程连接实验时桥接会更顺手。3. 虚拟机创建与生命周期管理实操3.1 准备系统镜像与磁盘文件安装虚拟机必须有一个可引导的安装介质。openEuler官方提供了ISO镜像下载后放到固定目录比如/home/user/isos/。如果你是离线环境也可以用教官提前准备好的镜像仓库。接着创建虚拟机的磁盘镜像。这里建议用qcow2格式sudo qemu-img create -f qcow2 /var/lib/libvirt/images/oslab-vm.qcow2 20Gqcow2格式最核心的特点是Copy-on-Write也就是写时复制。你给虚拟机分配20G空间宿主机上这个文件实际只有不到200K只有客户机真正写入数据时才逐步占用宿主机磁盘。类比一下就是去饭店订了20个座位的包间实际付钱只按来的人数算。这对实验课的场景非常友好十台虚拟机开出来宿主机磁盘压力也不大。创建完镜像顺手确认一下qemu-img info /var/lib/libvirt/images/oslab-vm.qcow2能看到虚拟大小20G、磁盘格式qcow2基本信息就齐了。3.2 virt-install 参数逐行讲透创建虚拟机的完整命令如下我每次实验课都会把这条命令拆开讲因为每个参数背后都对应着一个虚拟化原理sudo virt-install \ --name oslab-vm \ --memory 2048 \ --vcpus 2 \ --disk path/var/lib/libvirt/images/oslab-vm.qcow2,formatqcow2,busvirtio \ --network networkdefault,modelvirtio \ --os-variant openeuler-22.03 \ --graphics vnc,listen0.0.0.0 \ --cdrom /home/user/isos/openEuler-22.03-x86_64.iso逐个解释--name后面是虚拟机名字libvirt用它作为唯一标识后续所有virsh命令都要引用这个名字。--memory指定内存大小单位是MiB2048即2GB。注意不要给太多宿主机内存要留出一部分给自身运行。--vcpus指定虚拟CPU数量。这里的vCPU对应的是“线程”而不是完整物理核心超卖是允许的但你得清楚这是牺牲性能换资源密度。--disk指定磁盘路径、格式和总线类型。busvirtio的意思是客户机使用半虚拟化驱动访问磁盘性能远好于模拟IDE设备。这里有个前提客户机系统需要内置virtio驱动openEuler的内核默认支持所以可以直接用。--network指定网络类型和网卡模型。networkdefault表示接在上一节说的NAT网络上modelvirtio同样是为了性能。--os-variant告诉libvirt客户机系统类型它会据此优化CPU型号、设备配置等。版本号要看osinfo数据库支持情况拿不准就先osinfo-query os查。--graphics vnc表示通过VNC提供图形安装界面listen0.0.0.0允许远程连接。--cdrom指定安装ISO镜像。命令执行后virt-install会输出“Starting install...”然后进入等待状态。此时可以用virt-manager打开图形界面看安装进度也可以直接VNC连接。3.3 生命周期管理创建之后才是真正开始时安装完系统重启进入客户机系统之后虚拟化管理才算真正开始。所有日常操作集中在virsh一条命令上。先熟悉查询类操作virsh list # 查看正在运行的虚拟机 virsh list --all # 查看所有虚拟机包括已关闭的 virsh dominfo oslab-vm # 查看虚拟机配置信息 virsh vcpuinfo oslab-vm # 查看vCPU绑定情况然后是生命周期操作virsh shutdown oslab-vm # 发送ACPI关机信号优雅关机 virsh start oslab-vm # 启动已关闭的虚拟机 virsh reboot oslab-vm # 发送重启信号 virsh destroy oslab-vm # 强制断电相当于拔电源 virsh undefine oslab-vm # 删除虚拟机定义但保留磁盘文件这几条命令建议反复练习到条件反射。实验考试常见的题目就是“将虚拟机oslab-vm优雅关机后重新启动”很多人一紧张直接用destroy这在虚拟机没有重要数据时无所谓但真实生产环境里destroy等于直接拔电数据丢失风险极大。我给学生定的要求是shutdown优先确实无响应才用destroy。还有两个容易被忽略的操作autostart设置开机自启以及快照管理virsh autostart oslab-vm virsh snapshot-create-as oslab-vm base 系统初始状态 virsh snapshot-list oslab-vm virsh snapshot-revert oslab-vm base快照相当于给虚拟机拍了一张“可回退的照片”。我的建议是做完一次成功的系统安装之后立刻打一个快照后续配置改坏了直接回滚不用重新装系统。这个习惯在真实生产环境中非常值钱。4. 资源分配与调优细节4.1 CPU拓扑与绑定策略虚拟机创建时给的--vcpus 2只是“数量”实际上vCPU的调度完全由宿主机内核完成。默认情况下宿主机内核会把vCPU线程调度到任意物理CPU核心上。这样做的好处是负载均衡但也带来了缓存亲和性问题——vCPU在核心间来回迁移L2缓存反复失效性能打折。实验里可以体验一下手动绑核。先用lscpu看一下宿主机CPU拓扑然后用virsh vcpupin把vCPU固定到指定物理核心virsh vcpupin oslab-vm 0 2 virsh vcpupin oslab-vm 1 3 virsh emulatorpin oslab-vm 0-3第一行把vCPU 0绑到物理核心2第二行把vCPU 1绑到物理核心3第三行把QEMU进程整体绑到0-3号核心。这样vCPU线程和QEMU模拟线程都不会跑到核心4以上的区域去其他虚拟机再有负载也不容易争抢同一片CPU缓存。还有一点需要注意如果你所在的环境是云主机或者别人共享的机器绑定前一定确认那些物理核心没有被其他虚拟机占用否则两个vCPU绑到同一核心性能反而更差。实操中可以用top看到进程PID再用taskset -p检查一下亲和性掩码判断绑定是否生效。4.2 内存大页配置KVM虚拟化里内存性能的关键是TLB命中率。默认4K内存页下2GB客户机内存需要51万多个页表项TLB根本装不下几乎每次内存访问都要页表遍历。解决方案是使用2MB甚至1GB的大页。实验机上配置大页比较简单。临时生效可以这样echo 1024 /proc/sys/vm/nr_hugepages这表示预留1024个2MB大页总共2GB。想让虚拟机使用大页需要修改域XML在memoryBacking节点加hugepages配置virsh edit oslab-vm在 区域添加memoryBacking hugepages/ /memoryBacking保存后重启虚拟机通过以下命令确认生效grep HugePages_Total /proc/meminfo如果看到HugePages_Total有数值变化并且虚拟机的RSS不再计入普通内存说明大页启用成功。这个实验点做完再去跑一个内存密集型测试对比一下延时会非常有体感。4.3 磁盘性能与快照策略磁盘部分最容易踩的坑是格式选择。raw格式性能比qcow2好但不支持快照和精简置备qcow2功能全性能有少量损耗。实验和日常使用我推荐qcow2理由很简单快照能力太重要了性能差异在普通机械盘上根本感知不到在NVMe盘上差距也不大。qemu-img的几个常用操作建议熟练掌握qemu-img info /var/lib/libvirt/images/oslab-vm.qcow2 qemu-img resize /var/lib/libvirt/images/oslab-vm.qcow2 30G qemu-img convert -f qcow2 -O raw oslab-vm.qcow2 oslab-vm.rawresize只能扩大不能缩小而且扩大之后客户机里还要用分区工具扩展文件系统。convert可以把镜像格式互转实验里可以用来体会raw和qcow2的体积差异——你会发现同样内容的系统raw镜像文件比qcow2大不少。另外强调一点虚拟机开启状态下不要直接用qemu-img命令操作磁盘文件必须先把虚拟机shutdown否则镜像很容易损坏。我见过不止一个学生图省事虚拟机运行时直接convert镜像结果整个系统盘报废。4.4 virtio半虚拟化驱动的价值实验里有一个对比环节值得认真做分别用模拟设备和virtio设备创建虚拟机然后对比磁盘读写速度和网络吞吐。virtio模型的关键在于客户机知道自己是虚拟机所以主动配合宿主机的高效I/O通道而不是老老实实地模拟传统硬件。以网卡为例e1000模拟网卡需要QEMU逐条处理硬件中断和寄存器操作而virtio网卡通过共享内存环形队列批量传输数据。用一个简单对比表格说明对比维度传统模拟设备virtio半虚拟化磁盘性能差CPU占用高好接近物理设备网络吞吐低延迟高高延迟低驱动要求无需特殊驱动客户机需内置驱动CPU开销高低实验时创建两台虚拟机一台用bussata一台用busvirtio然后在客户机里跑dd测试写磁盘。我第一次跑这个对比时virtio的写入速度大概是模拟设备的4到5倍这个数据足够说明问题。5. 高频报错与排查手记5.1 常见问题速查表以下是我在这个实验上收集到的最高频报错按出现概率排序报错现象可能原因排查命令/解法无法打开/dev/kvmCPU虚拟化未开启或KVM模块未加载grep -c vmx /proc/cpuinfomodprobe kvm_intelERROR Failed to connect socket to /var/run/libvirt/libvirt-socklibvirtd未启动systemctl start libvirtderror: Failed to connect socket to /var/run/libvirt/virtlogd-sock当前用户不在libvirt组usermod -aG libvirt 用户名重新登录unsupported configuration: CPU mode custom is not supported--os-variant类型不匹配osinfo-query os查看可用类型客户机安装界面黑屏--graphics参数配置有问题或VNC端口被占用换VNCS端口检查监听地址虚拟机网络不通default网络未启动或网卡模型不匹配virsh net-info default虚拟机启动极慢CPU 100%宿主机内存不足或超卖严重free -h检查宿主机内存磁盘镜像体积异常膨胀qcow2碎片化或频繁快照qemu-img info查看实际占用5.2 三个值得细说的经典故障第一个是libvirtd连不上。有一批实验机器每次重启后libvirtd都没有自动启动查了很久发现不是服务配置问题而是机器内存紧张导致libvirtd被OOM杀掉systemd虽然设置了enable但进程一直起不来。解决办法是调高libvirtd的内存限制或者给宿主机加内存。排查命令是journalctl -u libvirtd日志里会直接写出Out of memory。第二个是客户机系统装完了没有网卡。openEuler客户机默认可能没有启用NetworkManager服务导致即使virtio网卡被识别也没有拿到IP。解决办法是进入客户机后先检查ip addr如果网络接口状态是DOWN就用nmcli或者systemctl restart NetworkManager重新拉起网络服务。这个坑跟KVM本身无关但会让没有Linux网络基础的同学卡很久。第三个是快照回滚失败。virsh snapshot-revert提示“cannot restore to snapshot as it is not the current snapshot”视频教程里很少讲清楚。这是因为Libvirt的快照回滚默认要求目标快照是当前叶子节点如果有更新的快照存在你需要加--force参数强制回滚。但要注意--force回滚会放弃目标快照之后的所有快照链操作前先把快照列表导出一份备份virsh snapshot-list oslab-vm --tree5.3 排查思路分享给刚接触虚拟化的同学一个通用的排查路径先看宿主机再看libvirt最后进客户机。宿主机层用dmesg | grep -i kvm看内核日志确认KVM模块有没有异常libvirt层用journalctl -u libvirtd看守护进程日志或者/var/log/libvirt/qemu目录下每个虚拟机有自己的日志文件客户机层就是进去之后用systemctl status排查各个服务。按照这个顺序查90%的问题都能定位。不要一上来就怀疑虚拟化本身多数报错其实出在环境配置和服务状态上。6. 实验之外嵌套虚拟化与扩展思考6.1 顺手试试嵌套虚拟化嵌套虚拟化是这个实验最有趣的扩展点意思是“虚拟机里面再开虚拟机”。openEuler的KVM默认支持嵌套但需要模块参数配合sudo modprobe kvm_intel nested1确认是否生效cat /sys/module/kvm_intel/parameters/nested输出Y说明支持嵌套。然后你在客户机系统里就能按照同样的流程再装一套KVM环境。这个操作在云原生领域有现实意义——很多CI流水线就是这么跑的宿主机上的隔离容器里再起一套完整虚拟化环境。我做实验的时候给学生演示过这个大家第一次看到虚拟机里有虚拟机都把“虚拟化是假的”这个疑问解决了嵌套环境里的虚拟机性能确实下降明显但指令集和系统调用路径依然是完整的。这种层层包裹的结构恰恰体现了操作系统抽象和复用的精髓。6.2 KVM与云计算的关系第九章实验做完值得想一个更大的问题云计算平台上的虚拟机底层绝大多数都是KVM。一台物理机上跑几十台云主机靠的是什么靠的就是你在实验里用到的这些机制CPU超卖、内存大页、qcow2精简置备、virtio高性能通道、快照迁移。实验课让你手动操作的每一件事在云端都是自动化平台在调度。理解了这层关系再看当前主流云平台思路会通很多。虚拟化管理面的大部分工作无非是给KVM这层能力包一层更友好的API和调度策略。你在实验里学会了virsh等于掌握了这棵技术树的根部。6.3 给后来者的私房建议最后说点实验课之外的经验。第一虚拟机命名别乱起学号拼音也好、实验编号也好整齐划一的命名能让你在virsh list的时候一眼找到目标。第二每完成一个阶段立刻打快照不要攒到最后不然出错只能重装。第三所有修改域配置的操作先备份XML文件virsh dumpxml oslab-vm oslab-vm.xml.bak这个习惯成本极低但能在你把配置改坏之后救你一命。我自己当初做这个实验的时候最深的体会是虚拟化不是神秘魔法它就是操作系统内核能力的一种组合运用。你理解了进程、理解了特权级、理解了中断再看KVM的每一处设计都顺理成章。做完第九章的实验建议回头翻翻理论课讲系统调用那一章你会发现自己原来已经摸到了相对完整的轮廓。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑