[issue翻译]提议:为CNI支持虚拟机监控程序容器运行时

URL: https://github.com/containernetworking/cni/issues/251

feiskyer
Overview
CNI旨在为Linux上的应用程序容器提供基于通用插件的联网解决方案。今天有许多容器运行时实现。为了将容器网络与主机隔离,其中一些基于Linux网络 命名空间(例如docker,没有lkvm的rkt),而其他的则基于管理程序(例如rkt带有lkvmHyperContainer)。 当前的CNI设计已经支持基于网络名称空间的运行时,但不支持虚拟机管理程序。因此,该提案旨在为CNI添加虚拟机监控程序运行时支持。 当前的CNI设计已经支持基于网络命名空间的运行时,但不支持虚拟机管理程序。因此,该提案旨在为CNI添加虚拟机监控程序运行时支持。
Considerations
网络上的hypervisor和linux网络名称空间之间有很多区别:
- 虚拟机监控程序具有自己的网络栈,无需为虚拟机监控程序创建网络名称空间。相反,CNI应该为管理程序创建一个Tap设备。
- 由于网络是在系统管理程序内部配置的,因此CNI网络插件无法直接在外部配置IP地址。相反,CNI应该准备网络设备(例如,创建网桥并连接tap设备),然后将网络信息(包括设备,IP地址,网关,路由等)传递回运行时,并让运行时完成剩余工作配置工作。
Design
- 为了支持基于管理程序的运行时,应在CNI中进行一些更改:
- 让CNI知道运行时类型( hypervisor 或netns) 为基于 hypervisor 的运行时配置tap设备而非veth对
- 将网络信息传递回运行时

1) 知道运行时类型
在RuntimeConf中添加一个新字段UsesTapDevice, 例如:

type RuntimeConf struct {
    // The ID of the container
    ContainerID string
    // If set, a tap device instead of veth pair should be created
    UsesTapDevice bool
    // The network namespace path. 
    // Optional. Only need if IsHypervisor is not set.
    NetNS       string
    // Name of the interface inside the container. 
    IfName      string
    // Extra arguments
    Args        [][2]string
}

2) 配置tap设备,而不是veth对
这将是网络插件的工作。由于没有网络名称空间,因此网络插件应直接在主机上创建Tap设备。现有插件将被重构以创建用于虚拟机管理程序运行时的tap设备。
网络配置和IPAM可以保持不变,因此可以像以前一样分配容器的IP地址。

3) 将网络信息传递回运行时
Dan已经从#145开始了

feiskyer:CNI不在乎虚拟机监控程序的实现细节,它只是知道运行时基于虚拟机监控程序,并且希望使用Tap设备而不是veth对。容器运行时应将此Tap设备连接到虚拟机监控程序。

lukasredynk :我研究了 #145 ,它在接口更改方面显得更改量很大,添加像“ CNI_VIRT”这样的env并返回tap索引还不够吗?

feiskyer :添加环境可能有效,但不是那么明确。当前所有的cni插件都应该是基于netns的,它需要知道运行时明确是虚拟机管理程序。
仅返回tap索引是不够的,因为我们不希望每个插件都直接与hypervisor交互。取而代之的是,cni将创建的tap设备和相关的IP地址/掩码/网关/dns返回到运行时,并让运行时本身将其配置到虚拟机监控程序中。

lukasredynk : 抱歉,我不确切,是的,我同意。
我正在考虑的方案:

  1. Set CNI_VIRT (optional)
  2. Run plugin (from plugins/main)
  3. Plugin checks if CNI_VIRT set
    • CNI_VIRT not set: no changes in flow
    • CNI_VIRT set: creates tap instead of veth
  4. Plugin executes IPAM plugin (and passes CNI_VIRT if set)
    • CNI_VIRT not set: no changes in flow
    • CNI_VIRT set: only reserves IP and returns information about how to configure iface in VM
  5. Top-most plugin returns:
    • CNI_VIRT not set: no changes in flow
    • CNI_VIRT set: to the usual output would be added additional param "Iface *uint" in types.IPConfig

feiskyer: 确实需要一个新的环境变量(例如CNI_VIRT),但是仅此一个环境变量是不够的:
- 许多外部cni插件都在使用libcni,这当然需要知道运行时是否基于管理程序
- invoke.Args和CmdArgs还需要知道运行时是否基于虚拟机管理程序
顺便说一句,我对IsHypervisor bool不满意,您对此有何建议?也许 Virtualized bool?例如

type RuntimeConf struct {
    // If set, the runtime is based on hypervisor
    Virtualized bool
    ....
}

lukasredynk:我已经开始着手研究可以显示的代码,以进一步推动讨论,但是现在,我已经在pkg / skel / skel.go“ CNI_VIRT”中添加了放入CmdArgs的环境变量列表。 首先,我正在考虑提供ptp和bridge插件的基本实现,但我仍在努力,看来netlink库版本应该受到影响,因为所使用的版本不支持创建tun / tap设备。 感谢您指出invoke.Args,我完全错过了它,我本以为在pkg / skel / skel.go中添加文件就足够了。
关于IsHypervisor bool:也许TunTap bool,默认为false?因为可能会出现这种情况,tap优先于veth,而不与虚拟机管理程序字段相关?

jellonek : 要使用tap设备,您不必使用虚拟化,因此应该使用UsesTapDevice 而不是Virtualized 。

feiskyer: 谢谢。已将提案更新为UsesTapDevice而不是IsHypervisor。

lukasredynk:非常早期且非常WIP的分支,它为ptp插件创建和配置Tap设备:https://github.com/lukasredynk/cni/pull/1/files,这里的大部分更改与更新netlink库有关(供应商的版本不能处理 Tap设备 )。

lukasredynk:我已经使用rkt-kvm进行了测试,并且至少在默认受限网络中有效。

lukasredynk: RFC:应该如何命名接口?我认为它应该与“ veth_”不同,不要混用不同的设备类型,也许是“ tap_”,其中“ *”后缀的生成方式与veth_型接口相同。你怎么看待这件事?

lukasredynk:我更新了PR: 将CNI_VIRT更改为CNI_USE_TAP ;向libcni添加了代码路径;重构tap创建。
唯一缺少的是在netlink存储库中合并挂起的PR。

thockin :我不确定,但是对我来说,这似乎是一个错误的转折。并非所有的CNI插件都将使用veth。感觉就像是在获取内部信息并将其放在外部。您现在使每个网络插件负责了解tap设备吗?
为什么不能在CNI插件中完全完成此操作?我们是否需要在CNI API中提供一些能力以为插件提供线索,我也许可以买单。但总的来说,这对我来说很困难。只是感觉不对。

feiskyer: 是的,该建议将使每个cni插件负责理解tap设备。这是有道理的,因为CNI是所有容器(包括基于管理程序的运行时)的所有容器的通用网络接口。
可以在CNI插件中完全完成此操作 ,但是该插件不再通用。通常,所有内置网络插件(不确定这是否正确,我的意思是这里的插件)应在所有支持CNI的运行时中正常工作。

thockin : 我认为这是一个非常可疑的起点。你不能合理地 希望所有容器供应商都支持这一点。
有人对网络有图表或详尽的解释吗 为虚拟化运行时设置?我想看一个例子 设备链接在一起,以及如何配置IP路由。

lukasredynk : 遵循@jellonek的建议,我已经准备了带有更新的netlink(包括我的更改)的PR(#274),合并之后,我将使用PTP插件对原始PR进行重新设置。

lukasredynk : @thockin CNI插件无法在VM内部设置网络,因为它始终在主机上运行。对于基于systemd-nspawn的容器来说,在主机生成之前先建立网络连接并不是问题,因为主机和容器共享内核空间,但是在VM的情况下,没有直接的方法来创建虚拟接口(它将如何连接到主机上的网络?) ,请通过syscall分配IP地址并设置路由(有效执行CNI的操作),因为在生成VM之前无法执行此操作。系统管理程序也无法将veth设备附加到VM(当前由ptp,bridge和flannel插件创建)。

lukasredynk : 您可以看一下rkt中的网络(在github.com/coreos/rkt/networking:networking.go和kvm.go中):当前实现对nspawn容器使用CNI,对于基于VM的容器,使用自定义路径(使用CNI代码库)设置tap,获取路由,获取IP并将此信息传递回虚拟机监控程序(tap设备名称, 通过cli )。还创建了systemd单元文件,VM的systemd使用该文件来设置所有网络。实际上,所有插件均能通过这种“野路子”支持,但是会a)部分复制了CNI功能 b)使其难以维护。
集装箱供应商对此有何担忧?选择加入创建tap。在将特定的可选标志传递给CNI之前,它们将像以前一样工作。实际上,对于希望通过CNI处理网络配置并且还需要针对特定​​情况需要基于tap的网络的项目而言,这是很大的收获。

jellonek: 老实说-并非所有插件(ipvlan 不支持)。将这些代码从rkt移到cni 仍然可以解决很多问题-首先消除了提到项目上的代码重复,其次-为其他基于VM的运行时(例如HyperKube或vocker)提供了相同的功能。 而且,这还提供了在容器启动之前配置网络,并在结束后在其他网络上重用它的可能性。

