多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

KVM管理工具深度解析:从virsh到virt-manager的选型与实践

KVM管理工具深度解析:从virsh到virt-manager的选型与实践 1. KVM管理工具全景为什么到了Part 7还要专门聊工具聊到KVM虚拟化很多人第一反应是不就是装个libvirt跑个virt-manager嘛。但真当你把虚拟机规模从三五台撑到几十台从自己笔记本上的实验环境挪到机房里的宿主机你会发现管理工具这件事远没有想象中那么简单。这篇Part 7的内容核心就一个主题KVM的管理工具到底该怎么选、怎么配、怎么用。我不打算给你罗列一堆命令然后说你看这些都能管虚拟机那没意思。我想拆的是工具背后的设计逻辑——为什么有些场景你必须用命令行有些场景用图形界面反而更顺手有些时候你又得绕开这些通用层直接去碰底层组件。把这些想明白了你再看那些眼花缭乱的工具列表心里自然就有谱了。适合看这篇内容的人我猜有这么几类刚入门KVM、被一堆virt-*命令搞晕的新手已经在用KVM但主要靠virt-manager点点点、想往自动化方向走的进阶用户还有那些需要在生产环境里做批量运维、但还没找到顺手工具链的实践者。无论你属于哪一类这篇内容都值得你花十分钟细看。先交代背景这个系列写到第7篇前面已经覆盖了KVM的安装、网络、存储、克隆迁移这些基础能力。Part 7专门聊管理工具其实是把前面那些能力收拢到一个怎么日常操作的层面。换句话说前面是造车这篇是讲怎么开、怎么保养、怎么在车出毛病的时候快速定位问题。2. 管理工具的层次划分别再把libvirt和KVM混为一谈很多教程一上来就让你装libvirt但很少有人讲清楚libvirt在整个KVM体系里到底站在哪个位置。我见过不少朋友把libvirt和KVM当成同一个东西其实这俩完全是两个层面的概念。KVM本身是内核模块它负责把Linux内核变成一个大号虚拟机监控器提供CPU虚拟化、内存虚拟化这些最底层的能力。但KVM模块本身并不提供创建虚拟机管理虚拟机生命周期这类操作接口——它只提供能力不提供服务。就好比一台发动机它能输出动力但你不能直接坐上去开。你还需要变速箱、方向盘、仪表盘这些组件才能把这台发动机真正用起来。libvirt就是那套仪表盘系统。它是一套开源的虚拟化管理API屏蔽了底层不同虚拟化技术的差异——KVM也好Xen也好QEMU也好libvirt都提供统一的管理接口。我们用virsh、virt-manager这些工具操作虚拟机本质上都是在调用libvirt的API而不是直接跟KVM内核模块打交道。这个分层设计是KVM管理工具的基石。明白了这层关系你才能理解为什么有时候某些功能在virsh里没有但用QEMU原生命令却能做到——因为libvirt作为中间层它提供的功能集合是跨平台通用的有些KVM/QEMU特有的高级特性libvirt的API可能还没来得及暴露出来。管理工具按照跟libvirt的关系大致可以分成三层直接基于libvirt的通用管理工具比如virsh、virt-manager、virt-install基于libvirt但侧重特定场景的工具比如oVirt、OpenStack里的计算节点组件绕过libvirt、直接操作QEMU/KVM底层组件的工具比如qemu命令行、guestfish这三层各有各的适用场景。对于个人用户和小型实验环境第一层就完全够用对于中型私有云环境第二层里的oVirt是主流选择当你需要做非常底层的调试或者镜像定制时第三层的工具反而更灵活。后面我会逐个展开讲。3. virsh最值得花时间吃透的命令行工具箱如果说KVM管理工具有一个必须精通的东西那一定是virsh。virt-manager那些图形界面工具你做熟了之后会发现底层就是封装了virsh的各类命令。把virsh命令搞熟练你不仅能在没有图形界面的服务器上从容管理虚拟机还能顺手把日常运维脚本化、自动化这是图形界面永远做不到的。3.1 virsh的核心操作从创建到销毁的完整生命周期virsh命令覆盖了虚拟机从定义到销毁的完整生命周期。我先把最常用的一批命令给你梳理一遍每个命令附上我实际使用时的习惯和注意点。创建虚拟机有两个层次virsh define和virsh create。前者是定义一个虚拟机—也就是说你有一个XML描述文件告诉libvirt这台虚拟机的硬件配置、存储、网络等信息然后把它注册到系统中但这时候虚拟机还没启动。后者则是定义并立即启动。我个人的习惯是用define注册确认配置无误后再用virsh start启动这样万一配置有问题不会对现有环境造成意外影响。# 定义一个虚拟机仅注册不启动 virsh define /path/to/vm.xml # 启动已定义的虚拟机 virsh start vm-name # 定义并立即启动 virsh create /path/to/vm.xml # 查看运行中的虚拟机列表 virsh list # 查看所有虚拟机包括已关机但已定义的 virsh list --all这里有个细节值得单独拎出来说virsh list默认只显示运行中的虚拟机加上--all才会显示所有已定义的虚拟机。我见过不少新手在虚拟机关机之后用virsh list查不到以为虚拟机被删了其实就是漏了--all参数。关机和销毁同样容易混淆。virsh shutdown是发送ACPI关机信号给虚拟机让客户机操作系统优雅退出相当于在虚拟机里点了关机virsh destroy则是强制断电直接终止虚拟机进程。这就好比你按了一下主机电源键和直接拔掉电源线的区别。日常使用中能shutdown就尽量shutdown频繁destroy容易导致客户机文件系统损坏。# 优雅关机发送ACPI关机信号 virsh shutdown vm-name # 强制停止相当于拔电源 virsh destroy vm-name # 彻底删除虚拟机定义注意不影响磁盘镜像文件 virsh undefine vm-name # 彻底删除虚拟机定义并同时删除磁盘镜像谨慎使用 virsh undefine vm-name --remove-all-storageundefine这个命令尤其要注意它只是删除虚拟机的定义虚拟机使用的磁盘镜像文件并不会被删除。想要连同磁盘一起删得加--remove-all-storage参数。我平时在清理实验环境时会先用virsh list --all确认当前存在的虚拟机再用virsh undefine --remove-all-storage批量清理但每次执行前都会再三确认磁盘路径避免误删有用的数据。3.2 通过virsh调整虚拟机配置两种思路两个场景改虚拟机配置在virsh里有两条路virsh edit和virsh setvcpus这类专用命令。virsh edit vm-name会打开一个临时XML文件让你编辑保存后libvirt会自动帮你做语法检查。这是最直观的方式但要求你懂XML格式。如果你要改的是CPU核数、内存大小这类高频配置用virsh setvcpus、virsh setmaxmem这类专用命令更方便不用去翻XML文件。# 设置虚拟机的CPU核数注意部分配置需要虚拟机处于关机状态 virsh setvcpus vm-name --count 4 # 设置虚拟机最大内存需要关机 virsh setmaxmem vm-name --size 8G # 设置虚拟机当前内存Online调优时使用 virsh setmem vm-name --size 4G --live这里有个生产环境里非常实用的小技巧virsh setmem可以做在线内存调整不需要重启虚拟机。前提是客户机操作系统本身支持内存热插拔而且你在XML里提前配置了相关的内存设备。我在临时扩容、处理内存紧张问题时经常用到这个能力省去了重启虚拟机的麻烦。热插拔CPU也是一样Linux的客户机一般支持在线添加CPU但Windows客户机对CPU热插拔的支持比较微妙建议在Windows虚拟机上不要随便在线加CPU容易出问题。3.3 快照管理给你的虚拟机上保险快照是KVM管理里非常实用、但很多人忽略的功能。你可以把快照理解成虚拟机的存档——在做危险操作之前打一个快照操作翻车了就直接回滚比备份恢复要快得多。# 创建快照 virsh snapshot-create-as vm-name snapshot-name --description 升级内核前的存档 # 查看快照列表 virsh snapshot-list vm-name # 回滚到指定快照 virsh snapshot-revert vm-name snapshot-name # 删除指定快照 virsh snapshot-delete vm-name snapshot-name用快照的时候有两个坑必须提醒你。第一快照不等于备份。快照依赖原始磁盘镜像如果原始镜像文件损坏或丢失快照也救不了你。所以重要数据该做备份还是得做备份快照只是短期回滚工具。第二快照回滚前务必确认客户机状态。如果你在虚拟机运行中创建了快照回滚时会顺带回滚到快照时刻的内存状态未写入磁盘的数据会丢失。建议在回滚前先virsh shutdown客户机确保数据一致。我还试过用快照做预演回滚——就是先打快照然后对虚拟机做操作稳定运行几天后再用snapshot-revert把环境拉回操作前的状态这样验证某些变更风险就小了很多。4. virt-install与virt-manager从命令行自动化到图形界面管理virsh命令管理已有虚拟机很顺手但创建新虚拟机时手写XML还是太痛苦。virt-install就是解决这个问题的——它让你用一条命令完成虚拟机的完整创建流程从磁盘分配、ISO挂载到系统安装引导全部自动化。而virt-manager则是图形界面版的综合管理工具适合不太熟悉命令行、或者需要直观查看虚拟机状态的人。4.1 virt-install一条命令完成虚拟机创建virt-install是创建虚拟机的瑞士军刀。我日常创建虚拟机基本都用它极少手写XML。它的核心优势在于把创建磁盘镜像定义硬件配置指定安装介质启动安装程序这一整套流程压缩成一条命令。下面这条命令是我最常用的模板创建一台CentOS Stream虚拟机virt-install \ --name centos-test \ --memory 4096 \ --vcpus 4 \ --disk path/var/lib/libvirt/images/centos-test.qcow2,size20,formatqcow2 \ --network networkdefault \ --osinfo detecton,namecentos-stream9 \ --cdrom /var/lib/libvirt/isos/CentOS-Stream-9-latest-x86_64-dvd1.iso \ --graphics vnc,listen0.0.0.0 \ --noautoconsole拆解一下每个参数的实际意义--name虚拟机名字后面所有virsh操作都用这个名字引用--memory和--vcpus内存大小和CPU核数。单位是MiB4096就是4GB--disk path...,size20,formatqcow2指定磁盘路径、大小和格式。qcow2格式支持快照和稀疏分配是我在测试环境的首选--network networkdefault使用libvirt默认的NAT网络。如果你有配置好的桥接网络这里改成networkbr0之类--osinfo指定客户机操作系统信息让libvirt自动选择合理的虚拟硬件配置--cdrom系统安装ISO镜像路径--graphics vnc,listen0.0.0.0开启VNC图形输出并监听所有地址方便后续用VNC客户端完成系统安装--noautoconsole创建完成后不要自动打开控制台而是让它在后台静默运行--noautoconsole这个参数是我特别在意的。不加它的话virt-install创建完虚拟机会直接尝试连接虚拟控制台如果你的终端不支持命令可能会卡住。加上它创建完就返回命令行提示符后续用virsh console或VNC自行连接就行在自动化脚本里尤其好用。我还踩过一个跟--osinfo有关的坑。早先的virt-install版本里如果没有正确指定操作系统类型创建出来的虚拟机会使用非常保守的默认硬件配置——比如默认网卡模型是rtl8139而不是virtio磁盘总线是IDE而不是virtio。这会导致虚拟机性能明显下降。后来版本加了osinfo自动检测才好很多。所以不管用哪个版本建议一定显式指定--osinfo别贪图省事省略。4.2 virt-manager图形界面里的虚拟机控制台virt-manager是KVM管理工具里最亲民的一个。它提供图形化的虚拟机列表、资源监控、虚拟硬件配置界面还内置了VNC/SPICE客户端你不需要额外工具就能打开虚拟机的图形桌面。对刚接触KVM的朋友我建议先通过virt-manager建立直觉——创建虚拟机、改配置、看监控曲线这些操作在图形界面里做一遍你对虚拟机的形态就有了直观认知。之后再转到virsh命令你会发现命令理解起来快很多因为你在图形界面里已经见过那些硬件单元长什么样了。virt-manager还有一个隐藏能力它可以连接远程的libvirt服务。也就是说你可以在本地电脑上打开virt-manager通过SSH连接到机房里跑KVM的宿主机远程管理那台宿主机上的所有虚拟机。配置方法是File - Add Connection选择QEMU/KVM勾选Connect to remote host填上宿主机IP和SSH用户名。这个能力对于没有部署集中管理平台的小团队来说非常实用省去了专门装一套web管理系统的麻烦。不过virt-manager的短板也很明显它不适合批量操作。你要给20台虚拟机统一改内存配置在virt-manager里一台一台点过去能点到怀疑人生。这种场景还是写脚本调用virsh靠谱。4.3 一条实用的创建流程用virt-install打底用virt-manager做局部调整我平时创建虚拟机的标准流程是这样先用virt-install快速建好虚拟机如果安装过程中需要图形交互就打开virt-manager附带的VNC控制台如果只是命令行安装就virsh console连上去。创建完成后需要微调硬件配置时再在virt-manager的图形配置界面里改或者直接virsh edit改XML。这套流程的好处是创建虚拟机的过程是命令行的、可脚本化的、可重复执行的而运行中的图形监控和临时调整则受益于图形界面的直观性。两者结合既不牺牲自动化能力又不牺牲可视化体验。5. 系统资源监控与性能调优管理工具不只是开关虚拟机很多朋友把管理工具理解为创建虚拟机、启动虚拟机、关闭虚拟机这其实是把管理工具看窄了。一台宿主机上跑着十几台虚拟机你最需要关注的不是哪台虚拟机开着而是宿主机资源够不够用哪台虚拟机在抢资源怎么让资源分配更合理。这些能力virsh同样提供了。5.1 宿主机与虚拟机资源监控virsh提供了几个监控虚拟机资源使用情况的命令日常运维中我会频繁使用# 实时查看CPU、内存、磁盘IO的使用情况 virsh domstats vm-name # 查看虚拟机CPU利用率 virsh vcpuinfo vm-name # 查看虚拟机的块设备信息磁盘读写 virsh domblkstat vm-name # 查看虚拟机的网络接口统计 virsh domifstat vm-name vnet0virsh domstats是这里最全面的一个命令它能一次性输出CPU时间、内存使用、块设备IO、网络收发等大量信息比逐个调用其他统计命令更高效。不过domstats的输出格式比较机械适合脚本通过--raw参数做机器解析。宿主机层面的监控我习惯配合Linux命令一起看用top或htop看CPU负载用free -h看内存余量。但虚机场景里有两个指标要特别留心一是CPU steal——这个指标表示宿主机CPU资源紧张时虚拟机等待CPU的时间占比如果它持续较高说明宿主机CPU已经过载二是内存的balloon机制——libvirt默认启用了内存气球驱动客户机内存可以动态伸缩但这有时候会导致虚机实际可用内存和XML里配置的不一样的困惑。5.2 资源限额与超分配宿主机资源的“分蛋糕”逻辑KVM允许你配置虚拟机使用的CPU份额、内存上限、磁盘IO上限等在工具层面这些能力叫资源限额。CPU方面除了vcpuinfo查看利用率你还可以通过virsh schedinfo调整虚拟机的CPU调度优先级# 查看虚拟机的CPU调度参数 virsh schedinfo vm-name # 设置CPU份额数值越高优先级越高 virsh schedinfo vm-name --set cpu_shares2048默认情况下cpu_shares通常是1024。当你把某台虚拟机的cpu_shares调到2048在CPU竞争激烈时它会获得另一台默认虚拟机两倍的CPU时间。这个参数是生产环境里做优先级控制很关键的手段——比如把数据库虚拟机的份额调高把测试虚拟机的份额调低。内存方面用virsh setmaxmem设置虚拟机的最大内存用virsh setmem调整当前分配内存。生产环境里我一般比较保守不会让所有虚拟机的maxmem加起来超过宿主机物理内存太多因为内存超分配过度容易导致宿主机内存耗尽、触发OOM killer误杀进程。磁盘IO方面可以通过virsh blkdeviotune设置IOPS上限和吞吐量上限防止某台虚拟机把宿主机的磁盘IO打满。5.3 性能调优工具不止libvirt这一层日常管理中很多性能问题光靠virsh看不出门道得深入到KVM/QEMU自身去看。比如qemu-monitor-command可以直接往QEMU monitor发送命令查看一些libvirt没有暴露的底层信息。perf kvm和kvm_stat则是分析KVM虚拟化性能瓶颈的利器它们能看到精确到内核态的KVM事件统计。不过我要强调一个原则性能调优最重要的不是工具用得多高级而是先搞清楚瓶颈在哪。是CPU是内存是磁盘IO是网络perf和kvm_stat只是放大镜你得先知道观察哪里才是关键。我见过一些新手连虚拟机的CPU和内存都没看就直接上perf去抓内核trace花了一整天最后发现是磁盘模式没选对——一堆IDE磁盘的虚拟机性能自然上不去。先轻量级地看virsh domstats和top锁定方向后再上重武器效率会高得多。6. 常见问题与排查技巧实录那些官网上不会写清楚的细节工具用多了总会遇到各种为什么不行的时刻。这一节我把自己这几年在KVM管理工具实操中踩过的、见过的问题集中整理出来按现象—原因—解决的形式给你一份可以直接照抄的排查速查表。6.1 常见问题速查表现象常见原因解决思路virsh list --all看不到某台虚拟机该虚拟机从未被define或已被undefine检查XML文件是否还存在重新define虚拟机关机后virsh list为空忘记加--all参数使用virsh list --all查看所有已定义虚拟机virsh destroy后虚拟机无法启动客户机文件系统损坏尽量使用shutdown而非destroy损坏后用维护模式修复virt-install创建后无法连接VNC防火墙未放行VNC端口或--graphics没有设置listen0.0.0.0检查防火墙确认listen参数virsh console连接后无输出客户机未配置串口终端或GRUB配置不支持串口输出修改客户机内核启动参数添加consolettyS0创建虚拟机速度特别慢磁盘格式选了raw或qcow2未开启缓存使用qcow2并合理设置cache模式测试环境可用nonevirsh edit修改配置后报错退出XML格式错误或引用了不存在的存储卷/网络virsh edit自带语法校验按提示修正检查UUID、路径引用虚拟机性能明显低于宿主机预期客户机未安装virtio驱动安装并加载virtio驱动Windows客户机需单独注入virtio驱动这里额外说两句virsh console。virsh console vm-name是通过半虚拟化串口连接的文本控制台它非常轻量适合排查网络故障——哪怕虚拟机的网络完全不通控制台依然能连。但前提是客户机要配置好串口终端。Linux客户机需要在GRUB的kernel命令行里加上consolettyS0并且确保串口设备存在。没配过串口的虚拟机virsh console连上去就是一片黑这时候不要慌不是工具坏了是客户机没把输出导向串口。6.2 排查“虚拟机突然失联”的通用思路虚拟机突然连不上是最常见的生产事故。我的排查顺序一般是这样第一步先看宿主机上虚拟机进程是否还活着virsh list ps aux | grep qemu如果虚拟机进程没了说明虚拟机崩溃或者被误关了检查系统日志和libvirt日志。第二步如果虚拟机进程还在但网络不通用virsh domifstat看看网卡状态再确认宿主机网络、桥接配置是否正常。第三步如果网卡正常但业务连不上用virsh console登录客户机检查系统状态。这时候串口控制台就是救命稻草它不依赖网络。第四步如果以上都正常但依然有问题那就得看宿主机资源——是不是内存耗尽、磁盘满了。virsh domstats输出里会有明确的数据。这条链路走下来绝大多数“虚拟机关联”问题都能定位到具体环节。我特别想强调的是不要一上来就virsh destroy重启虚拟机那是最后的手段。先排查、再处理避免自己把现场破坏了。6.3 备份与恢复的实操补充管理工具里还有一个经常被忽略的职责备份。严格来说virsh没有一个直接备份虚拟机的命令但你可以用它的组合拳完成备份。推荐的方式是用快照加外部备份结合。先关机或暂停虚拟机创建一致性快照然后拷贝磁盘镜像文件最后清理快照。如果你的虚拟机上跑着数据库备份前最好先确保数据落盘——在客户机里执行sync或直接停已知服务保证磁盘上的数据是可恢复的。我在生产环境里的习惯是常规数据用libguestfs直接挂载qcow2镜像文件做文件级备份整机备份才用快照加镜像拷贝。文件级备份更轻量恢复时还能只找回单个文件。整机备份则适合灾难恢复场景。7. 再分享一个我喜欢的小技巧用libvirt hooks实现自动化管理工具这部分最后说一个不算主流、但实际很管用的扩展点——libvirt的hooks机制。libvirt允许你在虚拟机生命周期事件触发时执行自定义脚本比如在虚拟机启动后自动执行一段命令。hooks脚本放在/etc/libvirt/hooks/目录下文件名对应事件类型比如qemu。脚本接收的参数包括虚拟机名称、操作类型等。我用它做过一个很简单的场景让所有虚拟机的iptables规则在虚拟机启动后自动加载省去了每次启动后手动配环境的重复劳动。这个功能想强调的其实不是hook脚本本身而是管理工具的思路——KVM管理工具的生态是开放的官方工具不满足需求时你有充分的余地通过脚本、API去扩展自动化能力。掌握virsh、virt-install这些基础工具再理解libvirt的API和事件机制你就能组合出各种适应自己环境的运维方案。我个人的体会是KVM管理工具的学习曲线并不陡峭但需要你沉下心把virsh命令和XML配置两个基本功打好。图形界面工具再方便也永远替代不了命令行的灵活和可控。把这个基础打牢了后面再接触oVirt、OpenStack这些更重的管理平台你会发现核心概念全都相通——无非是把libvirt这套东西包装得更花哨、更自动化罢了。最后提醒一句无论用什么工具生产环境的变更操作都要留好退路。打快照、做备份、写回滚脚本这些“保护性操作”比你想象中更重要。管理工具的本质是帮你驾驭虚拟机但真正可靠的运维习惯才是你最重要的工具。
返回列表