说明:

  1. 本文所提到的所有配置均针对KVM节点的配置
  2. 本文适用读者对象为:尝试过Opennebula搭建,但是在部署过程中存在一定疑惑,并对其中部分概念不是很清晰的

Opennebula的基本架构

Opennebula的架构中,服务器分为两类,分为FrontendNode两类。其中Frontend相当于主控节点,承担所有节点的协调,虚拟机的分配等。Node相当于工作节点,承担具体的虚拟机的工作任务。对于安装配置过程中,涉及到两个比较重要的问题,就是存储与网络。

Opennebula的重要基本概念与理解

OpenNebula的存储分类

OpenNebula的存储分为三种类型,分别为image, systemfiles。对于普通用户来说,接触最多的应该是imagesystem这两个。image类型的存储保存的是虚拟机的模板。system类型保存的是虚拟机运行时的本地磁盘。files用来保存一些opennebula运行是配置的文件,完全不需要管它,另外对于空间要求也不高。

对于系统的配置安装来说,image类型的存储只对Frontend节点有意义,即只有Frontend节点会访问image存储,并把image存储中的虚拟机镜像拷贝至对应的工作节点的system存储中。因此,对于image类型的存储可以只要frontend节点可以访问即可,可以采用NFS, Ceph等网络共享存储,也可以采用本机存储。

对于system类型来说,存储的是vm的运行是磁盘,是Node节点访问的存储。因此,对于system类型的存储来说,需要保证Node节点的访问。对于Node节点来说,system类型的存储可以选择本地存储,也可以选择网络存储。对于system类型的存储,Opennebula的定义的类型包括三类:1)shared,即所有的节点(包括FrontendNode节点)都必须通过可以共享的访问方式,例如NFS,挂载到统一的路径。2)ssh,所有的Node节点使用本地磁盘[1]作为system存储,Frontend通过SSH的方法把镜像拷贝至Node节点。3)qcow2,与shared相同,只是专门为qcow2优化过。

说明: 对于ssh类型的数据来说,实际上只要保证对应挂载点有足够的空间就行。不一定非要限制为本地磁盘。但是通过将ssh类型限制为本地磁盘可以提供更好的磁盘读写速度,例如可以用于数据库的磁盘系统。

综上,对于system的不同类型,其特点如下表所示:

类型 磁盘类型 说明
shared 必须为网络存储,例如NFS 所有节点上(FrontendNode)的挂载点都必须相同
ssh 每台Node自己管理的磁盘 只要保证有足够的存储空间可以满足虚拟机分配时所需要的磁盘空间即可。但需要满足opennebula对于磁盘挂载点的要求

OpenNebula的网络类型

和其他的云计算平台一样,Opennebula的网络配置选项较多,但不代表他的网络配置复杂。尤其对于KVM节点来说,实际上还是比较简单的。对于KVM节点,Opennebula提供了bridgedvlanvxlanopen vswitchopen vswitch on vxlan的多种选择。对于企业级中小型的部署来说,从目前来看,我个人认为bridgedvlan两种类型足够了。以下重点说一下bridgedvlan两种类型。

从概念理解上来说,bridgedvlan和VMWare Workstation以及Virtualbox中提供的桥接功能是一样的,即虚拟机通过网络设备桥接的形式直接连接物理网络。区别是,bridged网络需要用户手动在所有的Node上配置网桥,并且在配置网络的时候,将bridged类型的网络设定制定的网桥设备即可。例如下面这个图:

Screenshot_20200331_163619.png

对应一个bridged类型的网络,为了满足这个要求,需要在所有的节点上配置一个名字为br1的网桥设备。

而对于vlan来说,配置也比较简单,只需要选择对应的物理网卡即可。例如,对于下面的这个图

Screenshot_20200331_164357.png

只要保证所有的Node节点都存在名字为eno1的物理网卡即可。Opennebula可以根据这个配置自动的生成对应的vlan的配置,那么所有分配给这个网络的虚拟机会使用对应的vlan进行通信。

对于小型部署来说,bridgedvlan都可以使用。对于vlan的配置来说,需要支持vlan的交换机,适用于需求更为复杂的网络规划。对于bridged来说,对交换机没有任何要求,但是对于复杂的网络隔离需求只能通过在核心交换机或者配置更多的路由器或者通过Opennebula提供的Virtual Router功能来解决。总体来说,我个人更倾向于使用bridged的网络配置方式。