thockin:明确地说-我理解为什么这对于超虚拟化运行时更好。我比较关注的是API的丑陋性以及现有驱动程序的想法:应该实现两种模式。只是感觉不对。
如果我有一个可以处理OVS的CNI插件-我可以将Tap设备链接到我的 OVS 设备中吗 ?
我可以在Calico上使用tap设备吗? Weave ? Contiv 呢?
为什么这比一组明确支持"仅tap设备"的新CNI插件更好 ?是“需要开放的FD”问题吗?

feiskyer : @thockin创建水龙头已启用。现有的驱动程序可以像今天一样选择仅支持基于netns的容器。你能解释为什么它很丑吗?
当然可以支持OVS 。只需稍作改动即可:连接到容器时,创建分接设备而不是veth对。
如果Calico / Weave / Contiv添加了对tap设备的支持,则也是如此。

feiskyer:
1) 减少代码重复 :
- 一个二进制和代码库都可以
- 网络插件可以执行许多步骤来设置网络,例如分配IP地址,创建网桥,设置iptables规则,设置隧道,将网桥连接到容器(通过veth对或Tap设备)。只有最后一步是不同的。两者的所有其他步骤完全相同。
2) 扩展CNI的范围,因此它可以支持所有类型的运行时,无论是netns还是hypervisor。 (否则,我们可能需要另一个专用于Tap设备的CNI)
3) 切换运行时时具有一致的用户体验,因此用户无需重写新插件即可与现有网络基础架构集成。

lukasredynk: 并且只有以下插件是受此变更集影响 :

  • ptp
  • bridge
  • macvlan
  • flannel (because internally wraps bridge plugin)

一些来自主要的CNI存储库。如果外部插件希望支持创建tap,则可以,但这不是强制性的。 AFAIK Calico仅使用ipam进行IP管理(单独管理veth),我不确定Weave,但快速浏览他们的文档后,情况似乎是这样。

thockin :您正在详细说明:
网络设备的特定类型并且使其成为API的一部分。一旦支持,就没有根据了 拒绝下一个不同的想法,而您的APi变成 混乱的条件和可选的if字段。有优雅和 简单到不透明。这感觉不是最简单的 可能的解决方案。
我们可以做一些管理程序存在于网络中的事情吗? 主机os)和net插件在所有情况下都是相同的,并委托 虚拟机管理程序的复杂性仅在管理程序中出现?
MacVLAN? IPVLAN?我的意思是您已经强迫用户 考虑他们的插件是否支持特定的操作模式 。 为什么将其作为API的一部分。
我的观点是,tap是一种非常特殊的技术。立刻 更好的东西来了,此API就过时。可能是一样的 说到netns(实际上,libnetwork甚至不公开netns,如果我 回想一下),但那是一个较低的水平,因此对我来说风险较小。
但实际上他们确实有不同的插件。它可能会使用80% 相同的代码,但是其行为和执行方式有所不同,因此它 是不同的。

thockin : 用户也可以针对不同的运行时使用相同的配置。

rosenhouse : 不要堆得太多,但我还会问我们如何计划在CI系统中测试这种虚拟机监控程序支持? Travis允许我们创建netns并在这些netns中执行插件。是否可以使用CI环境来行使管理程序代码路径?

squeed : 与其让“ ADD”命令具有两种相当不同的语义,不如在规范中添加一个附加命令?诸如“ CONFIGURE”之类的东西,它通过一个已经初始化的接口(例如,由管理程序创建tap)来由CNI插件配置?

