基于Nomad的Libvirt虚拟机运行时设计与实现(3)

831 阅读6分钟

3.3.1 Libvirt虚拟机运行时关键技术实现

3.3.1.1 驱动配置解析及加载

将nomad-driver-libvirt驱动插件项目编译放入驱动加载文件夹下。如图3.8所示,在Nomad Client配置中新增并解析libvirt插件配置。libvirt公共API将其实现委托给一个或多个内部驱动程序,具体取决于初始化库时传递的连接URI,例如qemu:///system。如果libvirt守护程序可用,且有一个虚拟机监控程序处于活动状态,通常将有一个网络和存储驱动程序处于活动状态。

image.png

图3.8  nomad-driver-libvirt驱动插件配置

如图3.9所示,从Nomad Client日志中驱动插件以加载,Fingerprint健康检查正常。

image.png

图3.9  nomad-driver-libvirt驱动插件加载及Fingerprint

3.3.1.2 虚拟机生命周期管理

虚拟机运行时作业负载中包含了虚拟机任务组,任务组中包含的任务的生命周期管理需要实现运行时驱动接口,而更底层封装的是虚拟机的生命周期。

Libvirt能够控制域即虚拟机的整个生命周期。域可以在它的整个生命周期的几个状态之间进行转换:

(1)Undefined是一个基本的状态,任何没有定义或者没有建立的域的状态。

(2)Defined是域已定义但是没有运行的状态,这种状态也可以被描述为停止。

(3)Running是已经定义并运行在一个Hypervisor上面的域的状态。

(4)Paused是形容一个域系统从运行转换为暂停的状态。它的内存镜像已经被暂时地存储,它可以恢复到运行状态。

(5)Saved可以将一个域持久化,并再次恢复。

image.png

图3.10  域生命周期的状态图

域的生命周期比较详细,在上一层Libvirt虚拟机运行时包装里,本文减少了一些状态,提供了从配置文件创建虚拟机、停止虚拟机、删除虚拟机、虚拟机状态查询,以及事件监听和数据采集等接口抽象,如图3.11所示。

image.png

图3.11  虚拟机管理抽象接口

3.3.1.3 虚拟机任务配置

虚拟机任务配置由Libvirt虚拟机运行时定义和解析,沿用HCL格式,嵌套在原Nomad作业定义的task节部分。如表3.1所示,需要说明例如task.driver是指task域中的driver字段。

表3.1  虚拟机任务配置

字段
task.driverlibvirt,字符串
task.config.name任务名,字符串,例如centostask
task.config.memory.value虚拟机内存大小,整形,例如1
task.config.memory.unit内存描述的单位,字符串,有gib、mib、kib、b
task.config.vcpu虚拟机的虚拟CPU,整形,例如1
task.config.disks磁盘存储,列表类型
task.config.disks[0].device磁盘设备,字符串,有disk、lun、floppy、cdrom
task.config.disks[0].type文件类型,字符串,device为disk时有file、block
task.config.disks[0].source虚拟机镜像地址,字符串,例如/var/lib/libvirt/images/centos.qcow2
task.config.disks[0].target_bus总线,字符串,有virtio、sata、scsi、fdc
task.config.machine虚拟的硬件机器类型,字符串,例如pc-i440fx-2.12
task.config.interfaces列表类型,网络接口配置,实现了设备透传
task.config.interfaces[0].name指定虚拟机内部网络接口名,字符串,例如eth0
task.config.interfaces[0].model网络适配器类型,字符串,例如virtio、e1000、rtl8139
task.config.interfaces[0].interface_binding_method网卡绑定方式,字符串,有virtio、slirp、sriov、bridge、masquerade、network
task.config.interfaces[0].pci_address网卡设备透传时指定的PCI地址,字符串,如0000:00:1c.3
task.config.interfaces[0].mac_address指定网卡MAC地址,字符串,例如52:54:00:a5:ef:66
task.config.interfaces[0].source_name字符串,例如NAT网络设置default,Bridge网络指定网桥br0

作业提交到Nomad Server后会分配到具有Libvirt虚拟机运行时的Nomad Client执行作业,以上HCL定义的作业再转交给Libvirt虚拟机运行时解析,过程中被转换为XML格式发给Libvirt守护进程具体执行。

3.3.1.4 虚拟机运行时网络管理

Libvirt虚拟机运行时设计上支持NAT和Bridge两种网络方式。

KVM安装后的默认网络是NAT方式,宿主机上会有一个virbr0虚拟接口(即NAT方式里面的default虚拟网络),并有一块virbr0-nic的虚拟网卡,也是一个switch和bridge,负责把内容分发到各虚拟机。virbr0是一个网桥,默认接收所有到网络192.168.122.0/24的内容。virbr0并未直接绑定到实际的物理网卡,数据包经过virbr0,进行网络地址解析,IP包转发后从实际的物理网络设备出去。在NAT模式下,需要在宿主机上运行一个DHCP服务器给内网的机器分配IP地址,可以使用dnsmasq工具实现。

NAT网络实现,如图3.12所示,虚拟接口和物理接口之间没有连接关系,所以虚拟机只能在通过虚拟的网络访问外部世界,无法从网络上定位和访问虚拟主机。

image.png

图3.12  nomad-driver-libvirt NAT网络模型

以创建虚拟机为例,网络相关的创建流程:

1. 修改内核参数允许IP数据包转发。

2. 定义NAT虚拟网络,包含IP段范围。

3. 启动NAT网络,修改iptables规则。主机系统负责进行SNAT。

4. DNS/DHCP 的实现,本地宿主机通过启动一个dnsmasq来负责管理。

5. 宿主机创建iptables规则负责进行SNAT。

6. 创建虚拟机,指定虚拟网络类型virtio,并选用上述NAT网络。

7. 虚拟机启动,采取DHCP协议向dnsmasq请求动态配置IP。

 

Bridge网络实现,如图3.13所示,创建一个桥接接口br0,将这个网桥绑定到物理网卡eth0上并分配一个对外的地址,此时br0就成为了交换机设备,再将对应的虚拟机网络设备绑定到该虚拟网桥的一个端口上,在物理网卡和虚拟网络接口之间传递数据。

image.png

图3.13  nomad-driver-libvirt桥接网络模型

以创建虚拟机为例,网络相关的创建流程和上述NAT模式类似,略有区别:

1. 编辑修改网络设备脚本文件,创建网桥设备br0。

2. 为网桥启用生成树协议。

3. 为网桥br0设置IP获取式动态或静态配置。

4. 修改服务启动顺序,桥接方式虚拟网卡需要在宿主机网卡启动之前启动。

5. 修改网卡设备eth0,禁用NetworkManager服务,该服务不支持桥接。

6. 重启网络服务

7. 创建虚拟机,DHCP动态配置IP。

 

以上有关Libvirt虚拟机运行时创建虚机后动态获取IP,需要在虚拟机镜像中提前安装好qemu-guest-agent,实现是通过使用QEMU Guest Agent协议与虚拟机中的该客户端通信,执行命令guest-network-get-interfaces,来获取客户机的虚拟机IP地址、MAC地址、子网掩码等信息。获取虚拟机IP之后,用户可以通过SSH登陆进行操作。