# Libvirt (简体中文)

Related articles

- QEMU
- KVM
- VirtualBox
- Xen
- VMware

翻译状态： 本文是英文页面 Libvirt 的翻译，最后翻译时间：2014-06-07，点击这里可以查看翻译后英文页面的改动。

libvirt 是一个虚拟化 API 和虚拟机(VMs)管理后台，支持远程或本地访问，支持多种虚拟化后端 (QEMU/KVM， VirtualBox， Xen，等等) 。本文并不打算涉及有关 libvirt 的方方面面，仅讨论那些与通常的认知不同的地方或文档论述不详之处。

## 安装

服务器端需要从 官方仓库 同时安装下列包，它们组合起来共同作为虚拟化后端：

- libvirt
- virt-manager (一个图形界面程序，用于安装和管理虚拟机)
- bridge-utils 或 dnsmasq (用于网络共享)

客户端需要安装下列包：

- virt-manager
- virtviewer

注意: 服务器和客户端可以是同一台物理机器

### 为 Xen 构建 libvirt

目前，AUR中的libvirt-git 和 官方仓库中的 libvirt 二者的 PKGBUILD 均在 make 过程中通过 `--without-xen` 标记禁用了对 Xen 的支持。如果你需要用 libvirt 管理 Xen， 你需要 获取完整的文件集 以提供对 Xen 的支持，并且需要用ABS(即 Arch Build System，Arch 构建系统)构建你自己的 libvirt。AUR中的xen软件包要求 libvirt 构建时带有对 Xen 的支持。 The alternative XenAPI driver is lacking a package at the moment? (2010-05-23, friesoft)

## 配置

Libvirt 不是“开箱即用”的。你至少需要运行后台进程并且配置认证策略或者配置Unix 文件权限。同样也需要为 QEMU 打开 KVM 加速.

### 运行后台进程

在 `/etc/libvirt/qemu.conf`中修改默认的用户和用户组。 QEMU 默认是 nobody:nobody。

用 Systemd打开和启动 `libvirtd.service`

注意: Avahi 后台进程用于通过 DNS组播发现本地 libvirt 主机。可以在`/etc/libvirt/libvirtd.conf`中设置`mdns_adv = 0` 禁用此功能。

### 认证策略

创建下列文件，使libvirt用户组里面的非root用户可以管理虚拟机：

    /etc/polkit-1/rules.d/50-org.libvirt.unix.manage.rules

    polkit.addRule(function(action, subject) {
        if (action.id == "org.libvirt.unix.manage" &&
            subject.isInGroup("libvirt")) {
                return polkit.Result.YES;
        }
    });

或者，用下列语句授予非root用户仅查看虚拟机的权限

`org.libvirt.unix.monitor`。

更多信息请参阅：libvirt 的 wiki 站点。

### Unix 文件权限

注意: 这是#认证策略的替代方案

如果希望通过配置 Unix 文件权限的方式允许某些非 root 用户使用 libvirt，需按下列步骤设置：

首先，创建libvirt 用户组并将需授权访问 libvirt 的用户加入该组：

    # groupadd libvirt
    # gpasswd -a user libvirt

如果被加入的用户当前已登录，则需要注销后重新登录。或者，该用户也可以执行下列命令更新所属组：

    $ newgrp libvirt

将`/etc/libvirt/libvirtd.conf`文件中下列行的注释符（#号）删除（这些行可能位于文件中不同位置）：

    /etc/libvirt/libvirtd.conf

     #unix_sock_group = "libvirt"
     #unix_sock_ro_perms = "0777"
     #unix_sock_rw_perms = "0770"
     #auth_unix_ro = "none"
     #auth_unix_rw = "none"

注意: 还应当将 `unix_sock_ro_perms` 参数的值由 `0777` 改为 `0770` ，目的是取消非 libvirt 组的其他用户的只读访问权限

### 为 QEMU 打开 KVM 加速

注意: KVM 与 VirtualBox 有冲突，二者不能同时使用。

以惯常方式（不带 KVM 支持）运行 QEMU 模拟器会变态地慢！如果 CPU 支持，你一定要打开 KVM 支持。执行下列命令查看 CPU 是否支持 KVM：

    egrep --color "vmx|svm" /proc/cpuinfo

如果上述命令有输出结果返回，则说明 CPU 支持 KVM 硬件加速。如果没有返回任何信息，则无法使用 KVM

KVM 无效时，可在 `/var/log/libvirt/qemu/VIRTNAME.log` 这个文件中读到下列信息：

    /var/log/libvirt/qemu/VIRTNAME.log

    Could not initialize KVM, will disable KVM support

KVM 官方 FAQ中包含更多相关信息

### 宿主机关机/启动时停止/恢复客户机