jellonek:这将要求管理程序在调用CNI插件之前运行(这与kvm风格的rkt的当前实现的方式非常相似)。 使用当前的建议(以及  #271 中的初始实现),您可以从kubernetes网络准备过程中运行,然后将结果传递给任何基于虚拟机监控程序的运行时(这可能是kvm风格的rkt,hyperd或其他我现在正在工作的东西; ))。
仍然有可能通过网络设备(可以准备veth / tap / macv(lan | tap))作为附加的CNI“主”插件似乎很容易实现。现有的插件也可以重用它,就像它们已经在调用IPAM插件一样。
这样,我们将拥有像这样的链:
- 准备接口(可以通过插件或外部事物完成),该接口调用:
- 在调用特定设备的设备上分配ipv4 / ipv6所需的配置(地址/路由/ iptables) ,该接口调用:
- IPAM
实际上,前两个步骤在主要插件中组合在一起。 如果有人对此感兴趣-我们可以讨论这个问题,但是我看来在另外一个问题上。

翻译声明:并不保证翻译的质量,只是看都看了,顺便把零散的片段整理起来,也能够帮助同样需要的人罢了。

使用云镜像在KVM上创建一个Linux实验环境

参考自: http://giovannitorres.me/create-a-linux-lab-on-kvm-using-cloud-images.html 真可惜,发现是基于CentOS,可我的开发换是Ubuntu。其中的cloud-localds 命令找不到。

发现一个找命令的工具网站 https://command-not-found.com/cloud-localds ,安装 cloud-image-utils。

找到一个cloud-init,这应该是配套云镜像使用:

Ubuntu找到几个有意思的包:有图形化管理qemu的和使用云镜像的,有空试玩

uvtool/xenial,xenial 0~bzr99-0ubuntu1 all
  Library and tools for using Ubuntu Cloud images

uvtool-libvirt/xenial,xenial 0~bzr99-0ubuntu1 all
  Library and tools for using Ubuntu Cloud Images with libvirt

qtemu/xenial 2.0~alpha1-1ubuntu6 amd64
  graphical user interface for QEMU

ubuntu-virt-mgmt/xenial,xenial 1.4 all
  Common packages useful for managing virtual machines graphically

之前参考的文章,脚本更新了,在 https://github.com/giovtorres/kvm-install-vm。Bash包装了virt-install,仅在 Fedora 最新版上测试过。使用的 ssh-authorized-keys 登陆。这是方式一。


好了,正式开始。有一简短的教程可以参考,使用的指定password登陆。这是方式二,可能更方便些。就从这个入手了。

# Ubuntu 16.04
sudo apt install libvirt-dev libvirt0 libvirt-bin virt-top virt-manager virt-what virt-goodies genisoimage cloud-init cloud-image-utils libguestfs-tools qemu qemu-kvm
# reboot

cat > cloud-config <<EOF
#cloud-config
preserve_hostname: False
hostname: centos
fqdn: centos.example.local
password: 123456
chpasswd: { expire: False }
ssh_pwauth: True
runcmd:
  - [ yum, -y, remove, cloud-init ]
EOF

cloud-localds cloud-config.img cloud-config
mv cloud-config.img /var/lib/libvirt/images

# get the qcow2 images
wget http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2.xz #下载 img 文件
xz -d CentOS-7-x86_64-GenericCloud.qcow2.xz
cp CentOS-7-x86_64-GenericCloud.qcow2 centos.qcow2 #复制一份
# qemu-img resize centos.qcow2 +10G #增加磁盘大小
mv centos.qcow2 /var/lib/libvirt/images

#导入
virt-install --connect=qemu:///system \
 --name centos \
 --ram 2048 \
 --vcpus=2 \
 --os-type=linux \
 --os-variant=centos7.0 \
 --disk /var/lib/libvirt/images/centos.qcow2,device=disk,bus=virtio \
 --disk /var/lib/libvirt/images/cloud-config.img,device=cdrom \
 --graphics none \
 --import

导入后可使用用户名 centos 密码 123456 登陆

virt-install第一次安装时,硬件地址,获取IP是没有问题的。之后通过Libvirt启动该磁盘镜像时,会遇到dhclient没有运行,获取不到IPv4地址的问题,需要修改镜像中网卡的IP地址,使之与Libvirt分配的硬件地址匹配。

# 手动获取IP
/sbin/dhclient -1 -q -lf /var/lib/dhclient/dhclient--eth0.lease -pf /var/run/dhclient-eth0.pid -H centos eth0

(可选)在虚拟机中安装,之后开发要用,通过该软件来获取宿主机的IP。

sudo yum install qemu-guest-agent

qemu-guest-agent是一个助手守护进程,它安装在guest中。它用于在主机和客户端之间交换信息,并在客户端执行命令。 具体特性

基于QMP实现对qemu虚拟机进行交互,qemu命令参数支持2种方法配置qmp,即-qmp和-mon。Libvirt使用的-mon。

$ virsh qemu-monitor-command centos7.0 --pretty '{ "execute": "query-block" }'
{
    "return": [
        {
            "io-status": "ok",
            "device": "drive-virtio-disk0",
            "locked": false,
            "removable": false,
            "inserted": {
                "iops_rd": 0,
                "detect_zeroes": "off",
                "image": {
                    "virtual-size": 8589934592,
                    "filename": "/var/lib/libvirt/images/centos.qcow2",
                    "cluster-size": 65536,
                    "format": "qcow2",
                    "actual-size": 2079526912,
                    "format-specific": {
                        "type": "qcow2",
                        "data": {
                            "compat": "0.10",
                            "refcount-bits": 16
                        }
                    },
                    "dirty-flag": false
                },
                "iops_wr": 0,
                "ro": false,
                "node-name": "#block155",
                "backing_file_depth": 0,
                "drv": "qcow2",
                "iops": 0,
                "bps_wr": 0,
                "write_threshold": 0,
                "encrypted": false,
                "bps": 0,
                "bps_rd": 0,
                "cache": {
                    "no-flush": false,
                    "direct": false,
                    "writeback": true
                },
                "file": "/var/lib/libvirt/images/centos.qcow2",
                "encryption_key_missing": false
            },
            "type": "unknown"
        }
    ],
    "id": "libvirt-6114"
}

$ virsh qemu-monitor-command centos7.0 --hmp 'info block'
drive-virtio-disk0 (#block155): /var/lib/libvirt/images/centos.qcow2 (qcow2)
    Cache mode:       writeback

学习qmp的简单使用

以及, 使用QEMU客户代理查找客户IP地址

# 查看支持的操作
$ virsh qemu-agent-command centos7.0 --pretty '{ "execute": "guest-info" }'
{
    "return": {
        "version": "2.12.0",
        "supported_commands": [
            {
                "enabled": true,
                "name": "guest-get-osinfo",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-timezone",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-users",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-host-name",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-exec",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-exec-status",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-memory-block-info",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-set-memory-blocks",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-memory-blocks",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-set-user-password",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-fsinfo",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-set-vcpus",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-vcpus",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-network-get-interfaces",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-suspend-hybrid",
                "success-response": false
            },
            {
                "enabled": true,
                "name": "guest-suspend-ram",
                "success-response": false
            },
            {
                "enabled": true,
                "name": "guest-suspend-disk",
                "success-response": false
            },
            {
                "enabled": true,
                "name": "guest-fstrim",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-fsfreeze-thaw",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-fsfreeze-freeze-list",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-fsfreeze-freeze",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-fsfreeze-status",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-file-flush",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-file-seek",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-file-write",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-file-read",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-file-close",
                "success-response": true
            },
            {
                "enabled": false,
                "name": "guest-file-open",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-shutdown",
                "success-response": false
            },
            {
                "enabled": true,
                "name": "guest-info",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-set-time",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-get-time",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-ping",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-sync",
                "success-response": true
            },
            {
                "enabled": true,
                "name": "guest-sync-delimited",
                "success-response": true
            }
        ]
    }
}

$ virsh qemu-agent-command centos7.0 --pretty '{ "execute": "guest-network-get-interfaces" }'
{
    "return": [
        {
            "name": "lo",
            "ip-addresses": [
                {
                    "ip-address-type": "ipv4",
                    "ip-address": "127.0.0.1",
                    "prefix": 8
                },
                {
                    "ip-address-type": "ipv6",
                    "ip-address": "::1",
                    "prefix": 128
                }
            ],
            "statistics": {
                "tx-packets": 6,
                "tx-errs": 0,
                "rx-bytes": 416,
                "rx-dropped": 0,
                "rx-packets": 6,
                "rx-errs": 0,
                "tx-bytes": 416,
                "tx-dropped": 0
            },
            "hardware-address": "00:00:00:00:00:00"
        },
        {
            "name": "eth0",
            "ip-addresses": [
                {
                    "ip-address-type": "ipv4",
                    "ip-address": "192.168.122.58",
                    "prefix": 24
                },
                {
                    "ip-address-type": "ipv6",
                    "ip-address": "fe80::5054:ff:fe28:c078",
                    "prefix": 64
                }
            ],
            "statistics": {
                "tx-packets": 247,
                "tx-errs": 0,
                "rx-bytes": 100007,
                "rx-dropped": 12,
                "rx-packets": 1531,
                "rx-errs": 0,
                "tx-bytes": 19704,
                "tx-dropped": 0
            },
            "hardware-address": "52:54:00:28:c0:78"
        }
    ]
}

新建一个会话,弹出 cloud init 初始化镜像

$ virsh list
 Id    Name                           State
----------------------------------------------------
 4     centos                         running

$ virsh change-media centos hda --eject --config
Successfully ejected media.

退出时使用 Ctrl 键+ ] (左方括号)键退出

再次命令行界面登陆 virsh console

virsh start centos
virsh list #确保running
virsh console centos

关闭virsh shutdown

$ virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     centos                         shut off

之后立即禁止开机启动cloud-init,或者卸载。导致虚拟机开机启动贼慢。

$ ls /lib/systemd/system/cloud-*.service
/lib/systemd/system/cloud-config.service  /lib/systemd/system/cloud-init-local.service
/lib/systemd/system/cloud-final.service   /lib/systemd/system/cloud-init.service

$ systemctl disable cloud-config cloud-init-local cloud-final cloud-init
Removed symlink /etc/systemd/system/cloud-init.target.wants/cloud-config.service.
Removed symlink /etc/systemd/system/cloud-init.target.wants/cloud-init.service.
Removed symlink /etc/systemd/system/cloud-init.target.wants/cloud-init-local.service.
Removed symlink /etc/systemd/system/cloud-init.target.wants/cloud-final.service.

提供上述制作的镜像centos7.qcow2下载。

链接:https://pan.baidu.com/s/16PT60usy_HhxmtXD-FO-3A 
提取码:j8v1 
复制这段内容后打开百度网盘手机App,操作更方便哦

用virt-manager来启动,手动qemu启动,可能启动之后就找不到了

qemu-system-x86_64 -hda /var/lib/libvirt/images/centos7.qcow2 -enable-kvm  -vnc 0.0.0.0:0

推荐一本KVM入门书:《KVM Virtualization Cookbook》,网上有电子版


那如何在Windows上Libvirt呢? https://libvirt.org/windows.html

https://blog.csdn.net/weiyuanke/article/details/8020657


如何在Windows上使用qemu启动qcow2系统镜像?

https://www.xiexianbin.cn/windows/2017-02-16-use-qemu-start-qcow2-image-in-window/index.html

qemu-system-x86_64 -m 1024 -smp 1 -drive file="G:\VM\qemu\centos7.qcow2" -boot c -net nic -net tap,ifname=my-tap
Windows下启动的qemu虚拟机

一次永久解决cmd窗口汉字显示乱码:

  1. win+R 输入regedit 进入注册表
  2. 找到 HKEY_CURRENT_USER\Console\%SystemRoot%_system32_cmd.exe 如果 该项下已存在CodePage项,则把值改为十进制”65001”;如果不存在,在该项下新建一个 DWORD(32位值),命名为“CodePage”,值设为“65001”
  3. 重启cmd后生效
  4. 对于Power shell修改同样,只需在第2步修改
    %SystemRoot%_system32_WindowsPowerShell_v1.0_powershell.exe 下的项。

安装部署KVM虚拟机(四)

Libvirt提供了用户空间的命令行和编程语言绑定来管理虚拟机的build, configure, start, stop,migrate, terminate,etc.

OpenStack的组件中也做了集成。

https://blog.csdn.net/xxfigo/article/details/7590229

Nova是OpenStack云中的计算组织控制器。支持OpenStack云中实例(instances)生命周期的所有活动都由Nova处理。这样使得Nova成为一个负责管理计算资源、网络、认证、所需可扩展性的平台。但是,Nova自身并没有提供任何虚拟化能力,相反它使用libvirt API来与被支持的Hypervisors交互。

安装和配置libvirt

jahentao:qemu$ sudo apt install gir1.2-libvirt-glib-1.0 libvirt-bin libvirt-clients libvirt-daemon libvirt-daemon-system libvirt-dev libvirt-glib-1.0-0 libvirt0 python-libvirt virt-manager virt-top virt-viewer virtinst

查看libvirt的守护进程是否在执行

jahentao:qemu$  pgrep -lfa libvirtd
1895 /usr/sbin/libvirtd

修改配置/etc/libvirt/libvirtd.conf

查看配置

jahentao:~$ cat /etc/libvirt/libvirtd.conf | grep -vi "#" | sed '/^$/d'
listen_tls = 0
listen_tcp = 1
listen_addr = "127.0.0.1"
auth_tcp = "sasl"

Qemu默认用的Selinux策略

查看SELinux状态

/usr/sbin/sestatus -v

如果SELinux status参数为enabled即为开启状态,也可以用getenforce命令检查

我的机器上没有使用SeLinux。

警用QEMU的安全驱动,如果有selinux在运行。

jahentao:qemu$ sudo cat /etc/libvirt/qemu.conf | grep -vi '#' | sed '/^$/d'
security_driver = "none"

配置监听

jahentao:~$ sudo cat /etc/default/libvirtd | grep -vi '#' | sed '/^$/d'
start_libvirtd="yes"
libvirtd_opts=" --listen"

重启libvirt守护进程。

jahentao:~$ systemctl restart libvirtd
jahentao:~$ 

验证配置文件

jahentao:~$ ls -la /etc/libvirt/
总用量 140
drwxr-xr-x   8 root root  4096 3月   9 09:05 .
drwxr-xr-x 153 root root 12288 3月   9 09:00 ..
drwxr-xr-x   2 root root  4096 5月  16  2018 hooks
-rw-r--r--   1 root root   450 5月  16  2018 libvirt-admin.conf
-rw-r--r--   1 root root   642 2月  27 13:17 libvirt.conf
-rw-r--r--   1 root root   547 2月  21 19:00 libvirt.conf.bak
-rw-r--r--   1 root root 16047 2月  26 22:48 libvirtd.conf
-rw-r--r--   1 root root  2268 5月  16  2018 libxl.conf
-rw-r--r--   1 root root  2169 5月  16  2018 libxl-lockd.conf
drwxr-xr-x   2 root root  4096 3月   4 21:39 lxc
-rw-r--r--   1 root root  1175 5月  16  2018 lxc.conf
drwxr-xr-x   2 root root  4096 2月  21 17:29 nwfilter
-rw-r-----   1 root root 12288 2月  27 12:31 passwd.db
drwxr-xr-x   3 root root  4096 3月   6 19:17 qemu
-rw-------   1 root root 29195 3月   9 09:05 qemu.conf
-rw-r--r--   1 root root  2169 5月  16  2018 qemu-lockd.conf
-rw-r--r--   1 root root  2465 5月  16  2018 qemu-sanlock.conf
drwx------   2 root root  4096 2月  21 17:29 secrets
drwxr-xr-x   3 root root  4096 3月   4 21:22 storage
-rw-r--r--   1 root root  2003 5月  16  2018 virtlockd.conf
-rw-r--r--   1 root root  2101 5月  16  2018 virtlogd.conf
-rw-r--r--   1 root root  1883 5月  16  2018 virt-login-shell.conf
  • libvirt.conf是客户端的配置文件
  • libvirtd.conf是服务器端的配置文件
  • qemu.conf是libvirt使用QEMU的配置文件
  • QEMU/KVM虚拟机一经创建 /etc/libvirt/qemu/目录下就会出现定义相应实例的XML配置文件,/etc/libvirt/qemu/networks/包含网络配置

还有其他配置文件位置

jahentao:~$ sudo !!
sudo tree /var/lib/libvirt/
/var/lib/libvirt/
├── boot
├── dnsmasq
│   ├── default.addnhosts
│   ├── default.conf
│   ├── default.hostsfile
│   ├── virbr0.macs
│   └── virbr0.status
├── images
├── qemu
│   ├── channel
│   │   └── target
│   ├── dump
│   ├── nvram
│   ├── ram
│   │   └── libvirt
│   │       └── qemu
│   ├── save
│   └── snapshot
└── sanlock
/usr/lib/libvirt
├── connection-driver
│   ├── libvirt_driver_interface.so
│   ├── libvirt_driver_libxl.so
│   ├── libvirt_driver_lxc.so
│   ├── libvirt_driver_network.so
│   ├── libvirt_driver_nodedev.so
│   ├── libvirt_driver_nwfilter.so
│   ├── libvirt_driver_qemu.so
│   ├── libvirt_driver_secret.so
│   ├── libvirt_driver_storage.so
│   ├── libvirt_driver_uml.so
│   └── libvirt_driver_vbox.so
├── libvirt-guests.sh
├── libvirt_iohelper
├── libvirt_leaseshelper
├── libvirt_lxc
├── libvirt_parthelper
├── libvirt_sanlock_helper
├── lock-driver
│   └── lockd.so
├── storage-backend
│   ├── libvirt_storage_backend_disk.so
│   ├── libvirt_storage_backend_fs.so
│   ├── libvirt_storage_backend_iscsi.so
│   ├── libvirt_storage_backend_logical.so
│   ├── libvirt_storage_backend_mpath.so
│   └── libvirt_storage_backend_scsi.so
└── virt-aa-helper
/usr/lib/libvirt-admin.so [error opening dir]
/usr/lib/libvirt-admin.so.0 [error opening dir]
/usr/lib/libvirt-admin.so.0.4003.0 [error opening dir]
/usr/lib/libvirt-lxc.so [error opening dir]
/usr/lib/libvirt-lxc.so.0 [error opening dir]
/usr/lib/libvirt-lxc.so.0.4003.0 [error opening dir]
/usr/lib/libvirt-qemu.so [error opening dir]
/usr/lib/libvirt-qemu.so.0 [error opening dir]
/usr/lib/libvirt-qemu.so.0.4003.0 [error opening dir]
/usr/lib/libvirt.so [error opening dir]
/usr/lib/libvirt.so.0 [error opening dir]
/usr/lib/libvirt.so.0.4003.0 [error opening dir]

定义KVM实例

列出宿主机上所有的虚拟机

jahentao:~$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     ubuntu14.04                    shut off
jahentao:qemu$ cp debian.img debian2.img

编写XML配置文件,定义KVM实例

<boot dev>指定了虚拟机的启动设备
有关domain XML的文档 https://libvirt.org/formatdomain.html

virsh从XML创建虚拟机

jahentao:~$ sudo virsh define kvm1.xml
Domain kvm1 defined from kvm1.xml
jahentao:qemu$ ls /etc/libvirt/qemu/
kvm1.xml  networks  ubuntu14.04.xml

查看虚拟机列表

jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     kvm1                           shut off
 -     ubuntu14.04                    shut off

取消定义,即删除

jahentao:qemu$ sudo virsh undefine kvm1
Domain kvm1 has been undefined
jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     ubuntu14.04                    shut off

自己编写XML定义很容易出错,参考使用 virt-install 命令

启动、停止、移除KVM实例

启动

jahentao:qemu$ sudo virsh start kvm1
Domain kvm1 started

查看运行状态

jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 3     kvm1                           running
 -     ubuntu14.04                    shut off

验证

jahentao:qemu$ pgrep -lfa qemu
9138 qemu-system-x86_64 -enable-kvm -name guest=kvm1,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-3-kvm1/master-key.aes -machine pc-i440fx-2.12,accel=kvm,usb=off,dump-guest-core=off -cpu Nehalem -m 1024 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid 2616fd23-18e6-4e14-90c3-8042b890344c -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-3-kvm1/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -no-shutdown -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot strict=on -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x4.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x4.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x4.0x2 -drive file=/pan/qemu/debian2.img,format=raw,if=none,id=drive-ide0-0-0 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 -netdev tap,fd=27,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:ce:2c:a2,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -vnc 127.0.0.1:0 -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on

可以看见同xml中读取传递了大量参数.

停止KVM实例

jahentao:qemu$ sudo virsh destroy kvm1
Domain kvm1 destroyed
jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     kvm1                           shut off
 -     ubuntu14.04                    shut off

移除实例

jahentao:qemu$ sudo virsh undefine kvm1
Domain kvm1 has been undefined
jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     ubuntu14.04                    shut off

查看和编辑KVM配置

确保虚拟机正在运行

jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 5     kvm1                           running
 -     ubuntu14.04                    shut off

将配置文件dump到标准输出

jahentao:qemu$ sudo virsh dumpxml kvm1
<domain type='kvm' id='5'>
  <name>kvm1</name>
  <uuid>87efed27-be55-43f3-a5a1-ea523679c90c</uuid>
  <memory unit='KiB'>1048576</memory>
  <currentMemory unit='KiB'>1048576</currentMemory>
  <vcpu placement='static'>1</vcpu>
  <resource>
    <partition>/machine</partition>
  </resource>
  <os>
    <type arch='x86_64' machine='pc-i440fx-2.12'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
  </features>
  <cpu mode='custom' match='exact' check='full'>
    <model fallback='forbid'>Nehalem</model>
    <feature policy='require' name='vme'/>
    <feature policy='require' name='x2apic'/>
    <feature policy='require' name='hypervisor'/>
  </cpu>
  <clock offset='utc'>
    <timer name='rtc' tickpolicy='catchup'/>
    <timer name='pit' tickpolicy='delay'/>
    <timer name='hpet' present='no'/>
  </clock>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <pm>
    <suspend-to-mem enabled='no'/>
    <suspend-to-disk enabled='no'/>
  </pm>
  <devices>
    <emulator>/usr/bin/kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/pan/qemu/debian2.img'/>
      <backingStore/>
      <target dev='hda' bus='ide'/>
      <alias name='ide0-0-0'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <controller type='usb' index='0' model='ich9-ehci1'>
      <alias name='usb'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x7'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci1'>
      <alias name='usb'/>
      <master startport='0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci2'>
      <alias name='usb'/>
      <master startport='2'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci3'>
      <alias name='usb'/>
      <master startport='4'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'>
      <alias name='pci.0'/>
    </controller>
    <controller type='ide' index='0'>
      <alias name='ide'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <interface type='network'>
      <mac address='52:54:00:9c:9b:06'/>
      <source network='default' bridge='virbr0'/>
      <target dev='vnet0'/>
      <model type='rtl8139'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <source path='/dev/pts/1'/>
      <target type='isa-serial' port='0'>
        <model name='isa-serial'/>
      </target>
      <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/1'>
      <source path='/dev/pts/1'/>
      <target type='serial' port='0'/>
      <alias name='serial0'/>
    </console>
    <input type='mouse' bus='ps2'>
      <alias name='input0'/>
    </input>
    <input type='keyboard' bus='ps2'>
      <alias name='input1'/>
    </input>
    <graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1'>
      <listen type='address' address='127.0.0.1'/>
    </graphics>
    <video>
      <model type='cirrus' vram='16384' heads='1' primary='yes'/>
      <alias name='video0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
      <alias name='balloon0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </memballoon>
  </devices>
  <seclabel type='dynamic' model='dac' relabel='yes'>
    <label>+64055:+64055</label>
    <imagelabel>+64055:+64055</imagelabel>
  </seclabel>
</domain>

Dump到文件

jahentao:qemu$ sudo virsh dumpxml kvm1 > kvm1_dump.xml

编辑kvm1配置

jahentao:qemu$ sudo virsh edit kvm1
Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny
  4. /usr/bin/code
Choose 1-4 [1]:
Domain kvm1 XML configuration not changed.

管理KVM中的CPU和内存资源

获取运行实例的信息

jahentao:~$ sudo virsh dommemstat kvm1
actual 1048576
swap_in 0
swap_out 0
major_fault 155
minor_fault 27761
unused 959200
available 1020300
usable 903764
last_update 1552137455
rss 219708

更新可用内存大小

jahentao:~$ sudo virsh setmem kvm1 --size 1049000
error: invalid argument: cannot set memory higher than max memory

关闭虚拟机

jahentao:~$ sudo virsh destroy kvm1
Domain kvm1 destroyed

调整最大可用内存为2G

jahentao:~$ sudo virsh setmaxmem kvm1 --size 2097152

重新启动虚拟机

jahentao:~$ sudo virsh start kvm1
Domain kvm1 started

查看更新后的信息

jahentao:~$ sudo virsh dommemstat kvm1
actual 1048576
swap_in 0
swap_out 0
major_fault 150
minor_fault 25073
unused 1992768
available 2052492
usable 1932580
last_update 1552138163
rss 258580

检查XML内存配置

jahentao:~$ sudo virsh dumpxml kvm1 | grep memory
  <memory unit='KiB'>2097152</memory>

获取CPU信息

jahentao:~$ sudo virsh vcpuinfo kvm1
VCPU:           0
CPU:            6
State:          running
CPU time:       18.8s
CPU Affinity:   yyyyyyyy

列出被客户机使用的CPU

jahentao:~$ sudo virsh vcpucount kvm1
maximum      config         1
maximum      live           1
current      config         1
current      live           1

修改vCPU数目

jahentao:~$ sudo virsh edit kvm1
[sudo] jahentao 的密码:
Domain kvm1 XML configuration edited.
<vcpu placement='static'>4</vcpu>

查看修改后的CPU信息

jahentao:~$ sudo virsh vcpucount kvm1
maximum      config         4
maximum      live           1
current      config         4
current      live           1
jahentao:~$ sudo virsh dumpxml kvm1 | grep -i cp
  <vcpu placement='static'>1</vcpu>
    <acpi/>
  <cpu mode='custom' match='exact' check='full'>
  </cpu>

只是配置值改变了,为什么live值不变呢?

重启之后好了。

给虚拟机增加块设备

给虚拟机添加块设备,可以是iSCSI、LVM逻辑卷或者镜像文件

创建1G的镜像文件

jahentao:qemu$ dd if=/dev/zero of=/tmp/new_disk.img bs=1M count=1024
记录了1024+0 的读入
记录了1024+0 的写出
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.909218 s, 1.2 GB/s

将镜像文件作为磁盘,挂载到虚拟机

jahentao:qemu$ sudo virsh attach-disk kvm1 /tmp/new_disk.img vda --live
Disk attached successfully

连接到KVM实例

jahentao:~$ sudo virsh console kvm1
Connected to domain kvm1
Escape character is ^]
Debian GNU/Linux 9 jahentao-PC ttyS0
jahentao-PC login: root
Password:
Last login: Sun Mar 10 00:44:03 UTC 2019 on tty1
Linux jahentao-PC 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3 (2019-02-02) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@jahentao-PC:~# 

