
宿主机上能看到虚拟机已经装了qemu-guest-agent客户机里 systemd 也显示服务在运行但执行virsh domifaddr --source agent时返回的 IP 列表仍然是空的。这不是个例。Rocky Linux 10 这类 RHEL 系新版本客户机里qemu-guest-agent装好了并不代表 Host OS 一定能拿到被管 Guest 的 IP。真正的问题通常不在“安装”本身而是藏在服务状态、virtio-serial 通道、客户机网络配置和 qga 命令权限这几层链路里。这篇文章按实际排障顺序走一遍先确认 agent 是不是真的“活着”再查 Host 与 Guest 之间的通道接着看客户机内部网络最后分析 qga 配置、SELinux 和日志。末尾会给出一个批量获取多台虚拟机 IP 的脚本模板适合云平台或虚拟化运维场景。如果你现在正被“装好了代理但拿不到地址”这个问题卡住可以直接对照命令往下查。1. 排障信息速览项说明客户机系统Rocky Linux 10RHEL 系发行版核心组件qemu-guest-agent、libvirt、virtio-serial、NetworkManager典型现象客户机内 agent 已安装且服务 activeHost 端用 agent 来源查不到 IP高概率根因qga 服务未运行、virtio-serial 通道缺失、客户机接口无有效 IPv4、qga RPC 被黑名单拦截、SELinux 干扰主要排查工具systemctl、journalctl、virsh domifaddr、virsh qemu-agent-command、nmcli、ip、ausearch适用场景KVM/QEMU 虚拟化运维、批量虚拟机 IP 自动发现、云平台镜像制作前置要求有 Host 侧 sudo/libvirt 权限客户机可登录建议先在测试虚拟机上操作先明确一点这个问题的排查链路不是一条而是两条。第一条是 Host 到 Guest 的管理通道也就是 virtio-serial 上的org.qemu.guest_agent.0设备第二条是 Guest 内部网络栈是否有可用 IPv4。两条链路都通了Host 才能看到 IP。下面从第一条链路开始。2. 先确认客户机内 agent 是否真的在运行很多人习惯先看“包有没有装”但更好的起点是看服务状态。因为当qemu-guest-agent包通过 RPM 安装后默认会生成一个 systemd 单元文件但服务不一定会自动启动尤其是在模板克隆、镜像转换或者最小化安装场景下。登录客户机依次执行rpm -q qemu-guest-agent qemu-ga --version systemctl status qemu-guest-agent.service systemctl is-enabled qemu-guest-agent.service判断标准rpm -q qemu-guest-agent能输出版本号说明包确实装了。qemu-ga --version能输出版本说明二进制可执行。systemctl status显示active (running)服务才算是真正在跑。systemctl is-enabled显示enabled重启后才会自动拉起。如果服务处于inactive (dead)或failed直接启动并设置开机自启systemctl enable --now qemu-guest-agent.service启动后立刻看服务日志journalctl -u qemu-guest-agent.service -n 200 --no-pager日志里最典型的报错是cant open channel /dev/virtio-ports/org.qemu.guest_agent.0这句话的意思是qga 进程起来了但找不到与宿主机通信的串口设备。出现这种日志问题已经不在 agent 本身而是 Host/VM 之间的virtio-serial通道没建好。这就进入下一步。还需要注意一点在某些自定义加固过的系统里管理员可能会修改 service 的ExecStart参数或者通过/etc/sysconfig/qemu-ga添加了黑名单 RPC。所以启动服务后最好再确认一下实际执行行为systemctl cat qemu-guest-agent.service grep -vE ^#|^$ /etc/sysconfig/qemu-ga如果看到类似--blacklist guest-network-get-interfaces或环境变量BLACKLIST_RPC包含了网络接口命令那即使服务正常Host 侧也查不到 IP。这种情况后面第 5 节会细说。3. 检查 Host 与 Guest 的 virtio-serial 通道qemu-guest-agent 不是走普通网卡和宿主机通信的它依赖一台基于 virtio 的虚拟串口设备。libvirt 管的虚拟机里对应的是 domain XML 中的channel配置。如果这个 channel 不存在或者名称不是标准的org.qemu.guest_agent.0客户机里就不会出现对应的/dev/virtio-ports/设备。到宿主机上查看虚拟机 XMLvirsh dumpxml domain_name | sed -n /devices/,/\/devices/p | grep -B3 -A8 channel正常的配置大致如下channel typeunix source modebind/ target typevirtio nameorg.qemu.guest_agent.0/ /channel如果 XML 中完全没有channel节点说明这台虚拟机在创建时没有给客户机添加 qga 通道。哪怕客户机里已经装好了qemu-guest-agent包服务也只能一直报“打不开设备”。添加方法是在宿主机上编辑虚拟机配置virsh edit domain_name找到devices区域加入上面的 channel 配置。如果虚拟机里没有virtio-serial控制器还需要一并补上controller typevirtio-serial index0 alias namevirtio-serial0/ /controller修改虚拟机的 XML 属于变更操作。生产环境建议先在测试虚拟机上执行确认不会影响其他 virtio 设备后再轮到正式虚机。对于运行中的虚拟机最好选择计划维护窗口重启客户机或者按 libvirt 支持的热插拔方式动态添加设备保守做法是重启后验证。客户机内确认通道是否存在执行ls -l /dev/virtio-ports/ cat /sys/class/virtio-ports/org.qemu.guest_agent.0/name如果/dev/virtio-ports/目录下能看到org.qemu.guest_agent.0并且name文件内容就是org.qemu.guest_agent.0说明通道已经在客户机里注册成功。如果 Host XML 里有 channel客户机里却没有这个设备还需要检查客户机内核是否加载了virtio_console、virtio_serial相关模块或者 udev 规则是否被缺省。一般情况下默认内核都带但如果你用的是极度裁剪的内核就需要重点看模块列表。4. 客户机网络配置agent 查到了接口但没有 IPv4通道没问题、服务也在运行Host 端依然拿不到 IP下一块要查的是客户机内部网络。这里有一个很容易误解的点guest-network-get-interfaces是 qga 直接通过内核网络接口信息收集的不是从 NetworkManager 的 D-Bus 接口读的。所以即使 NetworkManager 看起来正常只要接口在操作系统层面没有 IPv4 地址上报结果就是空。登录客户机先看最基础的信息ip -br address ip -4 addr show nmcli device status nmcli connection show重点观察几点网卡是否处于UP状态。接口上有没有169.254.0.0/16这类链路本地地址没有拿到真实 DHCP 地址。NetworkManager 有没有为这张网卡建立 connection。接口名是否和 connection 绑定的接口名一致。比如系统里网卡叫ens3但 connection 里绑的是eth0就可能导致激活失败。在 Rocky Linux 10 这种 RHEL 系版本上NetworkManager 更偏向使用 keyfile 配置路径在/etc/NetworkManager/system-connections/。如果虚拟机是从老版本升级过来的可能还保留着/etc/sysconfig/network-scripts/ifcfg-*配置文件。两者冲突时会出现“网卡没地址”或者“NetworkManager 不托管该接口”的情况。检查有没有冲突ls -l /etc/sysconfig/network-scripts/ifcfg-* ls -l /etc/NetworkManager/system-connections/如果网卡没有被 NetworkManager 托管先用nmcli建一条连接。以接口ens3为例下面是通用模板地址要按实际网段替换nmcli connection add type ethernet con-name prod-ens3 ifname ens3 \ ipv4.method manual \ ipv4.addresses 192.0.2.10/24 \ ipv4.gateway 192.0.2.1 \ ipv4.dns 192.0.2.53需要走 DHCP 的话nmcli connection add type ethernet con-name prod-ens3 ifname ens3 ipv4.method auto配置完成后激活nmcli connection up prod-ens3执行完再确认ip -4 addr show ens3如果接口能正常拿到 IPv4回到宿主机再查一次。很多时候问题到这里就结束了之前的“拿不到 IP”其实是客户机本身网络配置失效而不是 agent 上报链路坏了。还有一种情况需要特别留意接口上只有 IPv6 地址或者只有 IPv6 链路本地地址。virsh domifaddr --source agent默认展示的地址条目可能不包含纯 IPv6 或链路本地地址所以表里看着是空。想看完整结果要直接调 qga 的 RPC 接口这个在第 6 节讲。5. 排查 qga 配置、SELinux 与异常日志如果前面几步都正常客户机内网络也有 IPv4但 Host 还是拿不到 IP就要进入更细节的配置层排查。先看 qga 是否把网络接口 RPC 加入了黑名单。RHEL/Rocky 系给 qemu-guest-agent 提供了/etc/sysconfig/qemu-ga配置文件。检查这个文件cat /etc/sysconfig/qemu-ga如果看到类似这样的配置问题就出在这BLACKLIST_RPCguest-network-get-interfaces把它改成空值或者移除该 RPC然后重启服务systemctl restart qemu-guest-agent.service同时确认 systemd 单元里的启动参数systemctl show qemu-guest-agent.service -p ExecStart正常启动参数中不应该出现--blacklist guest-network-get-interfaces。如果出现可能是安装后有人做了加固也可能是从某些定制模板继承来的。再看 SELinux。Rocky Linux 默认 SELinux 是 Enforcing尽管 qemu-ga 在客户机内一般不被 SELinux 限制但遇到自定义策略时也可能出现 AVC 拒绝。检查方式getenforce ausearch -m avc -ts recent | grep qemu-ga如果ausearch有输出说明确实有拒绝记录。可以在独立测试环境中临时验证setenforce 0注意这只用于临时定位验证完必须恢复setenforce 1如果确认是 SELinux 策略问题再针对策略模块处理不建议长期关闭 SELinux。日志层面qga 的专用日志通常在/var/log/qemu-ga/qemu-ga.log和 systemd 日志配合看tail -n 100 /var/log/qemu-ga/qemu-ga.log journalctl -u qemu-guest-agent.service --since today常见的日志问题包括failed to write to channelqga 和宿主机的通道断开可能需要重启客户机内 agent或者在宿主机上重启 libvirt 的 agent 会话。unsupported RPCHost 端调用的 RPC 在当前客户机 qga 版本里不支持通常是版本跨度太大导致需要升级客户机里的qemu-guest-agent包。反复 reconnectvirtio-serial 设备被热拔插过客户机内/dev/virtio-ports路径发生漂移重启 qga 服务重新初始化。协议版本兼容是容易被忽略的点。宿主机 QEMU/libvirt 版本比较新客户机内 qga 版本很旧或者反过来都可能出现 RPC 执行失败。升级客户机内 qemu-guest-agent 时注意使用发行版官方仓库不要随意从第三方源装。6. 在宿主机侧验证与批量获取 IP客户机内做完调整后回到宿主机侧验证。最直接的方式是几种数据源对比virsh domifaddr domain_name --source agent virsh domifaddr domain_name --source lease virsh domifaddr domain_name --source arp三种 source 的含义agent通过 qemu guest agent 在客户机内部枚举接口准确度最高。lease从宿主机 DHCP 租约文件里读对 DHCP 分配的地址有效静态 IP 看不到。arp从宿主机 ARP 表反查客户机有流量经过宿主机会出现但可能滞后或缺失。如果 agent 链路还处于不可信状态可以直接调用 qga 的 RPC看看完整返回virsh qemu-agent-command domain_name {execute:guest-network-get-interfaces}返回的 JSON 里会包含每个接口的name、hardware-address和ip-addresses。判断成功的标准很简单ip-addresses数组里能看到合法的 IPv4 地址且前缀掩码正确。确认单台机器没问题后可以做批量查询。下面是一个基于virsh的 bash 循环模板适合节点上虚拟机能被当前用户管理的情况for domain in $(virsh list --name); do ip$(virsh domifaddr $domain --source agent 2/dev/null \ | awk /ipv4/ {print $4} | cut -d/ -f1) if [ -n $ip ]; then echo $domain $ip else echo $domain NO_IP_AGENT fi done批量场景下要考虑单台无响应拖慢整个循环。可以给 qga 调用加超时timeout 5 virsh qemu-agent-command $domain {execute:guest-network-get-interfaces} /dev/null 21 if [ $? -ne 0 ]; then echo $domain agent_timeout fi如果虚拟机数量很多不建议同步循环逐个调用高频率命令尽量分批执行避免对宿主机 libvirt 的有较大瞬时压力。7. 资源占用、稳定性与性能影响qemu-guest-agent 本身是轻量级服务在客户机内的资源开销不大。为什么还要专门说资源占用因为故障场景往往不是常态性能而是批量调用时出现的连锁反应。批量执行virsh qemu-agent-command时每个 RPC 都会占用宿主机到客户机之间的一条 virtio-serial 会话。如果脚本并发过高可能出现宿主机 libvirtd 短暂吃高 CPU。客户机 qga 对大量命令处理不过来响应变慢。通道排队后续 RPC 超时。所以批量查询 IP 时建议控制并发不要直接用xargs -P 32之类的无脑并发。把并发控制在个位数或者使用轮询队列。另一个稳定性和“虚拟机关机后 IP 残留”有关的现象是当客户机被关闭lease 和 arp 数据源可能仍然保留旧记录导致 IP 分配混乱。解决思路就是优先信任--source agent其他来源只做兜底。还有客户机内核升级后可能需要重启 qga 才能正常工作。如果发现某台虚拟机升级内核后 Host 突然拿不到 IP先重启qemu-guest-agent.service再考虑重启虚拟机。8. 高频问题与排查方法问题现象可能原因排查命令解决方案Host 查 IP 为空客户机网络正常qga 服务没运行systemctl status qemu-guest-agent.servicesystemctl enable --now qemu-guest-agent.service服务启动报设备不存在虚拟机 XML 缺少 channells -l /dev/virtio-ports/virsh edit 添加 channel 后重启客户机qga 反复重启日志提示无法写通道通道被热拔插或路径变化journalctl -u qemu-guest-agent.service重启 qga 服务必要时重建通道客户机有 IPHost 仍查不到qga RPC 被黑名单拦截grep BLACKLIST_RPC /etc/sysconfig/qemu-ga清空黑名单后重启服务接口只有 IPv6没有 IPv4DHCP 未成功或静态配置失效ip -4 addr show ens3用 nmcli 修复 IPv4 配置virsh qemu-agent-command 返回不支持qga 版本过旧或过新qemu-ga --version升级客户机内 qemu-guest-agentSELinux 拦截 qga 操作自定义策略限制ausearch -m avc -ts recent测试环境验证后调整策略模块批量查询部分虚拟机超时agent 无响应或通道堵塞timeout 5 virsh qemu-agent-command记录失败清单分批重试模板克隆后所有新虚拟机都查不到模板里 qga 未开机自启systemctl is-enabled qemu-guest-agent在模板中 enable 服务后重新生成镜像表格里的命令是通用模板具体接口名、虚拟机和路径请按实际环境替换。9. 最佳实践让 IP 上报在生产环境稳定可用从“排障”跳到“预防”下面几条经验可以直接落到日常运维里。第一虚拟机模板阶段就把 qemu-guest-agent 装好并且执行systemctl enable --now qemu-guest-agent.service。不要等到批量交付后再补装。模板制作完成后在模板机上先执行一次virsh qemu-agent-command验证确认通道、服务和网络三层都通再发布给业务方使用。第二客户机网络配置统一收敛到 NetworkManager keyfile。通过 nmcli 创建的连接会自动写入/etc/NetworkManager/system-connections/避免 ifcfg 与 keyfile 冲突的坑。接口名尽量在镜像阶段通过 udev 规则或内核参数固定下来防止克隆后接口序号漂移。第三批量获取虚拟机 IP 时把--source agent作为主数据源将lease和arp作为可用性兜底。写脚本时给每条 qga RPC 增加超时失败时记录日志而不是直接中断。数据同步间隔控制在分钟级不要做成秒级轮询。第四定期升级客户机内 qemu-guest-agent。QEMU/libvirt 版本更新后老版本 qga 可能无法执行部分 RPC。升级动作纳入客户机系统补丁流程升级后抽查几台虚拟机验证 agent 连通性。第五注意 qga 的安全边界。qemu-guest-agent 不只是查询 IP还可以执行guest-file-*这类文件操作以及关机、重启等管理命令。它不能暴露在不可信网络里也不建议在未授权的虚拟机上调用。对客户机执行任何 agent RPC 前先确认这台虚拟机在管辖范围里避免越权操作。第六涉及真实业务数据的虚拟机和网络地址信息排障后注意日志脱敏。命令行输出中的 MAC 地址、IPv4 地址、hostname 都属于基础环境数据在粘贴到工单或归档前做模糊处理。10. 最后给一个定位顺序如果再遇到“Rocky 10 客户机装了 qemu-guest-agent但 Host 拿不到 IP”不要先怀疑 agent 没装好。按下面的顺序来在客户机执行systemctl status qemu-guest-agent.service确认服务是 running。检查/dev/virtio-ports/org.qemu.guest_agent.0是否存在不存在就去宿主机看 XML 里的 channel。在客户机执行ip -4 addr show确认接口有合法 IPv4。检查/etc/sysconfig/qemu-ga里的BLACKLIST_RPC。宿主机制执行virsh qemu-agent-command domain {execute:guest-network-get-interfaces}看完整 JSON。还不行就看/var/log/qemu-ga/qemu-ga.log和journalctl -u qemu-guest-agent.service。大部分情况下卡在第 1 步和第 3 步之间要么服务没启要么客户机网络本身没配好。把这两层盘清楚Host OS 大概率就能正常拿到虚拟机 IP。“已安装”不等于“在运行”“在运行”不等于“通道通”“通道通”也不等于“接口有 IP”。这三层齐了--source agent才会真正好用。希望这篇排查笔记能帮你少踩几个坑。