Systemd 的 `libvirt-guests.service` 这个服务程序可以支持在宿主机关机时自动地挂起或关闭客户机。同样也支持宿主机开机时自动恢复或启动客户机。

请查阅 `/etc/conf.d/libvirtd-guests` 中的 libvirt-guests 相关选项。

### 引导时启动 KVM 虚拟机

如果用 virt-manager 和 virsh 作为虚拟机管理工具，则很简单即可实现。

开机自动启动的命令：

    $ virsh autostart <domain>

禁用开机自动启动的命令：

    $ virsh autostart --disable <domain>

virt-manager 中，在引导 选项页下同样也有个自动启动勾选项。

注意: 以命令行方式通过 QEMU 或 KVM 启动的虚拟机不能通过 virt-manager 管理

## 使用

### 创建一个新虚拟机

创建新虚拟机需要准备安装介质，通常是一个标准的`.iso`文件。将其复制到`/var/lib/libvirt/images/` 目录即可（或者在 virt-manager 中新建一个 存储池 目录，将其复制到该目录）。

注意: SELinux要求虚拟机默认存储在`/var/lib/libvirt/images/`目录。如果启用了 SELinux并且 are having issues with virtual machines，需确保虚拟机位于该目录或确保添加了指向非默认目录的正确标签（译注：本段译文需斟酌）

然后运行`virt-manager`连接到服务器，右击连接、选择新建。 输入自定义的连接名，选择 本地安装介质，按照向导继续。

在第四步中，应当取消 分配全部磁盘空间 选项。当虚拟机并不需要使用全部磁盘时，这样做可以节约空间，但也会导致磁盘碎片增多。此时，应密切关注宿主机的剩余磁盘空间总量，否则很容易导致为虚拟机分配了过量磁盘空间。

在第五步中，打开 高级选项 并确认 虚拟类型 选择了 kvm。如果该选项无效，查阅前文 为 QEMU 打开 KVM 加速 一节

### 在virt-manager中创建存储池

首先连接到一个现有的服务器。连接后，右击详情，进入存储，点击左下方的+图标，然后按向导指示继续。

### 用virt-manager管理VirtualBox

注意: Libvirt对VirtualBox的支持尚不完备，有可能导致 libvirtd 进程崩溃。但通常这并不会导致灾难，重启进程即可恢复

virt-manager 不允许从图形用户界面程序连接 VirtualBox。但可以从命令行加载：

    virt-manager -c vbox:///system

或者通过 SSH 管理远程系统：

    virt-manager -c vbox+ssh://username@host/system

### 在线快照

Libvirt 可以在无需关闭虚拟机的情况下抓取虚拟机快照，这个功能称为外部快照(external snapshotting)。 当前该功能仅支持基于 qcow2 和 raw 文件的虚拟机镜像。

一旦快照创建完毕，KVM 将新建一个仅包含快照内容的块设备挂载到虚拟机，新产生的数据将直接写入这个新的磁盘，原始磁盘镜像将被置为离线，以便复制或备份。以后还可以重新将含快照的镜像与原始镜像融合而无需关闭虚拟机。（本段译文存疑-Aaron Chen）

以下演示其工作原理：

当前运行中的虚拟机：

    # virsh list --all

     Id    Name                           State
     ----------------------------------------------------
     3     archey                            running

查看虚拟机的全部镜像文件：

    # virsh domblklist archey

     Target     Source
     ------------------------------------------------
     vda        /vms/archey.img

注意看镜像文件的属性

    # qemu-img info /vms/archey.img

     image: /vms/archey.img
     file format: qcow2
     virtual size: 50G (53687091200 bytes)
     disk size: 2.1G
     cluster_size: 65536

创建一个 disk-only 类型的快照。开关参数`--atomic`将确保万一快照创建失败时虚拟机不被篡改

    # virsh snapshot-create-as archey snapshot1 --disk-only --atomic

查看快照清单：

    # virsh snapshot-list archey

     Name                 Creation Time             State
     ------------------------------------------------------------
     snapshot1           2012-10-21 17:12:57 -0700 disk-snapshot

virsh 创建了一个新的镜像文件。注意观察它的属性：只有几 MB 大小，并且链接到其原始的“后备镜像/链”

    # qemu-img info /vms/archey.snapshot1

     image: /vms/archey.snapshot1
     file format: qcow2
     virtual size: 50G (53687091200 bytes)
     disk size: 18M
     cluster_size: 65536
     backing file: /vms/archey.img

在这里，可以回过头来复制原始镜像（通过`cp -sparse=true`或`rsync -S`参数），然后就可以将原始镜像融合进快照。

    # virsh blockpull --domain archey --path /vms/archey.snapshot1