查看磁盘信息

root@jahentao-PC:~# fdisk -l /dev/vda
Disk /dev/vda: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
jahentao:qemu$ sudo virsh dumpxml kvm1
……
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/pan/qemu/debian2.img'/>
      <backingStore/>
      <target dev='hda' bus='ide'/>
      <alias name='ide0-0-0'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/tmp/new_disk.img'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </disk>
……

查看新磁盘的信息

jahentao:qemu$ sudo virsh domblkstat kvm1 vda
vda rd_req 48
vda rd_bytes 1081344
vda wr_req 0
vda wr_bytes 0
vda flush_operations 0
vda rd_total_times 6797296
vda wr_total_times 0
vda flush_total_times 0

删除磁盘

jahentao:qemu$ sudo virsh detach-disk kvm1 vda --live
Disk detached successfully

虚拟机和宿主机共享文件夹

在宿主机上创建共享目录

jahentao:qemu$ mkdir /tmp/shared
jahentao:qemu$ touch /tmp/shared/file

停止客户机后,编辑配置文件

jahentao:qemu$ sudo virsh destroy kvm1
Domain kvm1 destroyed
jahentao:qemu$ sudo virsh edit kvm1
Domain kvm1 XML configuration edited.
……
    <filesystem type='mount' accessmode='passthrough'>
        <source dir='/tmp/shared' />
        <target dir='tmp_shared' />
    </filesystem>