操作系统的存储与网络配置

存储与挂载点配置

对于Opennebula中的存储,当在通过Frontend添加一个存储,会为这个存储分配一个相应的id,这个id一般是一个编号,同时在/var/lib/one/datastores文件夹下面建立一个名字为/var/lib/one/datastores/<id>的文件夹,用来实际存储文件。例如,当Opennebula初步建立时,会默认建立id为0,1,2的三个存储,分别对应一个默认的systemimagefile类型。他们会分别对应在/var/lib/one/datastores文件夹下面的0,1,2三个子文件夹。

那么,如何新增一个存储呢。对于sharedssh两个类型,完全有两个不同的做法。分别如下:

  1. 新增shared类型。假定新增的shared类型的存储的id为101。那么,必须要保证所有节点下的 /var/lib/one/datastores/101 文件夹指向同一个共享的网络存储,例如NFS或者Ceph或者其他网络存储服务。
  2. 新增ssh类型。假定新增的ssh类型的存储的id为102。那么,只要在Node节点中保证/var/lib/one/datastores/102文件夹下边有足够的存储空间即可。例如,可以采用LVM+XFS的方法挂载一个设备在对应文件夹下边。

提示: 对于通过ssh添加的本地磁盘来说,底层的文件系统方案可以考虑采用LVM+XFS的方案。LVM可以不停的添加新磁盘,XFS可以在线调整容量,并且XFS对于大文件的存储更有优势,对提供本地的VM磁盘存储是比较好的选择。

重要: 对于shared类型的System storage,必须配置一个类型为shared的image storage,否则无法在shared system storage上创新虚拟机,ssh image storage是无法把镜像拷贝到shared system storage上的!。

网络配置

bridged网络Ubuntu Server 18.04节点配置示例

假定有一台Ubuntu Server作为Node,配备了两个网卡,分别为eno0eno1。现在考虑,对于eno0作为数据FrontendNode之间的配置通信,eno1采用bridged方式为虚拟机之间提供网络通信。那么对于Node节点中Ubuntu的Netplan配置示例如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  version: 2
  renderer: networkd
  ethernets:
    eno0:
      addresses: [10.0.0.1/16]
      gateway4: 10.0.0.254
      nameservers:
        addresses: [8.8.8.8, 114.114.114.114]
    eno1:
      dhcp4: no
      dhcp6: no
  bridges:
    br0:
      interfaces: [eno1]
      dhcp4: no
      dhcp6: no

在这个配置中,eno0用作opennebula集群的通信,eno1用于虚拟机之间的通信。

Opennebula安装要点

安装前操作系统的配置

安装前操作系统需要完成的网络的配置和MySQL的安装配置。网络配置需要完成1)主要需要参考网络配置小节的配置完成对网桥的配置。2)在没有DNS的情况下,需要配置hosts文件,实现所有节点之间可以通过主机名进行访问。

另外,对于其他方面,对于生产环境需要完成对MySQL/MariaDB的安装配置。

安装过程

安装过程比较简单。参考官方文档,分为以下几个步骤:

配置软件源

Ubuntu 18.04配置过程如下:

导入key

1
wget -q -O- https://downloads.opennebula.org/repo/repo.key | apt-key add -

配置软件源

1
echo "deb https://downloads.opennebula.org/repo/5.8/Ubuntu/18.10 stable opennebula" > /etc/apt/sources.list.d/opennebula.list

安装软件

对于Frontend节点,安装如下软件:

1
apt-get install opennebula opennebula-sunstone opennebula-gate opennebula-flow

对于Node节点,安装如下软件:

1
apt-get install opennebula-node

安装后操作系统需要的配置

添加节点前需要完成的安装配置

Opennebula安装完成后,会在系统里建立oneadmin的用户。并通过oneadmin用户使用ssh进行所有节点间的通信工作。因此,需要配置Frontend节点对于所有Node节点的无密码ssh访问。

添加节点后需要完成的配置

添加节点后可能需要动态的进行配置的调整。主要需要进行的调整是需要将系统的中的磁盘动态的按照存储与挂载点配置小节所述,进行磁盘挂载点的动态调整。

