强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

QEMU 虚拟化完全指南 / 09 - QEMU Guest Agent

09 - QEMU Guest Agent

掌握 QEMU Guest Agent(QGA)的安装、配置与使用,实现宿主机与虚拟机之间的自动化通信与管理。


9.1 Guest Agent 概述

QEMU Guest Agent(qemu-ga) 是运行在虚拟机内部的守护进程,通过 virtio 串口通道与宿主机上的 QEMU 进程通信,实现宿主机对虚拟机的管理操作。

Guest Agent 通信架构:
  ┌─────────────────────────────────────────────┐
  │           宿主机 (Host)                      │
  │                                             │
  │   QEMU Process                              │
  │   ┌───────────────────────┐                 │
  │   │  virtio-serial 通道    │◄── QMP 命令     │
  │   └───────────┬───────────┘                 │
  │               │ (virtio)                    │
  ├───────────────┼─────────────────────────────┤
  │               │ (虚拟机内)                   │
  │   ┌───────────┴───────────┐                 │
  │   │  qemu-ga (Guest Agent)│                 │
  │   │  监听 virtio 串口     │                 │
  │   └───────────────────────┘                 │
  │           虚拟机 (Guest)                     │
  └─────────────────────────────────────────────┘

功能清单

功能说明LinuxWindows
文件系统冻结fsfreeze,保证快照一致性✅ (VSS)
文件系统解冻fsthaw
获取文件系统信息guest-get-fsinfo
获取主机名guest-get-host-name
获取 OS 信息guest-get-osinfo
获取网络信息guest-network-get-interfaces
获取时间guest-get-time
设置时间guest-set-time
执行命令guest-exec / guest-exec-status
文件读写guest-file-open/read/write/close
用户管理guest-*/passwd
挂起/休眠guest-suspend-ram/disk/hybrid
获取内存块信息guest-get-memory-blocks

9.2 在 Linux 虚拟机中安装

Debian / Ubuntu

# 安装
sudo apt install qemu-guest-agent

# 启动并启用
sudo systemctl enable --now qemu-guest-agent

# 查看状态
sudo systemctl status qemu-guest-agent

Fedora / CentOS / RHEL

# 安装
sudo dnf install qemu-guest-agent

# 启动并启用
sudo systemctl enable --now qemu-guest-agent

Arch Linux

# 安装
sudo pacman -S qemu-guest-agent

# 启动
sudo systemctl enable --now qemu-guest-agent

cloud-init 自动安装

# user-data
#cloud-config
packages:
  - qemu-guest-agent
runcmd:
  - systemctl enable qemu-guest-agent
  - systemctl start qemu-guest-agent

9.3 在 Windows 虚拟机中安装

下载 virtio-win 驱动

# 在宿主机下载 virtio-win ISO
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso

# 在虚拟机中挂载
# 如果是 libvirt 管理的虚拟机
virsh attach-disk windows-vm /path/to/virtio-win.iso hdc --type cdrom --mode readonly

Windows 中安装

  1. 打开虚拟机的光驱,找到 guest-agent/qemu-ga-x86_64.msi
  2. 双击运行安装
  3. 安装完成后,服务 QEMU Guest Agent 会自动启动
# PowerShell 中检查服务状态
Get-Service QEMU-GA

# 如果服务未启动
Start-Service QEMU-GA
Set-Service QEMU-GA -StartupType Automatic

9.4 QEMU 配置 Guest Agent 通道

使用命令行

qemu-system-x86_64 \
  -enable-kvm -cpu host -m 4G \
  -drive file=vm.qcow2,format=qcow2 \
  -chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \
  -device virtio-serial \
  -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0

使用 libvirt XML

<domain type='kvm'>
  ...
  <devices>
    <!-- virtio 串口设备 -->
    <controller type='virtio-serial' index='0'/>
    
    <!-- Guest Agent 通道 -->
    <channel type='unix'>
      <source mode='bind' path='/var/lib/libvirt/qemu/ubuntu-vm.agent'/>
      <target type='virtio' name='org.qemu.guest_agent.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
  </devices>