accessmode有三种:

  • passthrough,默认,使用的客户机中用户的权限
  • mapped,继承自宿主机QEMU用户的权限
  • squash,与passthrough类似,但禁用chmod

登录后查看9p和virto模块都在

jahentao:qemu$ sudo virsh console kvm1
Connected to domain kvm1
Escape character is ^]
Debian GNU/Linux 9 jahentao-PC ttyS0
jahentao-PC login: root
Password:
Last login: Sun Mar 10 01:03:56 UTC 2019 on ttyS0
Linux jahentao-PC 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3 (2019-02-02) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@jahentao-PC:~# lsmod | grep 9p
9pnet_virtio           20480  0
9pnet                  86016  1 9pnet_virtio
virtio_ring            24576  3 9pnet_virtio,virtio_balloon,virtio_pci
virtio                 16384  3 9pnet_virtio,virtio_balloon,virtio_pci

如果没有加载,则加载

modprobe 9p virtio

将共享目录挂载到/mnt

root@jahentao-PC:~# mount -t 9p -o trans=virtio tmp_shared /mnt

查看宿主机中共享的文件

root@jahentao-PC:~# ls -la /mnt/
total 8
drwxr-xr-x  2 1000 1000 4096 Mar 10 01:31 .
drwxr-xr-x 22 root root 4096 Mar  7 11:56 ..
-rw-r--r--  1 1000 1000    0 Mar 10 01:31 file

如何取消挂载呢?重启之后报错。

设置自动启动KVM实例

默认情况下,KVM实例要等宿主机操作系统启动之后,才能运行。

当宿主机操作系统重启时,即使libvirt守护进程运行着,libvirt创建的实例并不会自动运行。

可以设置libvirt守护进程启动时,即启动KVM实例。

jahentao:qemu$ sudo virsh autostart kvm1
[sudo] jahentao 的密码:
Domain kvm1 marked as autostarted
jahentao:qemu$ sudo virsh dominfo kvm1
Id:             3
Name:           kvm1
UUID:           87efed27-be55-43f3-a5a1-ea523679c90c
OS Type:        hvm
State:          running
CPU(s):         4
CPU time:       29.6s
Max memory:     2097152 KiB
Used memory:    1048576 KiB
Persistent:     yes
Autostart:      enable
Managed save:   no
Security model: none
Security DOI:   0

停止运行的实例

jahentao:qemu$ sudo virsh destroy kvm1
Domain kvm1 destroyed
jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     kvm1                           shut off
 -     kvm2                           shut off
 -     ubuntu14.04                    shut off

停止libvirtd守护进程

jahentao:qemu$ /etc/init.d/libvirtd stop
[ ok ] Stopping libvirtd (via systemctl): libvirtd.service.
jahentao:qemu$ pgrep -lfa libvirtd

启动守护进程

jahentao:qemu$ /etc/init.d/libvirtd start
[ ok ] Starting libvirtd (via systemctl): libvirtd.service.

查看实例是否自动启动

jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 1     kvm1                           running
 -     kvm2                           shut off
 -     ubuntu14.04                    shut off

取消实例自动启动

jahentao:qemu$ sudo virsh autostart kvm1 --disable
Domain kvm1 unmarked as autostarted

安装部署KVM虚拟机(三)

使用 virt-install能够生成虚拟机的XML定义文件

jahentao:qemu$ sudo virt-install --name kvm1 --ram 1024 --disk path=/pan/qemu/debian2.img,format=raw --graphics vnc,listen=127.0.0.1 --noautoconsole --hvm --import
WARNING  未检测到操作系统,虚拟机性能可能会受到影响。使用 --os-variant 选项指定操作系统以获得最佳性能。
开始安装......
域创建完成。

查看创建的虚拟机

jahentao:qemu$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 2     kvm1                           running
 -     ubuntu14.04                    shut off

查看生成的XML定义,文档详见:https://libvirt.org/formatdomain.html

查看kvm1的XML,位于/etc/libvirt/qemu/kvm1.xml


使用virt-install也能安装系统

jahentao:qemu$ sudo virt-install --name kvm2 --ram 1024 --extra-args="text console=tty0 utf8 console=ttyS0,115200" --graphics vnc,listen=127.0.0.1 --hvm --location=https://mirrors.tuna.tsinghua.edu.cn/debian/dists/stable/main/installer-amd64/ --disk path=/pan/qemu/kvm2.img,size=8
WARNING  未检测到操作系统,虚拟机性能可能会受到影响。使用 --os-variant 选项指定操作系统以获得最佳性能。
开始安装......
搜索文件 linux......                                        | 4.0 MB  00:00:20
搜索文件 initrd.gz......                                    |  24 MB  00:00:57
正在分配 'kvm1.img'                                         | 8.0 GB  00:00:00     