现在，数据块被从原始镜像中抽离出来，`/vms/archey.snapshot1` 这个文件成为新的虚拟机磁盘的镜像文件。查看其磁盘容量就知道。这些都完成后，原始磁盘镜像`/vms/archey.img` 以及快照元数据就可以安全地删除了。

`virsh blockcommit`是`blockpull`的反向操作，不过似乎在当前的 qemu-kvm 1.3 版中（连同快照恢复(snapshot-revert)）功能都还处于开发阶段，按开发日程安排是在明年发布。

对于需要频繁在线备份的需求者来说，KVM的这一新功能十分便利而又不必冒文件系统损坏的风险。

## 远程访问libvirt

### 使用未加密的 TCP/IP socket (最简单，最不安全)

警告: 这一操作仅可应用于安全、私密、可信的网络环境

编辑`/etc/libvirt/libvirtd.conf`：

    /etc/libvirt/libvirtd.conf

    listen_tls = 0
    listen_tcp = 1
    auth_tcp=none

警告: 这里的设置没有打开 SASL，因而所有的 TCP 传输都是明文传输！在真实的应用环境中，一定要始终打开 SASL。

另外还要编辑`/etc/conf.d/libvirtd`，以监听模式启动libvirtd服务

    /etc/conf.d/libvirtd

    LIBVIRTD_ARGS="--listen"

### 使用 SSH

通过SSH远程管理，需要openbsd-netcat软件包。

用`virsh`连接到远程系统：

    $ virsh -c qemu+ssh://username@host/IP address/system

如果出错了，可以如下方式获取日志：

    $ LIBVIRT_DEBUG=1 virsh -c qemu+ssh://username@host/IP address/system

显示图形界面虚拟机控制台：

    $ virt-viewer --connect qemu+ssh://username@host/IP address/system myvirtualmachine

显示虚拟机桌面管理工具：

    $ virt-manager -c qemu+ssh://username@host/IP address/system

注意: 如果连接到远程的 RHEL （或者其他非 Arch 系统）服务器有问题，参阅FS#30748以及FS#22068。

### 使用 Python

libvirt-python软件包中的`/usr/lib/python2.7/site-packages/libvirt.py`提供了python2 的 API。

`/usr/share/doc/libvirt-python-your_libvirt_version/examples/`中给出了若干通用范例。

使用qemu 和 openssh 的非官方范例：

    #! /usr/bin/env python2
    # -*- coding: utf-8 -*-
    import socket
    import sys
    import libvirt
    if (__name__ == "__main__"):
       conn = libvirt.open("qemu+ssh://xxx/system")
       print "Trying to find node on xxx"
       domains = conn.listDomainsID()
       for domainID in domains:
           domConnect = conn.lookupByID(domainID)
           if domConnect.name() == 'xxx-node':
               print "Found shared node on xxx with ID " + str(domainID)
               domServ = domConnect
               break

## 桥接网络

如果要在虚拟机中使用宿主机的物理网卡，需要在物理网卡（此处为eth0）和虚拟机的虚拟网卡之间创建网桥。

### 宿主机配置

由于 libvirt 会创建一个名为virbr0的 NAT 网络，所以应该使用其他的名字比如br0或者virbr1创建网桥。 应当创建一个 Netctl 或 Systemd-networkd 的配置文件配置新创建的网桥，例如(使用 DHCP 的配置)：

    /etc/netctl/br0

    Description="Bridge connection for kvm"
    Interface=br0
    Connection=bridge
    BindsToInterfaces=(eno1)
    IP=dhcp

小贴士: 建议在新建的虚拟网桥（例如br0）配置中打开生成树(STP-Spanning Tree Protocol)功能，以避免产生潜在的桥接环路。You can automatically enable STP by appending `POST_UP="brctl stp $INTERFACE on"` to the netcfg profile.

### 客户机配置

现在可以在虚拟机中激活桥接网卡了。

如果还有其它的 Linux 虚拟机要使用这个桥接网卡，可以把下面这段代码复制到该虚拟机的.xml配置文件中：

     [...]
     <interface type='bridge'>
       <source bridge='br0'/>
       <mac address='24:42:53:21:52:49'/>
       <model type='virtio' />
     </interface>
     [...]

这段代码在虚拟机中激活了一个virtio设备，因而在Windows虚拟机中需要为它安装额外的驱动程序(位于Windows KVM VirtIO drivers)或者移去`<model type='virtio' />`这行：

     [...]
     <interface type='bridge'>
       <source bridge='br0'/>
       <mac address='24:42:53:21:52:49'/>
     </interface>
     [...]

## 参阅

- libvirt 网站

Categories:

- 简体中文
- Virtualization (简体中文)