</domain>
# 更新虚拟机配置
virsh define ubuntu-vm.xml
virsh shutdown ubuntu-vm
virsh start ubuntu-vm

9.5 通过 QMP 使用 Guest Agent

基本交互

# 连接到 QMP socket
# 方式 1: 使用 socat
echo '{"execute":"qmp_capabilities"}' | socat - UNIX-CONNECT:/var/lib/libvirt/qemu/ubuntu-vm.monitor

# 方式 2: 使用 virsh qemu-agent-command
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-info"}'

常用命令

# 获取客户机信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-info"}'

# 获取主机名
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-host-name"}'

# 获取操作系统信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-osinfo"}'

# 获取网络接口信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-network-get-interfaces"}'

# 获取时间
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-time"}'

# 设置时间(同步到宿主机时钟)
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-set-time"}'

# 获取文件系统信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-fsinfo"}'

9.6 文件系统冻结(fsfreeze)

冻结与解冻

# 冻结文件系统(确保快照一致性)
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-fsfreeze-freeze"}'

# 查看冻结状态
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-fsfreeze-status"}'

# 解冻文件系统
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-fsfreeze-thaw"}'

快照前自动冻结

#!/bin/bash
# snapshot-with-freeze.sh

VM_NAME="ubuntu-vm"
SNAP_NAME="consistent-snap-$(date +%Y%m%d)"

# 1. 冻结文件系统
echo "冻结文件系统..."
virsh qemu-agent-command ${VM_NAME} '{"execute":"guest-fsfreeze-freeze"}' --timeout 30

# 2. 创建快照
echo "创建快照..."
virsh snapshot-create-as ${VM_NAME} ${SNAP_NAME} --atomic

# 3. 解冻文件系统
echo "解冻文件系统..."
virsh qemu-agent-command ${VM_NAME} '{"execute":"guest-fsfreeze-thaw"}' --timeout 30

echo "一致性快照创建完成: ${SNAP_NAME}"

9.7 远程命令执行

在虚拟机中执行命令

# 执行命令(异步)
result=$(virsh qemu-agent-command ubuntu-vm \
  '{"execute":"guest-exec","arguments":{"path":"/bin/hostname","arg":[],"capture-output":true}}')

# 获取进程 PID
pid=$(echo $result | jq -r '.return.pid')

# 获取执行结果
virsh qemu-agent-command ubuntu-vm \
  "{\"execute\":\"guest-exec-status\",\"arguments\":{\"pid\":${pid}}}"

实用命令示例

# 获取磁盘使用情况
virsh qemu-agent-command ubuntu-vm \
  '{"execute":"guest-exec","arguments":{"path":"/bin/df","arg":["-h"],"capture-output":true}}'

# 获取系统负载
virsh qemu-agent-command ubuntu-vm \
  '{"execute":"guest-exec","arguments":{"path":"/usr/bin/uptime","capture-output":true}}'

# 获取进程列表
virsh qemu-agent-command ubuntu-vm \
  '{"execute":"guest-exec","arguments":{"path":"/bin/ps","arg":["aux"],"capture-output":true}}'

# 更新系统(谨慎使用)
virsh qemu-agent-command ubuntu-vm \
  '{"execute":"guest-exec","arguments":{"path":"/usr/bin/apt","arg":["update"],"capture-output":true}}'

9.8 文件操作

读取文件

# 打开文件
result=$(virsh qemu-agent-command ubuntu-vm \
  '{"execute":"guest-file-open","arguments":{"path":"/etc/hostname","mode":"r"}}')
fd=$(echo $result | jq -r '.return')

# 读取内容
virsh qemu-agent-command ubuntu-vm \
  "{\"execute\":\"guest-file-read\",\"arguments\":{\"handle\":${fd},\"count\":1024}}"

# 关闭文件
virsh qemu-agent-command ubuntu-vm \
  "{\"execute\":\"guest-file-close\",\"arguments\":{\"handle\":${fd}}}"

写入文件