然后控制台连接

jahentao:qemu$ sudo virsh console kvm2
Connected to domain kvm2
Escape character is ^]

一旦连接上会选择安装配置

通过弹出的文本菜单完成安装。

启动安装的虚拟机

jahentao:qemu$ sudo virsh start kvm2
Domain kvm2 started
jahentao:qemu$ ll
-rw------- 1 libvirt-qemu libvirt-qemu  8591507456 3月   9 18:07 kvm2.img

使用VNC客户端连接,这里我用的evnc

安装失败。引导问题,可能是安装的时候没有在grub界面中输入/sda1的分区。

尝试修复,修复过程和使用 qemu-img 和 qemu-system-x86_64 命令行方式安装中安装引导类似。

jahentao:qemu$ sudo modprobe nbd
jahentao:qemu$ sudo qemu-nbd --format=qcow2 --connect=/dev/nbd0 kvm2.img
jahentao:qemu$ sudo mount /dev/nbd0p1 /mnt/
jahentao:qemu$ sudo mount --bind /dev/ /mnt/dev
jahentao:qemu$ sudo chroot /mnt/
root@jahentao-PC:/# pwd
root@jahentao-PC:/# mount -t proc none /proc
root@jahentao-PC:/# mount -t sysfs none /sys
root@jahentao-PC:/# grub-install /dev/nbd0 --force
root@jahentao-PC:/# update-grub2
root@jahentao-PC:/# passwd
root@jahentao-PC:/# echo "pts/0" >> /etc/securetty
root@jahentao-PC:/# systemctl set-default multi-user.target
root@jahentao-PC:/# echo "/dev/sda1 / ext4 defaults,discard 0 0" > /etc/fstab
root@jahentao-PC:/# umount /proc/ /sys/ /dev/
root@jahentao-PC:/# exit
jahentao:qemu$ sudo grub-install /dev/nbd0 --root-directory=/mnt --modules="biosdisk part_msdos" --force
sed -i 's/nbd0p1/sda1/g' /mnt/boot/grub/grub.cfg
jahentao:qemu$ sudo umount /mnt
jahentao:qemu$ sudo qemu-nbd --disconnect /dev/nbd0

修复成功。

VNC连接root登录并启动服务

systemctl enable serial-getty@ttyS0.service
systemctl start serial-getty@ttyS0.service

控制台登录

jahentao:qemu$ sudo virsh console kvm2
Connected to domain kvm2
Escape character is ^]
Debian GNU/Linux 9 kvm2 ttyS0
kvm2 login: root
Password:
Last login: Sat Mar  9 19:10:32 CST 2019 on tty1
Linux kvm2 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@kvm2:~# 

使用Ctrl + ] 断开控制台

停止

查看

jahentao:qemu$ sudo qemu-img info kvm2.img
image: kvm2.img
file format: qcow2
virtual size: 8.0G (8589934592 bytes)
disk size: 5.2G
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: true
    refcount bits: 16
    corrupt: false

以上virt-install安装,使用了两种方式连接。

安装部署KVM虚拟机(二)

使用 qemu-img 和 qemu-system-x86_64 命令行方式安装

jahentao:qemu$ qemu-img create -f raw debian.img 10G
Formatting 'debian.img', fmt=raw size=10737418240

验证

jahentao:qemu$ ls -lah debian.img  # 验证大小
-rw-r--r-- 1 jahentao jahentao 10G Mar  7 17:12 debian.img
jahentao:qemu$ file -s debian.img  # 验证文件类型
debian.img: data
jahentao:qemu$ qemu-img info debian.img # 查看文件信息
image: debian.img
file format: raw
virtual size: 10G (10737418240 bytes)
disk size: 0

有关QEMU支持的格式:

  • raw
  • qcow2
  • qcow
  • dmg
  • nbd
  • vdi
  • vmdk
  • vhdk

继续在上面空白的镜像上创建文件系统

加载nbd内核模块

jahentao:qemu$ sudo modprobe nbd

使用qemu-nbd工具,将空白的镜像连接到/dev/nbd0块设备

jahentao:qemu$ sudo qemu-nbd --format=raw --connect=/dev/nbd0 debian.img

在块设备上创建两个分区。一个SWAP交换分区,一个作为客户机的根分区。

jahentao:qemu$ sudo sfdisk /dev/nbd0 << EOF
> ,1024,82
> ;
> EOF
Checking that no-one is using this disk right now ... OK
Disk /dev/nbd0: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
>>> Created a new DOS disklabel with disk identifier 0x02ff4743.
/dev/nbd0p1: Created a new partition 1 of type 'Linux swap / Solaris' and of size 512 KiB.
/dev/nbd0p2: Created a new partition 2 of type 'Linux' and of size 10 GiB.
/dev/nbd0p3: Done.
New situation:
Disklabel type: dos
Disk identifier: 0x02ff4743
Device      Boot Start      End  Sectors  Size Id Type
/dev/nbd0p1       2048     3071     1024  512K 82 Linux swap / Solaris
/dev/nbd0p2       4096 20971519 20967424   10G 83 Linux
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

查看分区后的块设备。

jahentao:qemu$ ls -la /dev/nbd0*
brw-rw---- 1 root disk 43, 0 3月   7 18:28 /dev/nbd0
brw-rw---- 1 root disk 43, 1 3月   7 18:28 /dev/nbd0p1
brw-rw---- 1 root disk 43, 2 3月   7 18:28 /dev/nbd0p2

创建交换分区

jahentao:qemu$ sudo mkswap /dev/nbd0p1
Setting up swapspace version 1, size = 508 KiB (520192 bytes)
no label, UUID=9ef655d8-af50-413b-9843-912a351f4981

在根分区创建EXT4文件系统

jahentao:qemu$ sudo mkfs.ext4 /dev/nbd0p2
mke2fs 1.44.2 (14-May-2018)
Discarding device blocks: failed - input/output error
Creating filesystem with 2620928 4k blocks and 655360 inodes
Filesystem UUID: 1e677faa-6f1f-4aae-97a8-7c6709c4a2d4
Superblock backups stored on blocks:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done 

充分利用内核末班nbd的提供的功能,用qemu-nbd将一个raw格式的镜像文件关联到块设备/dev/nbd0。

查看nbd内核模块的信息。

jahentao:qemu$ modinfo nbd
filename:       /lib/modules/4.15.0-29deepin-generic/kernel/drivers/block/nbd.ko
license:        GPL
description:    Network Block Device
srcversion:     F8504F95103BB66D10CBE33
depends:
retpoline:      Y
intree:         Y
name:           nbd
vermagic:       4.15.0-29deepin-generic SMP mod_unload
sig_id:         PKCS#7
signer:
sig_key:
sig_hashalgo:   md4
signature:      30:82:02:9A:06:09:2A:86:48:86:F7:0D:01:07:02:A0:82:02:8B:30:
		82:02:87:02:01:01:31:0D:30:0B:06:09:60:86:48:01:65:03:04:02:
		03:30:0B:06:09:2A:86:48:86:F7:0D:01:07:01:31:82:02:64:30:82:
		02:60:02:01:01:30:3B:30:2E:31:2C:30:2A:06:03:55:04:03:0C:23:
		42:75:69:6C:64:20:74:69:6D:65:20:61:75:74:6F:67:65:6E:65:72:
		61:74:65:64:20:6B:65:72:6E:65:6C:20:6B:65:79:02:09:00:F4:22:
		1F:32:5B:71:A7:D6:30:0B:06:09:60:86:48:01:65:03:04:02:03:30:
		0D:06:09:2A:86:48:86:F7:0D:01:01:01:05:00:04:82:02:00:BF:66:
		FE:A2:15:6E:92:5F:41:85:AE:07:C5:16:41:51:99:72:A4:FB:B0:68:
		FF:21:5B:37:33:6D:9C:62:16:C5:2F:46:C8:98:33:DC:12:11:2C:3E:
		1C:29:26:86:2E:FA:3E:E4:F9:F6:D0:91:33:9C:47:3E:DE:FC:77:30:
		5D:8D:98:40:F0:1E:29:6D:16:BC:54:A3:C2:C7:BE:88:46:74:A0:C6:
		B4:4D:8C:1D:52:1C:0E:C7:80:52:DE:9B:43:FC:0A:88:32:AA:95:54:
		5C:87:90:8A:1B:8C:17:B7:9B:24:2C:61:DE:D6:66:67:C0:FB:1A:09:
		51:BB:35:EE:6B:F5:2A:8C:48:0F:EB:8A:D6:45:04:C6:65:B0:12:AC:
		23:BB:AC:75:BB:FD:71:46:A2:AD:FD:0C:BA:C4:5A:8D:A1:C4:1A:F5:
		AD:29:77:6E:E9:66:9B:E9:8C:C0:CD:99:2B:7F:C6:13:32:E3:27:95:
		8A:CD:60:E6:39:7F:02:FD:0D:AC:88:11:DD:45:C1:19:C1:9E:CC:58:
		E1:6C:8D:C2:CE:D7:82:30:3C:8E:AD:02:CC:70:3C:99:A7:C2:D8:C4:
		BC:BE:53:6D:3E:8E:F3:2F:17:27:11:8D:3C:EB:4D:C5:5B:6B:95:9B:
		A3:C1:D7:8A:E2:BF:92:3E:E6:7D:50:9A:9D:81:02:65:E8:6E:45:81:
		04:DD:84:08:01:7E:72:20:1D:48:E1:EF:F8:2B:05:63:CB:B7:A2:E8:
		23:82:64:8C:6D:5F:E9:AB:D7:D6:B1:12:5E:FF:AA:C6:41:8E:FF:1C:
		D7:76:70:21:71:68:87:55:7C:A8:A4:B2:AE:40:38:9F:73:58:A3:01:
		5A:76:77:24:A6:69:4A:E9:A0:04:E7:C9:27:99:1E:70:41:A6:8D:2D:
		2F:18:06:1B:59:71:74:C3:59:68:A8:CB:0C:3F:76:E0:C0:70:B8:17:
		97:14:C7:73:E7:88:23:EB:E2:1D:08:1C:2C:B5:A0:3B:18:2D:5B:87:
		96:D8:CC:23:38:E6:DA:17:74:CE:BA:6C:6F:A5:B2:C6:2E:5A:1A:91:
		E9:D7:53:7F:55:58:5F:26:B8:4C:C5:E9:D7:0F:84:87:34:6F:FE:5B:
		B2:47:97:DD:48:CC:B9:CF:B9:12:A3:50:38:C7:82:C2:05:84:C8:6E:
		94:64:C3:7D:BB:53:C9:11:B0:0D:C4:17:46:F4:08:D7:79:C6:13:5A:
		B4:48:01:84:D0:ED:5C:88:F7:63:8F:0F:6B:69:69:03:C5:F1:2C:DE:
		E7:70:1F:6D:D6:97:37:94:4A:21:09:A3:56:4C:1D:54:21:A5:2B:4D:
		BB:6B:1F:CA:49:41:FD:BA:B6:92
