KVM(六)Nova 通过 libvirt 管理 QEMU/KVM 虚机
1. Libvirt 在 OpenStack 架构中的位置
在 Nova Compute 节点上运行的 nova-compute 服务调用 Hypervisor API 去管理运行在该 Hypervisor 的虚机。Nova 使用 libvirt 管理 QEMU/KVM 虚机,还使用别的 API 去管理别的虚机。
libvirt 的实现代码在 /nova/virt/libvirt/driver.py 文件中。
这里是 OpenStack Hypervisor Matrix。
这里是 每个 Linux 发行版里面 libvirt, QEMU/KVM 的版本号。
请注意Juno 版本 Nova 对 libvirt 和 QEMU 的各种最低版本要求:
功能 | 最低 libvirt 版本 | 最低 QEMU 版本 | 不支持的后果 |
所有 | 0.9.11 | Nova 不能使用 libvirt driver | |
支持 device callback |
1.1.1 | 不支持的话,就无法支持 Detach PCI/SR-IOV 设备 | |
Live snapshot | 1.3.0 | 1.3.0 | 只能使用 Clod Snapshot |
挂载卷时设置卷的 block 大小(Block IO) | 0.10.2 | 不能使用的话,就不能设置卷的特定 block size,只能使用其默认的 block size。 | |
Block Job Info | 1.1.1 | 不能在线删除卷的快照 (online deletion of volume snapshots) | |
Discard | 1.0.6 | 1.6.0 |
|
NUMA topology | 1.0.4 | 无法获取 node 的 NUMA topology 信息,就无法将虚机的 vCPU 指定到特定的 node CPU 上,会影响虚机的性能 |
2. Nova 中 libvirt 的使用
Nova 使用 libvirt 来管理虚机,包括:
- 创建虚机
- 虚机的生命周期管理(参考这篇文档)
- 添加和删除连接到别的网络的网卡 (interface)
- 添加和删除 Cinder 卷 (volume)
2.1 创建 QEMU/KVM 虚机
创建虚机的配置有几个来源:
- 用户的选项,包括虚机的基本信息,比如 name,flavor,image,network,disk等。
- image 的属性,比如 hw_vif_model,hw_scsi_model 等。完整的供 libvirt API 使用的属性列表 在这里。
- 管理员在 nova.conf 中的配置
(注意:image 的元数据属性的优先级高于 nova.conf 中的配置。只有在没有property的情况下才使用nova.conf中的配置)
创建虚机的过程的几个主要阶段:
(1)消息由 nova-api 路由到某个 nova compute 节点 (API -> Scheduler -> Compute (manager) -> Libvirt Driver)
(2)调用 Neutron REST API 去准备网络。其返回的数据类似:
[VIF({'profile': {}, 'ovs_interfaceid': u'59cfa0b8-2f5c-481a-89a8-7a8711b368a2', 'network': Network({'bridge': 'br-int', 'subnets': [Subnet({'ips': [FixedIP({'meta': {}, 'version': , 'type': 'fixed', 'floating_ips': [], 'address': u'10.0.10.14'})], 'version': , 'meta': {'dhcp_server': u'10.0.10.11'}, 'dns': [], 'routes': [], 'cidr': u'10.0.10.0/24', 'gateway': IP({'meta': {}, 'version': , 'type': 'gateway', 'address': u'10.0.10.1'})})], 'meta': {'injected': False, 'tenant_id': u'74c8ada23a3449f888d9e19b76d13aab'}, 'id': u'a924e87a-826b-4109-bb03-523a8b3f6f9e', 'label': u'demo-net2'}), 'devname': u'tap59cfa0b8-2f', 'vnic_type': u'normal', 'qbh_params': None, 'meta': {}, 'details': {u'port_filter': True, u'ovs_hybrid_plug': True}, 'address': u'fa:16:3e:e0:30:e7', 'active': False, 'type': u'ovs', 'id': u'59cfa0b8-2f5c-481a-89a8-7a8711b368a2', 'qbg_params': None})]
(3)从 image 启动话,nova 会调用 Glane REST API 后者 image metadata 和准备本地启动盘
image metadata:
{u'status': u'active', u'deleted': False, u'container_format': u'bare', u'min_ram': , u'updated_at': u'2015-04-26T04:34:40.000000', u'min_disk': , u'owner': u'74c8ada23a3449f888d9e19b76d13aab', u'is_public': False, u'deleted_at': None, u'properties': {}, u'size': , u'name': u'image', u'checksum': u'64d7c1cd2b6f60c92c14662941cb7913', u'created_at': u'2015-04-26T04:34:39.000000', u'disk_format': u'qcow2', u'id': u'bb9318db-5554-4857-a309-268c6653b9ff'}
本地启动盘:
{'disk_bus': 'virtio', 'cdrom_bus': 'ide', 'mapping': {'disk': {'bus': 'virtio', 'boot_index': '', 'type': 'disk', 'dev': u'vda'}, 'root': {'bus': 'virtio', 'boot_index': '', 'type': 'disk', 'dev': u'vda'}, 'disk.local': {'bus': 'virtio', 'type': 'disk', 'dev': 'vdb'}, 'disk.swap': {'bus': 'virtio', 'type': 'disk', 'dev': 'vdc'}}}
本地启动盘的文件信息:
root@compute2:/home/s1# qemu-img info /var/lib/nova/instances/-940f--bc01-36220db80639/disk.local
image: /var/lib/nova/instances/-940f--bc01-36220db80639/disk.local
file format: qcow2
virtual size: .0G ( bytes) #由 flavor.ephemeral_disk 指定其 size disk size: 324K
cluster_size:
backing file: /var/lib/nova/instances/_base/ephemeral_1_default
Format specific information:
compat: 1.1
lazy refcounts: false root@compute2:/home/s1# qemu-img info /var/lib/nova/instances/-940f--bc01-36220db80639/disk.swap
image: /var/lib/nova/instances/-940f--bc01-36220db80639/disk.swap
file format: qcow2
virtual size: 30M ( bytes) # 由 flavor.swap_disk 指定其size disk size: 196K
cluster_size:
backing file: /var/lib/nova/instances/_base/swap_30
Format specific information:
compat: 1.1
lazy refcounts: false
(4)根据这些信息,生成 domain xml,然后生成其配置使得它是一个持久性虚机 (调用 libvirt Python DefineXML API)。
一个从 image 启动的 Domain 的配置 XML 实例(蓝色部分是注释说明):
<domain type="qemu">
8352e969-0a25-4abf-978f-d9d0ec4de0cd
instance-0000002f
# guest.memory = flavor.memory_mb * units.Ki 即 * = <vcpu cpuset=""> #flavor.vcpus
<nova:instance xmlns:nova="http://openstack.org/xmlns/libvirt/nova/1.0">
<nova:package version="2014.2.2"/>
vm11 #input.name -- ::
<nova:flavor name="tiny2"> #input.flavor <nova:user uuid="bcd37e6272184f34993b4d7686ca4479">admin
<nova:project uuid="74c8ada23a3449f888d9e19b76d13aab">admin <nova:root type="image" uuid="bb9318db-5554-4857-a309-268c6653b9ff"/> #input.source <sysinfo type="smbios"> # Nova 中写死的
<entry name="manufacturer">OpenStack Foundation
<entry name="product">OpenStack Nova
<entry name="version">2014.2.
<entry name="serial">03bb1a0f-ae04--9f3c-d200a2540675
<entry name="uuid">8352e969-0a25-4abf-978f-d9d0ec4de0cd hvm #表示 Guest OS 需要 full virtualiaiton 支持 <boot dev="hd"/> #指定启动盘 <smbios mode="sysinfo"/> #去读取 的定义 # Soft Reboot 需要 ACPI 的支持,否则只能使用 Hard reboot。 https://bugs.launchpad.net/horizon/+bug/1346741 # 没 APIC 的话,Windows Guest 会在 Xen 或者 KVM 上崩溃。 https://bugs.launchpad.net/nova/+bug/1086352
<clock offset="utc"/> #如果Guest OS 是 MS,则是 localtime,否则都是 utc <cpu mode="host-model" match="exact"> # 对于 KVM,如果 CONF.libvirt.cpu_mode 是 none,mode 则设为 "host-model"。具体可参考 https://wiki.openstack.org/wiki/LibvirtXMLCPUModel <topology sockets="1" cores="1" threads="1"/> #默认的时候,sockets 数目设为 vcpu 的数目,cores 和 threads 都设为 1. 可以通过设置 image 的 hw_cpu_topology 属性来改变这里的设置,具体请参考 https://blueprints.launchpad.net/nova/+spec/support-libvirt-vcpu-topology 以及 https://wiki.openstack.org/wiki/VirtDriverGuestCPUMemoryPlacement <disk type="file" device="disk"> # 从 image 启动时候的启动盘(flavor.root_disk) <driver name="qemu" type="qcow2" cache="none"/>
<source file="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk"/>
<target bus="virtio" dev="vda"/> #对于 KVM,disk 的 bus 为 "virtio",cdrom 的 bus 为 "ide",floppy 的 bus 为 "fdc"
<disk type="file" device="disk"> #临时分区 (falvor.ephemeral_disk) <driver name="qemu" type="qcow2" cache="none"/>
<source file="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk.local"/>
<target bus="virtio" dev="vdb"/> <disk type="file" device="disk"> #swap 分区 (flavor.swap_disk) <driver name="qemu" type="qcow2" cache="none"/>
<source file="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk.swap"/>
<target bus="virtio" dev="vdc"/> <interface type="bridge"> # 虚机通过网桥连接到 OVS <mac address="fa:16:3e:e0:30:e7"/>
<model type="virtio"/> #该 type 可以由 image metadata hw_vif_type 指定。未指定的话,如果配置了 conf.libvirt.use_virtio_for_bridges = true (默认就是 true)的话,QEMU/KVM 会使用 virtio 类型。 <driver name="qemu"/>
<source bridge="qbr59cfa0b8-2f"/> #qbr59cfa0b8-2f 连接虚机的 vNIC tap59cfa0b8-2f 和 qvb59cfa0b8-2f ,而 qvb59cfa0b8-2f 练到 OVS 的 br-int 上。 <target dev="tap59cfa0b8-2f"/>
</interface>
<serial type="file"> 当 CONF.serial_console.enabled = true 时,type 为 "tcp",使用 config 配置,其 XML 为 ;当为 false 时,使用 console.log 文件,type 为 file。 <source path="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/console.log"/> <serial type="pty"/> #每个domain都有 type 为 "pty" 的 serial 配置。 <input type="tablet" bus="usb"/> #当 CONF.vnc_enabled = true 或者 CONF.spice.enabled = true 并且 CONF.spice.agent_enabled = false 时添加 tablet,type 和 bus 都是固定的。 <graphics type="vnc" autoport="yes" keymap="en-us" listen="0.0.0.0"/> #如果 CONF.vnc_enabled = true,那么 keymap=CONF.vnc_keymap;listen=CONF.vncserver_listen #如果 CONF.vnc_enabled 或者 CONF.spice.enabled,则添加该 video 配置 <model type="cirrus"/> #如果 CONF.spice.enabled,则 type 为 qxl;否则为 cirrus。
<memballoon model="virtio"> #如果 CONF.libvirt.mem_stats_period_seconds > 则添加 memballoon;对 KVM,model 固定为 "virtio" <stats period=""/>
从 bootable volume 启动的话,disk 部分为:
<disk type="file" device="disk">
<driver name="qemu" type="qcow2" cache="none"/>
<source file="/var/lib/nova/instances/02699155-940f-4401-bc01-36220db80639/disk.local"/>
<target bus="virtio" dev="vdb"/> <disk type="file" device="disk">
<driver name="qemu" type="qcow2" cache="none"/>
<source file="/var/lib/nova/instances/02699155-940f-4401-bc01-36220db80639/disk.swap"/>
<target bus="virtio" dev="vdc"/> -5a56-4c79-b839-a8e13a66dc7a
(5). 启动 domain (调用 libvirt Python createWithFlags API)
2.2 添加 volume 到虚机 (nova volume-attach)
(1)使用 volume id 通过 volume driver 找到指定的 volume
(2)调用 volume driver 来建立主机和 Volume 之间的连接
主机信息为:
{'ip': '192.168.1.15', 'host': 'compute2', 'initiator': 'iqn.1993-08.org.debian:01:a9f2b45c24f9'}
建立的 iSCSI 连接信息为:
{u'driver_volume_type': u'iscsi', u'data': {u'access_mode': u'rw', u'target_discovered': False, u'encrypted': False, u'qos_specs': None, u'target_iqn': u'iqn.2010-10.org.openstack:volume-51da0d1f-0a17-4e7f-aeff-27438963348a', u'target_portal': u'10.0.2.41:3260', u'volume_id': u'51da0d1f-0a17-4e7f-aeff-27438963348a', u'target_lun': , u'auth_password': u'hXG64qrzEjNt8MDKnERA', u'auth_username': u'fKSAe6vhgyeG88U9kcBV', u'auth_method': u'CHAP'}}
volume 在主机上的磁盘为:
root@compute2:/home/s1# ls /dev/disk/by-path/ -ls
total
lrwxrwxrwx root root Jun : ip-10.0.2.41:-iscsi-iqn.-.org.openstack:volume-51da0d1f-0a17-4e7f-aeff-27438963348a-lun- -> ../../sdc Disk /dev/sdc: MB, bytes
heads, sectors/track, cylinders, total sectors
Units = sectors of * = bytes
Sector size (logical/physical): bytes / bytes
I/O size (minimum/optimal): bytes / bytes
Disk identifier: 0x00000000 Disk /dev/sdc doesn't contain a valid partition table
(3)通过 domain name 来找到指定 domain 对象 (通过调用 lookupByName API)
(4)生成 volume 连接的配置 xml,比如:
51da0d1f-0a17-4e7f-aeff-27438963348a
(5)调用 attachDeviceFlags API 将 volume 挂载到该虚机
2.3 添加连接到新的网络的 interface 给虚机 (nova interface-attach)
(1)运行 nova interface-attach,传入 network-id,Neutron 会分配如下network info 给 Nova
VIF({'profile': {}, 'ovs_interfaceid': u'0142efee-7382-43ef-96e8-d0084ecc893c', 'network': Network({'bridge': u'br-int', 'subnets': [Subnet({'ips': [FixedIP({'meta': {}, 'version': , 'type': u'fixed', 'floating_ips': [], 'address': u'10.0.0.40'})], 'version': , 'meta': {u'dhcp_server': u'10.0.0.3'}, 'dns': [], 'routes': [], 'cidr': u'10.0.0.0/24', 'gateway': IP({'meta': {}, 'version': , 'type': u'gateway', 'address': u'10.0.0.1'})})], 'meta': {u'injected': False, u'tenant_id': u'74c8ada23a3449f888d9e19b76d13aab'}, 'id': u'01630966-b21f-4a6d-95ff-10c4575f1fe2', 'label': u'demo-net'}), 'devname': u'tap0142efee-73', 'vnic_type': u'normal', 'qbh_params': None, 'meta': {}, 'details': {u'port_filter': True, u'ovs_hybrid_plug': True}, 'address': u'fa:16:3e:14:32:d9', 'active': True, 'type': u'ovs', 'id': u'0142efee-7382-43ef-96e8-d0084ecc893c', 'qbg_params': None})
(2)执行下面的命令,将 Neutron 分配的 port 连接到 OVS
#添加 linux bridge
brctl addbr qbr0142efee- #名字是 devname 的后半部分 brctl setfd qbr0142efee- brctl stp qbr0142efee- off
tee /sys/class/net/qbr0142efee-/bridge/multicast_snooping ip link add qvb0142efee- type veth peer name qvo0142efee- ip link set qvb0142efee- ip link set qvb0142efee- promisc on #在 OVS 上添加端口
ovs-vsctl --timeout= -- --if-exists del-port qvo0142efee- -- add-port br-int qvo0142efee- -- set Interface qvo0142efee- external-ids:iface-id=0142efee--43ef-96e8-d0084ecc893c external-ids:iface-status=active external-ids:attached-mac=fa::3e:::d9 external-ids:vm-uuid=8352e969-0a25-4abf-978f-d9d0ec4de0cd
(3)生成 interface 配置的xml,比如:
(4)调用 attachDeviceFlags API 来挂载该 interface 到虚机
至于其他的虚机操作,会在另一篇文章中描述。
KVM(六)Nova 通过 libvirt 管理 QEMU/KVM 虚机的更多相关文章
- KVM 介绍(6):Nova 通过 libvirt 管理 QEMU/KVM 虚机 [Nova Libvirt QEMU/KVM Domain]
学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...
- KVM 介绍(8):使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机 [Nova Libvirt QEMU/KVM Live Migration]
学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...
- KVM 介绍(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照 (Nova Instances Snapshot Libvirt)
学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...
- KVM(七)使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照
本文将梳理 QEMU/KVM 快照相关的知识,以及在 OpenStack Nova 中使用 libvirt 来对 QEMU/KVM 虚机做快照的过程. 1. QEMU/KVM 快照 1.1 概念 QE ...
- KVM(八)使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机
1. QEMU/KVM 迁移的概念 迁移(migration)包括系统整体的迁移和某个工作负载的迁移.系统整理迁移,是将系统上所有软件包括操作系统完全复制到另一个物理机硬件机器上.虚拟化环境中的迁移, ...
- qemu 对虚机的地址空间管理
转载:http://huchh.com/2015/06/22/qemu-%E5%AF%B9%E8%99%9A%E6%9C%BA%E7%9A%84%E7%BA%BF%E6%80%A7%E5%9C%B0% ...
- Guest CPU model configuration in libvirt with QEMU/KVM
每个hypervisor对于guest能看到的cpu model定义都不同,Xen 提供host pass through,所以guest能看到的cpu和host完全相同. QEMU/KVM中gues ...
- KVM虚拟机IO处理过程(二) ----QEMU/KVM I/O 处理过程
接着KVM虚拟机IO处理过程中Guest Vm IO处理过程(http://blog.csdn.net/dashulu/article/details/16820281),本篇文章主要描述IO从gue ...
- [daily][qemu][libvirt] 使用libvirt管理qemu
别人创建的虚拟机.用libvirt做的配置. 我一直是手写qemu脚本的,不会用virtsh,所以,学一下. ------------------ 先来个arch的文档: https://wiki.a ...
随机推荐
- 软工实践 - 第二十八次作业 Beta 冲刺(6/7)
队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10146478.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...
- iOS-SDWebImage的原理以及使用流程
SDWebImage 支持异步的图片下载+缓存,提供了 UIImageView+WebCacha 的 category,方便使用.SDWebImage加载图片的流程: 1. 入口 setImageWi ...
- 算法(10)Subarray Sum Equals K
题目:在数组中找到一个子数组,让子数组的和是k. 思路:先发发牢骚,这两天做题是卡到不行哇,前一个题折腾了三天,这个题上午又被卡住,一气之下,中午睡觉,下午去了趟公司,竟然把namespace和cgr ...
- 文件系统中 atime,lazytime,relatime 详聊
atime,ctime,mtime是文件inode的三个时间戳,分别表示文件最近一次的访问时间:inode本身的更改(changed)时间:文件数据的更改(modify)时间:这几个概念还是很好区分. ...
- BZOJ1095 [ZJOI2007]Hide 捉迷藏 【动态点分治 + 堆】
题目链接 BZOJ1095 题解 传说中的动态点分治,一直不敢碰 今日一会,感觉其实并不艰涩难懂 考虑没有修改,如果不用树形dp的话,就得点分治 对于每个重心,我们会考虑其分治的子树内所有点到它的距离 ...
- POJ2774 Long Long Message 【后缀数组lcp】
长长的消息 时间限制: 4000MS 内存限制: 131072K 提交总数: 32393 接受: 13079 案件时间限制: 1000MS 描述 小猫在拜特兰的首府物理专业.最近有一个不幸的消 ...
- 如何配置开源中国Maven库以加快依赖包下载速度
有时有某些地方由于网络问题,访问maven主仓库比较慢,甚至有可能无法下载某些jar包,此时可以把开源中国Maven库配置到settings.xml文件中,加快依赖包的下载速度. 具体如何配置? 在m ...
- 2016广东工业大学校赛 E题 GDUT-oj1173
Problem E: 积木积水 Description 现有一堆边长为1的已经放置好的积木,小明(对的,你没看错,的确是陪伴我们成长的那个小明)想知道当下雨天来时会有多少积水.小明又是如此地喜欢二次元 ...
- PHP设计模式-工厂模式、单例模式、注册模式
本文参考慕课网<大话PHP设计模式>-第五章内容编写,视频路径为:http://www.imooc.com/video/4876 推荐阅读我之前的文章:php的设计模式 三种基本设计模式, ...
- c++(类) this指针
this指针的相关概念: this只能在成员函数中使用.全局函数,静态函数都不能使用this.实际上,成员函数默认第一个参数为T* const register this. 为什么this指针不能再静 ...