在OpenStack中那些很少见但很有用的操作中介绍了一些很少提及但很有用的功能,本文在此基础上介绍几个OpenStack的几个高级特性。这里所谓的高级特性,是指那些非人人都需要的OpenStack通用默认配置,而是专门针对一些特定场景需求设定的。
通常情况下,当用户删除虚拟机时,虚拟机会立即从hypervisor底层删除,不可撤回。为了防止人为误操作,Nova支持开启软删除(soft delete)功能,或者称为延迟删除,延迟删除时间通过Nova配置项/etc/nova/nova.conf
的reclaim_instance_interval
项指定,如下:
为了演示该功能,我们删除一台虚拟机int32bit-test-2
:
通过nova list
命令并指定--deleted
选项可以列出已删除的所有虚拟机实例:
可见,刚刚删除的虚拟机已经恢复了。
注意如果管理员通过nova force-delete
命令强制删除虚拟机,虚拟机会立即从底层删除而无视延迟时间。
需要注意的是,由于这个功能早期设计的缺陷,开启虚拟机软删除功能必须保证所有计算节点和API节点配置一样并且时间同步,并且所有节点的延迟时间不可动态修改,这非常不灵活。我在我们内部私有云二次开发中改善了该功能,延时时间不再通过配置文件指定,而是通过虚拟机的admin metadata指定,这样就不再依赖于各个节点的配置项的同步与更新,并且可随时调整延时时间。
OpenStack K版本引入了许多CPU高级特性功能,不仅支持自定义CPU拓扑功能,支持设置虚拟机CPU的socket、core、threads等,还支持CPU pinning功能,即CPU核绑定,甚至能够配置虚拟机独占物理CPU,虚拟机的vCPU能够固定绑定到宿主机的指定pCPU上,在整个运行期间,不会发生CPU浮动,减少CPU切换开销,提高虚拟机的计算性能。除此之外,OpenStack还支持设置threads policy,能够利用宿主机的SMT特性进一步优化虚拟机的性能。
接下来简单介绍下如何配置OpenStack的CPU高级特性。
在配置之前,首先需要规划计算节点的CPU和内存,哪些CPU分配给虚拟机,哪些CPU给宿主机本身的进程预留,预留多少内存等。为了性能的最优化,还需要考虑宿主机CPU的NUMA架构。
由以上信息可知,该宿主机一共两个CPU(socket),每个CPU 10核(core),每个核可以开启两个超线程(thread),即一共有40个逻辑CPU,包含两个NUMA node,其中node0包括0,2,4,...,38,node1包括1,3,5,...,39。
预留CPU个数和内存需要根据实际情况调整,比如若计算节点和存储节点融合,则需要预留更多的CPU来保证存储服务的性能。
本例子仅作为测试使用,测试环境预留了4个逻辑CPU(1-3)和4GB物理内存给宿主机,剩下的资源全部分配给虚拟机使用。
配置虚拟机使用的CPU集合(cpuset)是通过计算节点的vcpu_pin_set
配置项指定,目前支持以下三种语法格式:
^
表示排除的CPU号,剩下的全部作为虚拟机使用。以上三种语法格式可以组合使用。
isolcpu
来限制其他进程使用指定的CPU。比如我们需要把CPU 2,3,6,7作为CPU pinning给虚拟机独占,设置如下:AggregateInstanceExtraSpecFilter
和NUMATopologyFilter
这两个filter:在实际环境中肯定不是所有的计算节点都开启这些高级功能,并且CPU特性也有差别,我们可以通过主机集合(host aggregate)把所有相同的CPU配置放到一个集合中,通过主机集合(host aggregate)区分哪些计算节点开启CPU核绑定功能,哪些不开启。
pinned=true
元数据的请求就会自动从包含pinned=true
元数据的主机中调度。目前Nova并不支持启动时直接指定主机集合的metadata(hint只支持指定server group),需要通过flavor的extra specs配置,并与主机集合的metadata匹配,不匹配的主机将被过滤掉,不会被选择作为候选主机。
flavor支持很多内置的extra specs,通过内置extra specs,可以配置虚拟机的CPU拓扑、QoS、CPU pinning策略、NUMA拓扑以及PCI passthrough等,更详细的介绍可参考官方文档。这里我们只关心CPU拓扑和核绑定功能。
如下是设置CPU topology的语法,自定义CPU的socket数量、core数量以及超线程数量:
CPU-POLICY
合法值为shared
、dedicated
,默认为shared
,即不进行CPU核绑定,我们需要把这个值设置为dedicated
。CPU-THREAD-POLICY
和SMT有关,合法值为:通常设置成默认值prefer
或者isolate
即可。
接下来开始创建flavor,设置为8个CPU、2GB内存以及20GB磁盘空间:
nova show
命令查看虚拟机所在的宿主机,在该宿主机上查看虚拟机的xml文件:306abd22-28c5-4f91-a5ce-0dad03a35f4
为虚拟机的uuid。2 sockets * 2 cores * 2 threads
)。默认情况下我们创建的KVM虚拟机的CPU特性中没有包含vmx,这意味着不能在虚拟机中再创建开启KVM硬件加速的虚拟机,即不支持虚拟化嵌套。值得庆幸的是,目前除了VirtualBox(题外话:VirtualBox在9年前就有人提出要支持嵌套,只是一直没有实现,参考ticket #4032),主流的hypervisor比如VMware、KVM、Xen都支持已经虚拟化嵌套。也就是说,我们可以实现在支持KVM的宿主机创建同样支持KVM的虚拟机。
N
则表明没有开启KVM嵌套功能,可以通过修改/etc/modprobe.d/kvm-intel.conf
配置文件开启该功能:OpenStack支持虚拟化嵌套,修改计算节点的nova配置文件/etc/nova/nova.conf
,设置cpu_mode = host-passthrough
,然后重启nova-compute服务即可。
需要注意的是,使用host-passthrough
的虚拟机迁移功能受限,只能迁移到相同配置的宿主机。
虚拟机的虚拟硬盘默认使用半虚拟化驱动virt-blk,此时硬盘在虚拟机的设备名称形如/dev/vda
、/dev/vdb
等。
事实上,virt-blk
有点老了,其本身也存在许多问题,比如:
virt-blk
的存储设备和PCI设备一一对应,而我们知道系统中至多可以有32个PCI总线,这说明虚拟机最多可以挂32个虚拟硬盘。virt-blk
的设备名称为vd[a-z]
,而现代的物理机通常都会使用SCSI控制器,设备名称为sd[a-z]
,这意味着物理机迁移到虚拟机中可能存在问题,比如fstab中使用的设备名挂载而不是uuid,系统就会起不来。virtio-blk
不支持discard
特性,关于discard
特性后面讲。因此,建议使用virtio-scsi
半虚拟化驱动代替virtio-blk
,这是因为:
sd[a-z]
),解决了前面提到的物理机和虚拟机设备名不一样的问题。256 * 16384 == 4194304
个虚拟机硬盘,这100%足够了。discard
特性。前面提到块设备的discard
特性,这个主要和精简置备有关,就拿Ceph RBD说,我们知道当我们分配一个20GB的image时,Ceph并不会真正分配20GB的存储空间,而是根据需要逐块分配,这和Linux的sparse稀疏文件的原理是一样的,这个特性节省了物理存储空间,实现了硬盘的超售。然而,Ceph只知道上层文件系统需要空间时就分配,而并不知道上层文件系统如何使用存储资源的(实际上也不关心)。而实际上,我们的文件系统肯定是频繁创建文件、删除文件的,删除文件后按理说是可以释放物理存储资源的,然而Ceph并不知道,所以不会回收,占据的存储空间会越来越多,直到空间达到真实的分配空间大小(20GB),而文件系统层可能并没有真正使用那么多空间,这就造成了存储空间利用率下降的问题。比如,我们创建了一个5GB的文件,Ceph底层会分配5GB的空间,此时我们把这个5GB的文件删除,分配的这5GB空间并不会释放。好在Linux支持fstrim
,如果块设备支持discard
特性,文件系统会发送flush通知给底层块设备(RBD),块设备会回收空闲资源。Sébastien Han写了一篇博客关于ceph discard的,参考ceph and krbd discard。
正如前面所言,virt-blk
是不支持discard
的,而virt-scsi
支持,所以如果关心底层存储的空间利用率,建议使用virt-scsi
,并在挂载设备中指定discard
参数(或者写到fstab
中):
virio-scsi
相对virtio-blk
IO路径会更复杂,性能可能会有所下降,参考virtio-blk vs virtio-scsi。mount
命令挂载虚拟硬盘时开启discard
特性会降低文件系统的读写性能。前面讲了那么多关于virio-blk
以及virtio-scsi
,那怎么在OpenStack中使用virtio-scsi
呢?很简单,只需要设置Glance镜像的property
就可以了:
virtio-scsi
驱动,挂载新的Cinder volume也会默认使用virtio-scsi
驱动。需要注意的是,制作OpenStack镜像时一定要保证initrd中包含virtio-scsi驱动,否则操作系统会由于在初始化时不识别SCSI块设备导致启动失败:
/etc/sysconfig/kernel
文件,配置INITRD_MODULES
参数:/dev/sda
,则说明使用的是virtio-scsi
驱动。我们都知道OpenStack虚拟机启动时是通过cloud-init完成初始化配置的,比如网卡配置、主机名配置、注入用户密码等。而虚拟机启动之后处于运行状态时,外部如何与虚拟机通信呢,这就是qemu-guest-agent要完成的事,这其实在如何构建OpenStack镜像一文中已经介绍过,这里直接搬过来。
qemu-guest-agent是运行在虚拟机的一个daemon服务,libvirt会在宿主机本地创建一个unix socket,并模拟为虚拟机内部的一个串口设备,从而实现了宿主机与虚拟机通信,这种方式不依赖于TCP/IP网络。
如下是开启qemu-guest-agent的虚拟机xml配置信息:
org.qemu.guest_agent.0.instance-00003c2c.sock
,在虚拟机内部映射为/dev/virtio-ports/org.qemu.guest_agent.0
。通过这种方式,宿主机只要发送指令到该socket文件中就会在虚拟机对应的串口设备中收到,虚拟机内部的qemu-guest-agent会轮询查看这个串行设备是否有指令,一旦接收到指令就可以执行对应的脚本,从而实现了宿主机控制虚拟机执行命令的功能,其中最常用的指令就是通过libvirt修改虚拟机密码。更多关于qemu-guest-agent请参考官方文档。
首先在制作镜像时需要安装qemu-guest-agent服务:
hw_qemu_guest_agent
property:nova set-password <server>
子命令验证修改虚拟机的密码功能。需要注意的是,Nova默认修改的是管理员用户的密码,Linux系统为root
,Windows系统为Administrator
,因此上传镜像时需要指明镜像是什么操作系统类型:
os_admin_user
属性配置修改其他用户的密码,比如配置修改密码时指定用户不是root,而是ubuntu用户:默认情况下网卡中断由单个CPU处理,当有大量网络包时单个CPU处理网络中断就可能会出现瓶颈。通过网卡多队列技术可以把网卡的中断分摊到多个CPU中。阿里云官方文档测试表明在网络PPS和网络带宽的测试中,与1个队列相比,2个队列最多可提升50%到1倍,4个队列的性能提升更大。
OpenStack支持配置网卡多队列(要求内核版本大于3.0),配置方法如下:
ethtool
工具修改配置:irqbalance
服务:在一些分布式集群中,我们可能期望虚拟机crash时自动关机,防止出现集群脑裂。或者当负载过高时自动执行重启,使服务恢复正常。
OpenStack支持配置虚拟watchdog,首先制作镜像时需要安装并开启watchdog服务:
reset
: 强制重启。shutdown
: 安全关机。poweroff
: 强制关机。pause
: 停止虚拟机。参考官方文档可以查看更详细的配置。
OpenStack从Q版本开始支持GPU虚拟化,由于测试环境中没有GPU,因此本文仅参考官方文档描述配置过程。
首先在安装有GPU(假设为nvidia-35)的计算节点中修改nova配置文件:
resources:VGPU=1
extra specs指定虚拟GPU个数:需要注意的是,如果使用libvirt driver,对于分配了vGPU的虚拟机:
如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!
赞5
添加新评论1 条评论
2019-03-05 14:58