parm:           nbds_max:number of network block devices to initialize (default: 16) (int)
parm:           max_part:number of partitions per device (default: 16) (int)

块设备的元属性已经被修改了。

jahentao:qemu$ sudo file -s /dev/nbd0
/dev/nbd0: DOS/MBR boot sector; partition 1 : ID=0x82, start-CHS (0x0,32,33), end-CHS (0x0,48,48), startsector 2048, 1024 sectors; partition 2 : ID=0x83, start-CHS (0x0,65,2), end-CHS (0x119,106,17), startsector 4096, 20967424 sectors

同样镜像文件的属性也被改变了

jahentao:qemu$ file -s debian.img
debian.img: DOS/MBR boot sector; partition 1 : ID=0x82, start-CHS (0x0,32,33), end-CHS (0x0,48,48), startsector 2048, 1024 sectors; partition 2 : ID=0x83, start-CHS (0x0,65,2), end-CHS (0x119,106,17), startsector 4096, 20967424 sectors

现在该 debian.img 镜像文件包含了两个分区和一个文件系统。

接下来安装客户机的OS系统,以Debian为例。

debootstrap:  Bootstrap a basic Debian system

参考 https://hosxy.github.io/2017/05/03/debootstrap%E5%AE%89%E8%A3%85debian/

jahentao:qemu$ sudo apt install debootstrap

将/dev/nbd0p2分区挂载到/mnt,这样就能看见内容了

jahentao:qemu$ sudo mount /dev/nbd0p2 /mnt/
jahentao:qemu$ sudo mount | grep mnt
/dev/nbd0p2 on /mnt type ext4 (rw,relatime,data=ordered)

将根分区挂载到/mnt,挂载点作为安装目标,使用debootstrap从公开仓库安装最新的Debian发行版

Debian全球镜像站点 https://www.debian.org/mirror/list

jahentao:qemu$ sudo debootstrap --arch=amd64 --include="openssh-server vim" stable /mnt/ http://mirrors.ustc.edu.cn/debian
I: Target architecture can be executed
I: Retrieving InRelease
……
I: Base system installed successfully.

验证根文件系统创建好了

jahentao:qemu$ ls -lah /mnt/
总用量 100K
drwxr-xr-x 22 root root 4.0K 3月   7 19:35 .
drwxr-xr-x 26 root root 4.0K 3月   4 21:39 ..
drwxr-xr-x  2 root root 4.0K 3月   7 19:34 bin
drwxr-xr-x  2 root root 4.0K 2月   3 21:01 boot
drwxr-xr-x  4 root root 4.0K 3月   7 19:26 dev
drwxr-xr-x 53 root root 4.0K 3月   7 19:35 etc
drwxr-xr-x  2 root root 4.0K 2月   3 21:01 home
drwxr-xr-x 10 root root 4.0K 3月   7 19:32 lib
drwxr-xr-x  2 root root 4.0K 3月   7 19:29 lib64
drwx------  2 root root  16K 3月   7 18:34 lost+found
drwxr-xr-x  2 root root 4.0K 3月   7 19:26 media
drwxr-xr-x  2 root root 4.0K 3月   7 19:26 mnt
drwxr-xr-x  2 root root 4.0K 3月   7 19:26 opt
drwxr-xr-x  2 root root 4.0K 2月   3 21:01 proc
drwx------  2 root root 4.0K 3月   7 19:26 root
drwxr-xr-x  3 root root 4.0K 3月   7 19:26 run
drwxr-xr-x  2 root root 4.0K 3月   7 19:35 sbin
drwxr-xr-x  2 root root 4.0K 3月   7 19:26 srv
drwxr-xr-x  2 root root 4.0K 2月   3 21:01 sys
drwxrwxrwt  2 root root 4.0K 3月   7 19:35 tmp
drwxr-xr-x 10 root root 4.0K 3月   7 19:26 usr
drwxr-xr-x 11 root root 4.0K 3月   7 19:26 var

为个给镜像安装GRUB引导程序,将宿主机的文件系统/dev目录挂载到镜像文件系统/mnt内

jahentao:qemu$ sudo mount --bind /dev/ /mnt/dev

使用chroot工具,切换到镜像的根文件系统的命名空间。这样执行的操作就是在客户机系统内的。

jahentao:qemu$ sudo chroot /mnt/
root@jahentao-PC:/# pwd
/

检查chroot环境下的发布版本

root@jahentao-PC:/# cat /etc/debian_version
9.8

在已经chroot的环境下,挂载/proc和/sys虚拟文件系统,这是因为GRUB引导程序需要它们

root@jahentao-PC:/# mount -t proc none /proc
root@jahentao-PC:/# mount -t sysfs none /sys

仍然在已经chroot的环境下,安装Debian内核元数据包和grub2工具

root@jahentao-PC:/# apt-get install -y --force-yes linux-image-amd64 grub2
Reading package lists... Done

在根设备上安装GRUB

root@jahentao-PC:/# grub-install /dev/nbd0 --force
Installing for i386-pc platform.
Installation finished. No error reported.

更新GRUB配置和initrd镜像。生成GRUB配置文件,更新内存盘镜像

root@jahentao-PC:/# update-grub2
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.9.0-8-amd64
Found initrd image: /boot/initrd.img-4.9.0-8-amd64
Found Deepin 15.9.1  (15.9.1) on /dev/sda1
done

更改密码

root@jahentao-PC:/# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

在新客户机内部允许访问pseudo 终端,之后就可以登录虚拟机了

root@jahentao-PC:/# echo "pts/0" >> /etc/securetty

更改多用户运行级别

root@jahentao-PC:/# systemctl set-default multi-user.target
Created symlink /etc/systemd/system/default.target → /lib/systemd/system/multi-user.target.

这时fstab还是空的,给fstab增加root挂载点,使它能够启动

echo "/dev/sda2 / ext4 defaults,discard 0 0" > /etc/fstab

取消挂载的文件系统

umount /proc/ /sys/ /dev/

退出chroot的路径

root@jahentao-PC:/# exit
exit
jahentao:qemu$ 

在宿主机根分区上安装GRUB,关联raw镜像文件

jahentao:qemu$ sudo grub-install /dev/nbd0 --root-directory=/mnt --modules="biosdisk part_msdos" --force
[sudo] jahentao 的密码:
Installing for i386-pc platform.
Installation finished. No error reported.

更新GRUB配置文件,反映正确的客户机块设备信息。sda2是客户机内部可见的nbd0p2是当前宿主机可见的。从客户机的角度,第二块分区默认就是sda2。

sed -i 's/nbd0p2/sda2/g' /mnt/boot/grub/grub.cfg

取消挂载

sudo umount /mnt

取消ndb0设备与镜像的关联

jahentao:qemu$ sudo qemu-nbd --disconnect /dev/nbd0
/dev/nbd0 disconnected

再查看宿主机上支持的CPU架构