# 打开文件(写入模式)
result=$(virsh qemu-agent-command ubuntu-vm \
  '{"execute":"guest-file-open","arguments":{"path":"/tmp/test.txt","mode":"w+"}}')
fd=$(echo $result | jq -r '.return')

# 写入内容(base64 编码)
content=$(echo -n "Hello from host" | base64)
virsh qemu-agent-command ubuntu-vm \
  "{\"execute\":\"guest-file-write\",\"arguments\":{\"handle\":${fd},\"buf-b64\":\"${content}\"}}"

# 关闭文件
virsh qemu-agent-command ubuntu-vm \
  "{\"execute\":\"guest-file-close\",\"arguments\":{\"handle\":${fd}}}"

9.9 VSS(Volume Shadow Copy Service)- Windows

Windows 虚拟机使用 VSS 实现文件系统冻结的一致性:

VSS 工作原理

Windows VSS 冻结流程:
  1. qemu-ga 发送冻结请求
  2. VSS 通知所有 VSS Writer 应用程序
  3. 应用程序完成内存数据刷盘
  4. VSS 创建卷影副本
  5. qemu-ga 返回冻结成功
  6. 宿主机创建快照
  7. qemu-ga 发送解冻请求
  8. VSS 释放卷影副本

验证 VSS 支持

# 在 Windows 虚拟机中
vssadmin list writers

9.10 自动化运维脚本

批量管理脚本

#!/bin/bash
# qga-batch-ops.sh - 批量通过 Guest Agent 管理虚拟机

VM_LIST="vm1 vm2 vm3 vm4"
COMMAND="$1"

for VM in ${VM_LIST}; do
    echo "=== ${VM} ==="
    
    case "${COMMAND}" in
        info)
            virsh qemu-agent-command ${VM} '{"execute":"guest-get-host-name"}' 2>/dev/null
            ;;
        network)
            virsh qemu-agent-command ${VM} '{"execute":"guest-network-get-interfaces"}' 2>/dev/null
            ;;
        update)
            virsh qemu-agent-command ${VM} \
              '{"execute":"guest-exec","arguments":{"path":"/usr/bin/apt","arg":["update"],"capture-output":true}}' 2>/dev/null
            ;;
        reboot)
            virsh qemu-agent-command ${VM} \
              '{"execute":"guest-exec","arguments":{"path":"/sbin/reboot","arg":[]}}' 2>/dev/null
            ;;
        *)
            echo "用法: $0 {info|network|update|reboot}"
            exit 1
            ;;
    esac
    
    echo ""
done

9.11 故障排查

问题原因解决方案
Agent 无响应服务未启动检查 systemctl status qemu-guest-agent
通道未建立XML 中未配置 channel添加 virtio-serial 和 channel 定义
命令超时虚拟机负载过高增加 –timeout 参数
冻结失败文件系统正在使用确认没有大文件写入操作
Windows 安装失败virtio 驱动版本不匹配使用与 QEMU 版本匹配的 virtio-win
# 检查通道是否建立
virsh domiflist ubuntu-vm
virsh dumpxml ubuntu-vm | grep -A5 channel

# 测试 Agent 通信
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-ping"}'

# 查看 Agent 日志
# Linux
journalctl -u qemu-guest-agent

要点回顾

要点核心内容
Guest Agent宿主机通过 virtio 串口与虚拟机内部通信
fsfreeze冻结文件系统确保快照一致性
guest-exec在虚拟机内远程执行命令
文件操作可以读写虚拟机内的文件
VSSWindows 使用 VSS 实现一致性快照

注意事项

安全风险: guest-exec 允许在虚拟机内执行任意命令,应限制 QMP socket 的访问权限。

Agent 版本: Guest Agent 版本应与 QEMU 版本匹配,否则可能出现命令不支持的问题。

通道名称: Guest Agent 通道名称必须是 org.qemu.guest_agent.0,否则无法正常工作。


扩展阅读


下一步

10 - 设备直通:学习 VFIO、PCI/GPU/NVMe/USB 设备直通配置。