qemu-guest-agent 卡死排障记
摘要
VM1002(办公虚机)的 qemu-guest-agent 出了个怪病:重启虚机后只能管几分钟,然后 PVE 侧就失联了,但虚机内的服务显示 active,SSH 也能连。这篇记录完整的排障过程:先分清 qemu-guest-agent 到底分几层(虚机内服务、virtio 通道、PVE 侧),再逐层排查,最后定位到通道层问题。结论:PVE 经专用密钥直连虚机 SSH,办公中转不受影响,qga 当它不存在。排障的最大收获:分层定位,别在应用层修通道层的病。
目录
一、先分清:qemu-guest-agent 到底分几层
qemu-guest-agent(qga)是 PVE 管理虚机的"手",但它不是一根线,而是三层:
PVE 宿主机 ←→ virtio-serial 通道 ←→ 虚机内的 qemu-guest-agent 服务
第 3 层 第 2 层 第 1 层
| 层 | 位置 | 职责 | 坏了的表现 |
|---|---|---|---|
| 第 1 层 | 虚机内 | qemu-guest-agent 服务,执行 PVE 发来的指令(关机、查 IP、fsfreeze) | 服务 inactive,PVE 侧报 agent 未运行 |
| 第 2 层 | 虚拟硬件 | virtio-serial 通道,PVE 和虚机之间的数据线 | 服务 active 但 PVE 侧超时,指令发过去没回音 |
| 第 3 层 | PVE 宿主机 | PVE 的 qm guest 命令,收发指令 | qm 命令本身报错 |
分层的意义:排障时先定位是哪一层坏了,再修那一层。在第 1 层重装服务,治不好第 2 层的通道病。
二、症状:重启只能管几分钟
VM1002(Debian 13,办公虚机)的症状:
- PVE 面板上,虚机的 IP 信息、关机/重启按钮,重启后能用几分钟,然后失联;
- 虚机内
systemctl status qemu-guest-agent显示 active,服务本身没挂; - 虚机的 SSH(经 nps 隧道 22223)正常,业务不受影响;
- PVE 侧
qm guest cmd 1002 ping超时。
"服务 active 但 PVE 侧不通",直接指向第 2 层:virtio 通道。服务活着,线断了。
三、逐层排查
第 1 层:虚机内服务
# 经 SSH 进虚机
systemctl status qemu-guest-agent
# active (running),没问题
# 看 agent 的 socket
ls -l /run/qemu-ga/
# 正常
第 1 层正常,排除。
第 2 层:virtio 通道
# PVE 宿主机上,看虚机的 qga 通道
qm config 1002 | grep agent
# agent: enabled=1,配置没问题
# 试发 ping
qm guest cmd 1002 ping
# 超时
配置是对的,ping 不通。结合"重启后能管几分钟",像是通道在虚机运行一段时间后断掉。virtio-serial 通道的状态,PVE 侧不好直接看,这是 qga 排障最难受的地方:中间这层是黑盒。
第 3 层:PVE 侧
# PVE 侧 qm 命令本身正常(别的虚机 qga 好用)
qm guest cmd 100 ping
# 通,说明 PVE 侧没问题
别的虚机 qga 正常,说明 PVE 侧的收发逻辑没坏。问题锁定在 VM1002 的第 2 层:virtio 通道层。
尝试过的修复(都没根治)
- 重启虚机内的 qemu-guest-agent 服务:好几分钟,又断;
- 重启虚机:好几分钟,又断;
- 检查虚机配置的 agent 开关:enabled=1,没问题。
"重启只能管几分钟"这个模式,指向通道层的间歇性故障,不是配置问题。配置问题要么一直坏,要么一直好,不会"好几分钟"。
四、应急:PVE 直连虚机 SSH
qga 失联期间,虚机的管理不能停。应急通道:PVE 宿主机经专用密钥直连虚机的 SSH:
# PVE 宿主机上(经 /root/.ssh/id_pve_home 免密)
ssh -i /root/.ssh/id_pve_home root@192.168.0.60
# VM1002 的内网 IP,直接连,不走 qga
这条通道走的是正常的 TCP SSH,和 qga 的 virtio 通道完全独立。qga 断了,SSH 照样能进虚机执行命令、传文件。办公中转(office-relay.sh)走的就是这条路,不受影响。
教训:关键虚机至少要有两条管理通道。qga 是 PVE 的原生通道,SSH 是独立通道。一条断了,另一条顶上。单通道等于单点故障。
五、结论:通道层问题,绕行
最终结论:VM1002 的 qga 问题在 virtio 通道层,虚机内服务和 PVE 侧都正常。目前的策略是绕行:
- 日常管理走 SSH 直连(PVE 宿主机 → 虚机内网 IP);
- qga 的 IP 信息、优雅关机等功能暂时不用;
- 关机用
qm stop(硬关机)或进虚机poweroff,不用 qga 的 guest-shutdown。
为什么不去根治通道层?因为 virtio 通道是黑盒,PVE 侧可调的东西有限(开关 agent、换 virtio 版本、重建虚机配置),都试过没根治。重建虚机能根治,但 1002 是办公虚机,60G 数据,重建成本太高。在"有可用绕行方案"的前提下,接受现状,把精力放更重要的事上。这是工程取舍:不是所有 bug 都值得修,修的成本要和影响匹配。
六、排障方法论
这次排障沉淀的方法论,通用:
- 先分层,再定位:把系统拆成层,逐层验证,缩小范围。qga 分三层,网络分七层,道理一样。
- 用"正常对照组":别的虚机 qga 正常,说明 PVE 侧没问题。对照组是定位的利器。
- 看模式,不只看现象:"重启好几分钟"这个模式,比"连不上"这个现象更有信息量。间歇性 + 重启恢复,指向状态/通道类问题,不是配置类。
- 先保业务,再修根因:SSH 绕行先让管理不断,根因慢慢查。排障时业务连续性优先。
- 接受"绕行"是合法结论:修的成本 > 影响时,绕行就是正确答案。记下来,定期回头看。
qga 的常用功能:除了排障还能干什么
qga 修不好,不代表它没用。正常工作的虚机上,qga 是 PVE 的"手",常用功能:
| 功能 | 命令 | 说明 |
|---|---|---|
| 查虚机 IP | qm guest cmd <vmid> network-get-interfaces |
PVE 面板上显示的 IP 就是这么来的 |
| 优雅关机 | qm guest cmd <vmid> shutdown |
走虚机内关机流程,比硬关机安全 |
| 执行命令 | qm guest exec <vmid> -- <命令> |
PVE 侧直接在虚机里跑命令 |
| 冻结文件系统 | guest-fsfreeze-freeze/thaw |
备份前冻结,保证数据一致性 |
vzdump 备份时如果开了 qga 的 fsfreeze,备份的是"静止"的文件系统,恢复后数据更干净。这就是备份体系里 qga 的位置:平时是管理手,备份时是数据一致性的保障。
PVE 侧管理虚机的命令速查
不依赖 qga,PVE 宿主机本身就能管虚机:
| 操作 | 命令 |
|---|---|
| 开机/关机 | qm start/stop <vmid>(stop 是硬关机) |
| 重启 | qm reboot <vmid> |
| 看配置 | qm config <vmid> |
| 进控制台 | qm terminal <vmid> |
| 容器 | pct start/stop/enter/exec <ctid> |
qm terminal 是串口控制台,不走网络,虚机网络挂了也能进。pct enter 进容器,pct exec 跑单条命令。这两个是 LXC 的日常,比 qga 还常用。记住:PVE 侧的命令是"宿主机视角",qga 是"虚机内视角",两个视角互补。
排障心态:从"修好它"到"理解它"
qga 这个坑,最后没有"修好",而是"绕行"。这个结论下得不容易,因为技术人的本能是"修好它"。但排障的成熟度,恰恰体现在知道"什么时候不修"。
修与不修的账:修的成本是重建 60G 的办公虚机(数据迁移、环境重配、至少半天停机),修的收益是 qga 的 IP 显示和优雅关机;不修的成本是少两个小功能,不修的收益是零风险、零停机。这笔账算完,绕行是理性选择。技术决策不是"能不能修",是"值不值得修"。值不值得,看三个数:影响多大(qga 断了,业务没断)、修的成本多高(重建虚机半天起)、有没有替代方案(SSH 直连)。三个数摆出来,结论自己浮现。
理解比修好更重要:虽然没修好,但这次排障把 qga 的三层模型搞透了,以后任何虚机的 qga 问题,5 分钟能定位到层。这个"理解"是永久资产,下次遇到同类问题直接受益。排障记录的价值不在"修好了",在"理解了"。很多坑,第一次花两小时,第二次花五分钟,差的就是这份理解。
接受"带病运行":生产系统没有 100% 健康的,都是"带病运行"。区别在于:病的 part 有没有被隔离、有没有替代方案、有没有记录在案。qga 的病被隔离在"管理通道"(SSH 顶着)、有替代方案(直连)、有记录(这篇)。带病运行不可怕,可怕的是"不知道自己有病"。定期回头看这些"绕行"的结论:也许半年后 PVE 升级了,通道层的 bug 修了,那时再回头根治。绕行不是放弃,是"择时再战"。
虚拟化的管理面:PVE、qga、SSH 三者的分工
PVE 管虚机,有三条路:PVE 面板(Web)、qga(virtio 通道)、SSH(网络)。三者的分工,值得一次说清。
| 通道 | 走什么 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| PVE 面板 | HTTPS(8006) | 图形化,直观 | 依赖网络和管理服务 | 日常查看、点按钮 |
| qga | virtio-serial(不走网络) | 网络挂了也能用,能拿虚机 IP、优雅关机 | 通道层可能出问题(本文的坑) | 网络故障时的救命稻草 |
| SSH | TCP 22(走网络) | 最通用,能干一切 | 依赖网络通、sshd 活着 | 日常运维的主力 |
三者的关系是"互补",不是"替代"。网络正常时,SSH 是主力(脚本、ansible、日常);网络挂了,qga 是救命稻草(不走网络);都不想敲命令,面板点按钮。关键虚机,三条路都要通:面板能开、qga 装着、SSH 密钥配好。单通道是单点故障,管理通道也一样。
这次 qga 断了,SSH 顶着,业务没断,就是"多通道"的价值。如果当时只有 qga 一条路,1002 的管理就全瞎了。管理面的冗余,和数据的冗余一个道理:平时觉得多余,出事时救命。配新虚机时,三条管理通道一次性配齐,别偷懒。
还有一个细节:PVE 宿主机到虚机的 SSH,走的是内网(192.168.0.x),不依赖 nps 隧道、不依赖公网。内网通,管理就通。这是"家里"的优势:物理上离得近,管理通道不经过公网。公网是"业务"的路,内网是"管理"的路,两条路分开,公网断了,管理还在。
qga 的日志:在哪看
qga 出问题,日志在哪?两头看。
虚机内:journalctl -u qemu-guest-agent,看服务有没有报错、重启记录。如果服务一直在重启(restart loop),日志里能看到原因(比如 socket 权限、配置错误)。服务 active 但 PVE 不通,日志通常是干净的——因为病在通道层,不在服务层。日志干净,本身就是信息:排除法,服务没问题。
PVE 侧:/var/log/syslog 或 journalctl,搜 qemu-ga、guest-agent。PVE 侧能看到"发了什么指令、收没收到回音"。qm guest cmd 超时,PVE 侧日志会有记录。两头对照:虚机内说"我活着",PVE 侧说"我喊了没人应",中间断的,就是通道。
日志是排障的"第一现场"。动手改配置前,先看 5 分钟日志。很多"怪病",日志里第一行就写了原因,只是没人看。
排障的终点不是"修好",是"下次更快"。这篇就是为了下次。管理通道三件套(面板、qga、SSH),配新虚机时一次性配齐。通道断了别慌,SSH 直连是永远的备胎。备胎平时不用,但不能没有。管理通道的冗余,和数据的冗余一个道理:平时觉得多余,出事时救命。这次 qga 断了 SSH 顶上,就是证明。证明一次,就够了。
qga 的通道问题,还有一个排查方向:PVE 宿主机的 libvirt 日志。virtio-serial 通道是 qemu 提供的,通道层的问题,journalctl -u qemu 或 dmesg 里可能有线索(比如 virtio 设备重置、ring buffer 溢出)。这次没深挖(SSH 备胎够用),但记下来:通道层的问题,看宿主机侧的日志,别只盯着虚机内。排障的视野,要覆盖"通道的两端",而不只是"出问题的一端"。视野全了,怪病才有解。视野不全,就只能靠备胎。备胎靠得住,是因为平时配得全。配得全,靠的是这篇这样的记录。记录写下来,下次就不用从头查。这就是记录的复利。
七、总结
qemu-guest-agent 卡死的排障:分三层(虚机内服务、virtio 通道、PVE 侧),逐层查,定位到通道层间歇性故障。应急靠 PVE 直连虚机 SSH,业务不受影响。结论是绕行:修的成本(重建 60G 办公虚机)大于影响(有 SSH 顶着),接受现状。记住:关键虚机至少两条管理通道;排障先分层;"重启好几分钟"这种模式比现象本身更说明问题。