jahentao:qemu$ qemu-system-x86_64 --cpu help
Available CPUs:
x86              486
x86   Broadwell-IBRS  Intel Core Processor (Broadwell, IBRS)
x86 Broadwell-noTSX-IBRS  Intel Core Processor (Broadwell, no TSX, IBRS)
x86  Broadwell-noTSX  Intel Core Processor (Broadwell, no TSX)
x86        Broadwell  Intel Core Processor (Broadwell)
x86           Conroe  Intel Celeron_4x0 (Conroe/Merom Class Core 2)
x86        EPYC-IBPB  AMD EPYC Processor (with IBPB)
x86             EPYC  AMD EPYC Processor
x86     Haswell-IBRS  Intel Core Processor (Haswell, IBRS)
x86 Haswell-noTSX-IBRS  Intel Core Processor (Haswell, no TSX, IBRS)
x86    Haswell-noTSX  Intel Core Processor (Haswell, no TSX)
x86          Haswell  Intel Core Processor (Haswell)
x86   IvyBridge-IBRS  Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)
x86        IvyBridge  Intel Xeon E3-12xx v2 (Ivy Bridge)
x86     Nehalem-IBRS  Intel Core i7 9xx (Nehalem Core i7, IBRS update)
x86          Nehalem  Intel Core i7 9xx (Nehalem Class Core i7)
x86       Opteron_G1  AMD Opteron 240 (Gen 1 Class Opteron)
x86       Opteron_G2  AMD Opteron 22xx (Gen 2 Class Opteron)
x86       Opteron_G3  AMD Opteron 23xx (Gen 3 Class Opteron)
x86       Opteron_G4  AMD Opteron 62xx class CPU
x86       Opteron_G5  AMD Opteron 63xx class CPU
x86           Penryn  Intel Core 2 Duo P9xxx (Penryn Class Core 2)
x86 SandyBridge-IBRS  Intel Xeon E312xx (Sandy Bridge, IBRS update)
x86      SandyBridge  Intel Xeon E312xx (Sandy Bridge)
x86 Skylake-Client-IBRS  Intel Core Processor (Skylake, IBRS)
x86   Skylake-Client  Intel Core Processor (Skylake)
x86 Skylake-Server-IBRS  Intel Xeon Processor (Skylake, IBRS)
x86   Skylake-Server  Intel Xeon Processor (Skylake)
x86    Westmere-IBRS  Westmere E56xx/L56xx/X56xx (IBRS update)
x86         Westmere  Westmere E56xx/L56xx/X56xx (Nehalem-C)
x86           athlon  QEMU Virtual CPU version 2.5+
x86         core2duo  Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz
x86          coreduo  Genuine Intel(R) CPU           T2600  @ 2.16GHz
x86            kvm32  Common 32-bit KVM processor
x86            kvm64  Common KVM processor
x86             n270  Intel(R) Atom(TM) CPU N270   @ 1.60GHz
x86          pentium
x86         pentium2
x86         pentium3
x86           phenom  AMD Phenom(tm) 9550 Quad-Core Processor
x86           qemu32  QEMU Virtual CPU version 2.5+
x86           qemu64  QEMU Virtual CPU version 2.5+
x86             base  base CPU model type with no features enabled
x86             host  Enables all features supported by the accelerator in the current host
x86              max  Enables all features supported by the accelerator in the current host
Recognized CPUID flags:
  fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 pn clflush ds acpi mmx fxsr sse sse2 ss ht tm ia64 pbe
  pni pclmulqdq dtes64 monitor ds-cpl vmx smx est tm2 ssse3 cid fma cx16 xtpr pdcm pcid dca sse4.1 sse4.2 x2apic movbe popcnt tsc-deadline aes xsave osxsave avx f16c rdrand hypervisor
  fsgsbase tsc-adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap avx512ifma pcommit clflushopt clwb intel-pt avx512pf avx512er avx512cd sha-ni avx512bw avx512vl
  avx512vbmi umip pku ospke avx512vbmi2 gfni vaes vpclmulqdq avx512vnni avx512bitalg avx512-vpopcntdq la57 rdpid
  avx512-4vnniw avx512-4fmaps spec-ctrl
  syscall nx mmxext fxsr-opt pdpe1gb rdtscp lm 3dnowext 3dnow
  lahf-lm cmp-legacy svm extapic cr8legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 tce nodeid-msr tbm topoext perfctr-core perfctr-nb
  invtsc
  ibpb
  xstore xstore-en xcrypt xcrypt-en ace2 ace2-en phe phe-en pmm pmm-en
  kvmclock kvm-nopiodelay kvm-mmu kvmclock kvm-asyncpf kvm-steal-time kvm-pv-eoi kvm-pv-unhalt kvm-pv-tlb-flush kvmclock-stable-bit
  kvm-hint-dedicated
  npt lbrv svm-lock nrip-save tsc-scale vmcb-clean flushbyasid decodeassists pause-filter pfthreshold
  xsaveopt xsavec xgetbv1 xsaves
  arat

使用x86-64架构qemu-system-x86_64 启动QEMU虚拟机

启动的是之前的我们安装好的debian.img镜像

qemu-system-x86_64 -name debian -cpu Nehalem -m 1024 -drive format=raw,index=2,file=debian.img -daemonize
安装成功

至此,说明之前的安装是成功的。安装之后可以ping通宿主机,关机重启之后网络就失效了。网络还得学一下如何配置,重点是bridge网络。可以在客户机内使用dhclient <网卡>申请IP地址。

安装部署KVM虚拟机(一)

最近有以特定网络模式,管理KVM虚拟机的需求,先尝试了安装和部署虚拟机。安装KVM虚拟机有四种方式,最近完成读书报告汇报,正逢周末,抽空把这些探索过程分享出来。

安装KVM虚拟机有四种方式:

  • 使用 virt-manager GUI工具
  • 使用 qemu-img 和 qemu-system-x86_64 命令行方式安装
  • 使用 virt-install 命令
  • 使用 libvirt工具集管理虚拟机的生命周期

在安装KVM虚拟机并用libvirt进行管理的时候,有本书对我很有帮助。《KVM Virtualization Cookbook (2017)》,也看见有人称它为KVM虚拟化实践的圣经,但中肯的评价是实践帮助确实很大。


安装环境说明:

软件 版本
Deepin 15.9
virt-top 1.0.8-1+b1 amd64
virt-manager 1.4.3
qemu-system-x86_64 2.12.0
virt-viewer 6.0
libvirtd(libvirt) 4.3.0
virt-install 1.4.3
bridge-utils 1.5-16 amd64

宿主机为Intel CPU,支持Intel虚拟化,确保BIOS里开启VT

cat /proc/cpuinfo |grep vmx| uniq  #intel cpu
# 有输出

KVM是Linux的一个模块

jahentao:~$ lsmod | grep kvm
kvm_intel             204800  0
kvm                   593920  1 kvm_intel
irqbypass              16384  1 kvm

使用 virt-manager GUI工具

命令行输入 virt-manager,打开Virtual Machine Manager窗口页面;

virt-manager GUI

使用 VMM GUI 创建的虚机的xml 定义文件在 /etc/libvirt/qemu/ 目录中。

在操作创建虚拟机过程中遇到了问题:ISO文件所在路径没有搜索权限。

方法一:复制iso镜像到用户目录下。

virt-manager doesn't have permission to access other users' directories and devices. Even when run as root. (you can change this is SElinux, but it's less hassle to just copy the .iso over) 

https://unix.stackexchange.com/questions/409860/virt-manager-the-emulator-may-not-have-search-permissions-for-the-path

方法二:将iso文件所在上层目录改为当前用户和用户组所有。 https://www.reddit.com/r/VFIO/comments/5ti9h2/virtmanager_the_emulator_may_not_have_search/

改为当前用户和用户组所有

继续

Step 1

据说Ubuntu 16.04的iso官方镜像中文安装有问题,换成14.04

Step 2
Step 3
Step 4
Step 4.1
Step 5
开始安装

以下可视化界面安装。

安装中

这样安装好了。

网络使用的default模式,一开始是inactive状态,但安装系统的时候正常。之后重启了,尝试开启,又会遇到default(NAT)模式inactive的问题。

Requested operation is not valid: network 'default' is not active.

管理界面

Virt-manager使用的是Python调用libvirt的API进行GUI管理。

default network未启用
虚拟网络配置

解决方法:

  • 点击左下角启动网络
  • 勾选开机时自动启动
  • 点击应用

这几步图形界面操作,对应的管理命令应该是

# virsh net-autostart default
# virsh net-start default

default虚拟网络,用的virbr0网卡。

jahentao:~$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:66:de:00:34  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
enp8s0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether 40:61:86:b9:34:a3  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 9059  bytes 2463836 (2.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9059  bytes 2463836 (2.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether 52:54:00:06:73:0e  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
wlp6s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.103  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::9733:2f30:b3e:2e39  prefixlen 64  scopeid 0x20<link>
        ether 00:26:c7:a4:10:a6  txqueuelen 1000  (Ethernet)
        RX packets 9148  bytes 4179684 (3.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12135  bytes 8761784 (8.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

By the way, Kubernetes已经有项目将KVM libvirt集成了,名为kubevirt。有个录屏效果。

在请求virt-manager、virsh等系统管理时,每台虚拟机都会由libvirtd启动一个独立的qemu-kvm进程。

虚拟机的属性如CPU,内存,I/O设备配置都在/etc/libvirt/qemu/下、libvirtd通过读取XML配置文件,获取传给qemu-kvm的参数列表。

jahentao:pan$ tree /etc/libvirt/qemu/
/etc/libvirt/qemu/
|-- networks
|   |-- autostart
|   |   `-- default.xml -> /etc/libvirt/qemu/networks/default.xml
|   `-- default.xml
`-- ubuntu14.04.xml

以ubuntu14.04.xml为例

default网络XML