Opennebula的配置与调优

基础VM配置的调整

参考https://storpool.com/blog/vm-performance-optimization-for-opennebula-with-kvm,对安装后的系统进行一些配置调优。

这其中,比较合适的调整为:

1、调整创建默认虚拟机的Feature。将/etc/one/vmm_exec/vmm_exec_kvm.conf中 的

1
FEATURES = [ PAE = “no”, ACPI = “yes”, APIC = “no”, HYPERV = “no”, GUEST_AGENT = “no”, VIRTIO_SCSI_QUEUES = “0” ]

调整为

1
FEATURES = [ PAE = “no”, ACPI = “yes”, APIC = “no”, HYPERV = “no”, GUEST_AGENT = “yes”, VIRTIO_SCSI_QUEUES = “0” ]

注意: 这一项调整主要是针对Opennebula的Marketplace下载的镜像进行的。如果使用自定义镜像,只有在镜像的系统中安装了qemu-guest-agent软件包的镜像才有意义。

2、调整创建默认虚拟机的磁盘配置。将/etc/one/vmm_exec/vmm_exec_kvm.conf中的

1
DISK = [ driver = “raw” , cache = “none”]

内容调整为

1
DISK = [ driver = “raw” , cache = “none” , io = “native” , discard = “unmap” ]

这项调整的含义为,默认建立的虚拟机的 默认磁盘(即系统盘) 的格式使用raw格式,不使用cache,使用linux系统内置原生的AIO进行io操作,同时采用unmap,将trim下沉到底层磁盘,unmap的设置对于SSD硬盘特别重要!

3、调整默认的网卡驱动为virtio。将/etc/one/vmm_exec/vmm_exec_kvm.conf中对应的

1
#NIC     = [ model=”virtio” ]

去掉注释,修改为

1
NIC     = [ model=”virtio” ]

VM的开机自启动

Opennebula比较坑的一点是对于节点重启后VM的自动启动,官方一直没有加入这个功能,需要通过自己写Opennebula的hook来完成。opennebula在5.10之后,启用了新的hook api,之前的hook脚本不兼容。在新的api中,传递给VM Hook的参数是$template,是VM的XML文件。因此,需要自己写一个处理的脚本。对于开启自动的配置过程如下:

1、编写恢复虚拟机操作的脚本。

将如下内容写入/usr/local/bin/vmresume.py文件,并赋予可执行权限。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/env python3

import sys
from base64 import b64decode
import xml.etree.ElementTree as ET
import subprocess

vm = ET.fromstring(b64decode(sys.argv[1]))
vm_id = vm.find("./ID")

if vm_id is not None:
    subprocess.run(["/usr/bin/onevm", "resume", vm_id.text])

该脚本通过解析传入的XML文件,获取虚拟机id,并通过onevm resume命令完成对虚拟机的恢复。

2、创建两个VM状态变化hook文件

首先,创先文件/var/lib/one/hooks/node_restart,其内容为:

1
2
3
4
5
6
7
8
NAME            = autostart_vm_on_node_restart
RESOURCE        = VM
TYPE            = state
COMMAND         = "/usr/local/bin/vmresume.py"
ARGUMENTS       = "$TEMPLATE"
STATE           = POWEROFF
LCM_STATE       = LCM_INIT
ON              = CUSTOM

其次,创建文件/var/lib/one/hooks/cluster_restart,其内容为:

1
2
3
4
5
6
7
8
NAME            = autostart_vm_on_cluster_restart
RESOURCE        = VM
TYPE            = state
COMMAND         = "/usr/local/bin/vmresume.py"
ARGUMENTS       = "$TEMPLATE"
STATE           = ACTIVE
LCM_STATE       = UNKNOWN 
ON              = CUSTOM

然后通过onehook create /var/lib/one/hooks/node_restartonehook create /var/lib/one/hooks/cluster_restart两个命令,将对应的hook添加至系统中。

这两个hook中,第一个对应节点服务器重启可能出现的VM状态,第二个对应整个集群重启可能出现的VM异常状态,目前,我在使用时只遇到过以上两种VM的异常状态。如果发现其他状态,可以以此类推,自己添加其他状态的Hook