网络作者以上四个问题为切入点,结合 Kilo 版本 Nova 源码,对问题进行了分析解答,现收集如下.
在默认 Hypervisor 为 Qemu-kvm 的前提下(不同 Hypervisor 的资源统计方式差别较大 ),揭开 OpenStack 统计资源和资源调度的面纱。
Nova 需统计哪些资源
云计算的本质在于将硬件资源软件化,以达到快速按需交付的效果,最基本的计算、存储和网络基础元素并没有因此改变。就计算而言,CPU、RAM 和 DISK等依旧是必不可少的核心资源。
从源码和数据库相关表可以得出,Nova 统计计算节点的四类计算资源:
原作者认为重点关注 CPU、RAM 和 DISK 三类资源。
Nova 如何收集资源
从源码可以看出,Nova 每分钟统计一次资源,方式如下:
CPU
vcpus: libvirt 中 get_Info()
vcpu_used: 通过 libvirt 中 dom.vcpus() 从而统计该节点上所有虚拟机 vcpu 总和
RAM
memory: libvirt 中 get_Info()
memory_mb_used:先通过 /proc/meminfo 统计可用内存, 再用总内存减去可用内存得出(资源再统计时会重新计算该值)
DISK
local_gb: os.statvfs(CONF.instances_path)
local_gb_used: os.statvfs(CONF.instances_path)(资源再统计时会重新计算该值)
其它
hypervisor 相关信息:均通过 libvirt 获取
PCI: libvirt 中 listDevices(‘pci’, 0)
NUMA: livirt 中 getCapabilities()
那么问题来了,按照上述收集资源的方式,free_ram_mb, free_disk_gb 不可能为负数啊!别急,Nova-compute 在上报资源至数据库前,还根据该节点上的虚拟机又做了一次资源统计。
Nova 资源再统计
首先分析为什么需要再次统计资源以及统计哪些资源。从 源码 可以发现,Nova 根据该节点上的虚拟机再次统计了 RAM、DISK 和 PCI 资源。
为什么需再次统计 RAM 资源?以启动一个 4G 内存的虚拟机为例,虚拟机启动前后,对比宿主机上可用内存,发现宿主机上的 free memory 虽有所减少(本次测试减少 600 MB),却没有减少到 4G,如果虚拟机运行很吃内存的应用,可发现宿主机上的可用内存迅速减少 3G多。试想,以 64G 的服务器为例,假设每个 4G 内存的虚拟机启动后,宿主机仅减少 1G 内存,服务器可以成功创建 64 个虚拟机,但是当这些虚拟机在跑大量业务时,服务器的内存迅速不足,轻着影响虚拟机效率,重者导致虚拟机 shutdown等。除此以外,宿主机上的内存并不是完全分给虚拟机,系统和其它应用程序也需要内存资源。因此必须重新统计 RAM 资源,统计的方式为:
free_memory = total_memory - CONF.reserved_host_memory_mb - 虚拟机理论内存总和
CONF.reserved_host_memory_mb:内存预留,比如预留给系统或其它应用
虚拟机理论内存总和:即所有虚拟机 flavor 中的内存总和
为什么要重新统计 DISK 资源?原因与 RAM 大致相同。为了节省空间, qemu-kvm 常用 QCOW2 格式镜像,以创建 DISK 大小为 100G 的虚拟机为例,虚拟机创建后,其镜像文件往往只有几百 KB,当有大量数据写入时磁盘时,宿主机上对应的虚拟机镜像文件会迅速增大。而 os.statvfs 统计的是虚拟机磁盘当前使用量,并不能反映潜在使用量。因此必须重新统计 DISK 资源,统计的方式为:
free_disk_gb = local_gb - CONF.reserved_host_disk_mb / 1024 - 虚拟机理论磁盘总和
CONF.reserved_host_disk_mb:磁盘预留
虚拟机理论磁盘总和:即所有虚拟机 flavor 中得磁盘总和
当允许资源超配(见下节)时,采用上述统计方式就有可能出现 free_ram_mb, free_disk_gb 为负。
资源超配与调度
即使 free_ram_mb 或 free_disk_gb 为负,虚拟机依旧有可能创建成功。事实上,当 nova-scheduler 在调度过程中,某些 filter 允许资源超配,比如 CPU、RAM 和 DISK 等 filter,它们默认的超配比为:
CPU: CONF.cpu_allocation_ratio = 16
RAM: CONF.ram_allocation_ratio = 1.5
DISK: CONF.disk_allocation_ratio = 1.0
以 ram_filter 为例,在根据 RAM 过滤宿主机时,过滤的原则为:
memory_limit = total_memory * ram_allocation_ratio
used_memory = total_memory - free_memory
memory_limit - used_memory
相关代码如下(稍有精简):
def host_passes(self, host_state, instance_type):
"""Only return hosts with sufficient available RAM."""
requested_ram = instance_type['memory_mb']
free_ram_mb = host_state.free_ram_mb
total_usable_ram_mb = host_state.total_usable_ram_mb
memory_mb_limit = total_usable_ram_mb * CONF.ram_allocation_ratio
used_ram_mb = total_usable_ram_mb - free_ram_mb
usable_ram = memory_mb_limit - used_ram_mb
if not usable_ram >= requested_ram:
LOG.debug("host does not have requested_ram")
return False123456789101112
宿主机 RAM 和 DISK 的使用率往往要小于虚拟机理论使用的 RAM 和 DISK,在剩余资源充足的条件下,libvirt 将成功创建虚拟机。
随想:内存和磁盘超配虽然能提供更多数量的虚拟机,当该宿主机上大量虚拟机的负载都很高时,轻着影响虚拟机性能,重则引起 qemu-kvm 相关进程被杀,即虚拟机被关机。因此对于线上稳定性要求高的业务,建议不要超配 RAM 和 DISK,但可适当超配 CPU。建议这几个参数设置为:
CPU: CONF.cpu_allocation_ratio = 4
RAM: CONF.ram_allocation_ratio = 1.0
DISK: CONF.disk_allocation_ratio = 1.0
RAM-Reserve: CONF.reserved_host_memory_mb = 2048
DISK-Reserve: CONF.reserved_host_disk_mb = 20480
指定 host 创建虚拟机
本节用于回答问题四,当所有宿主机的资源使用过多,即超出限定的超配值时(total_resource * allocation_ratio),nova-scheduler 将过滤这些宿主机,若未找到符合要求的宿主机,虚拟机创建失败。
创建虚拟机的 API 支持指定 host 创建虚拟机,指定 host 时,nova-scheduler 采取特别的处理方式:不再判断该 host 上的资源是否满足需求,而是直接将请求发给该 host 上的 nova-compute。
相关代码如下(稍有精简):
def get_filtered_hosts(self, hosts, filter_properties,
filter_class_names=None, index=0):
"""Filter hosts and return only ones passing all filters."""
...
if ignore_hosts or force_hosts or force_nodes:
...
if force_hosts or force_nodes:
# NOTE(deva): Skip filters when forcing host or node
if name_to_cls_map:
return name_to_cls_map.values()
return self.filter_handler.get_filtered_objects()123456789101112
当该 host 上实际可用资源时满足要求时,libvirt 依旧能成功创建虚拟机。
最后,以一图总结本文内容
1) vcpu应该配置多少?
(网络资源)
虚拟机性能取决于配置的合理性—确保虚拟机获得足够多的时钟周期、内存空间以及IO带宽。当配置错误或者计算需求增加导致虚拟机出现资源紧张状况时,虚拟机性能及稳定性可能会受影响。很多IT管理员为虚拟机配置了过多的计算资源,以确保在处理峰值请求时不会存在资源短缺情况。尽管过量配置通常没有什么坏处,但存在资源浪费。然而,存在过度配置vCPU实际上会对虚拟机性能带来不利影响的情况。
资源配置的目标是为虚拟机分配足够多的计算资源以使其能够正常运转,但这并不意味着要过度分配计算资源。资源过度分配是一种浪费,就CPU而言,过度分配可能会影响虚拟机性能。
问题出在调度上,hypervisor必须调度vCPU的计算资源供虚拟机使用。当虚拟机使用一个vCPU时并不存在冲突,但当虚拟机使用的多个vCPU分布在两个或多个核心上时,hypervisor必须在两个或多个物理处理之间进行调度。这意味着hypervisor及其正在调度的虚拟机必须等待不同物理处理器核心的响应。
如果虚拟机针对对称多处理器(SMP)而设计,那么没什么问题,而且hypervisor厂商像VMware提供了SMP附加组件,允许SMP工作负载高效、成功地调度并使用多个vCPU。
但是对于没有专门针对SMP设计的常见的单线程工作负载,虚拟机的工作负载可能会浪费时间等待hypervisor对多个vCPU进行调度,这肯定会降低虚拟机性能。在这种情况下,为虚拟机配置一个vCPU实际上能够提升工作负载的性能。管理员必须擅长为工作负载分配vCPU并识别出vCPU资源分配不合理的情况。
2)几种sdn方案比较
OpenFlow交换机就是基于流标项的转发,可以结合SDN被用于结合业务的转发,无需考虑MAC学习,无需考虑是否有路由,而是用户或者管理员根据自 己的需要来配置交换机。所以利用BMC或者MVL的传统商用交换芯片来做OpenFlow的开发,会导致表项容量小、OpenFlow标准支持不完全、对交换芯片其他处理流程组件浪费的现象。
SDN和OpenFlow关系,二者是不能划等号的。例如OpenStack中,如果Neutron下的plugin用 Linux bridge,那么这个就不是SDN了吗?显然答案为仍然是SDN网络。SDN我理解的是一种思想,而不是一种方案或者功能。所以网络很多做法都是和 SDN有着扯不清的关系,但是这个绝非像某些大的互联网公司扯自己的产品硬跟SDN挂钩那样,因为他们的产品开发时研发和测试人员脑袋里连SDN的概念都 没有听说过,现在国内互联网公司和很多的设备商都还只是停留在观望和接触的状态,并没有什么实质的SDN产品或者方案。并且SDN并不代表完全脱离硬件, 有的云计算公司对于网络虚拟化中有一些硬件参与就不认可是SDN,难道说要全世界的人都用一台服务器,里面的每人用的虚拟机都用虚拟端口通信才算是真的 SDN吗?这个逻辑充满了荒谬。SDN只是一种思想,一种站在用户角度、站在管理员角度可以参与管理和控制网络底层转发决策需求的满足和实现。底层转发的 实现是否是纯软件或者有多大程度的硬件参与并不重要。如果一个人坚持这么认为,我只能说这个人不懂SDN。而OpenFlow交换机提供的基于流标项的转 发方式,正是SDN用硬件作为底层转发时所需要的,因此可以说OpenFlow交换机是SDN底层用硬件实现的一种方式,而虚拟网络里采用 OpenVswitch互通虚拟机则是用OpenFlow流表实现SDN思想的一种纯软件方案。
OpenFlow作为SDN底层实现的一个理想选择,在转发层面确实有很多优势,但是个人认为也有很多需要注意的点:
如前文所述,将控制平面和转发平面进行分离,减少了控制点,增加了控制平面的负担,需要比以往有更强的CPU计算能力的设备才能堪重负;
SDN强调管理员在管理网络方面的能力,这些无疑对管理员的技能和对所管理的业务熟悉度有了更高一步的要求,这点与网络设备智能化、自动化、傻瓜化的发展思想多少是有点相悖的;
OpenFlow的多表项为业务实现提供了灵活性,但是这无疑增加了设备的成本,并且为交换芯片驱动开发人员在软件中记录和维护配置表项、容错等研发工作提供相当大的复杂度;
OpenFlow 在转发层面相比于传统方式有了很大提高,应该是先兼容以前所有的转发方式,但是现在的标准中,还有很多传统转发方式支持但是OpenFlow中不支持的, 比如我要实现某个出端口中SIP=1.1.1.1的报文全丢弃,标准中暂时没有出现匹配出端口的的内容,希望OpenFlow标准尽快得到完善;
传统交换机中还有很多非产生直接转发意义或动作方面的功能,比如流控、队列调度、WRED等方面都要涉及交换芯片MMU,而这些OpenFlow是很难对各个厂家通过标准而统一的,所以OpenFlow标准化方面还有很多的工作要做;
虚拟机、iptables
为了提高物理服务器CPU的利用率,出现了使用虚拟机的概念,这样一台物理设备有多台虚拟机,分别“计算”处理不同的数据,如果物理服务器是多核的 情况下,可以说是真正的并行计算不同的数据。当一台物理机内有很多虚拟机时,虚拟机的通信和隔离就有了需求,因为可能在一台物理机内的虚拟机承载着不同的 业务,而承载相同业务的虚拟机分布在多台物理机上。打个比方,中国每个城市是一台物理机,每个城市里的企事业单位是不同虚拟机;同一台物理机的每个企事业 单位之间是无法用自己的内网直接通信的,他们必须都将内网地址转化为外网地址才能在公网上交互数据;而每个企事业单位可能有很多分地,比如可能腾讯在北京 有几个地方,而在广州、深圳和上海还有分地,所有腾讯的这些分地内网都是想通的,其他企事业单位在任何处的公司里都可以通过内网转换后利用外网访问腾讯提 供在公网的服务,这个就是不同虚拟机之间的隔离和互通。如果阿里内网的一台设备,想SSH到腾讯的一台内网机器上,必须给腾讯的这台设备赋予一个公网的 IP,且通常情况下,从阿里这台设备上发出的报文到达腾讯内网时,会通过一种功能将报文的目的IP从公网地址转成腾讯的内网IP地址,这种功能就是 NAT。为了进制这种现象的发生,腾讯的内网可以通过iptables配置这台设备进制外网ssh连接。iptables是云计算中虚拟机常用的技 术,NAT是 iptables的一个功能子集,就像对报文丢弃是OpenFlow规则中动作的一种一样。而云计算是把所有相关的管理节点和计算节点进行多虚一,看做是 一个大的整体并进行统一的资源管理和调度;在所有的这些物理机上的虚拟机之间的通信和隔离,有很多种实现方案,但从技术方案上说基本都是二层vlan隔离 或者对vlan数目要求过多时的vxlan方案及nvgre方案。拿OpenStack举例,Neutron下面的plugin仅官方支持的就有十来种之 多,还有很多非官方维护的,OVS的一出现就受到关注有其道理;因为最初虚拟机之间的隔离是采用Linux bridge技术,非常的不灵活而且配置无法模板化,对于搭建复杂的虚拟网络是无法满足的;并且对于虚拟网络的调试、监控、故障定位都是非常不便的,而且 搭建复杂拓扑的功能也很多无法满足;Openvswitch的出现解决了这些问题,并引入了QOS、镜像、CFM、netflow等功能,而且它还可以支 持OpenFlow标准,最重要的是有一套用C语言的开源实现;导致其在网络虚拟化里得到了很大的重视。这部分内容在论文《Extending Networking into the Virtualization Layer》和《VirtualSwitching in an Era of Advanced Edges》有非常详细的介绍。
OpenStack
OpenStack现在是一个非常火的开源社区,官方有大量的资料和大牛贡献代码及文档。但是从国内的分享来看,大部分是基于如何搭建出某种简单的 环境,尤其是网络这块如何搭建,以保证能建立虚拟机后在虚拟机内部可以正确的访问各种网络,但是从介绍来看绝大多数的分享者对OpenStack的底层技 术并不了解,甚至出现了两台云主机在两个vlan就无法ping通的实验。因为网络虚拟化在OpenStack进行商业活动中提供服务的重要性,每年的 OpenStack会议都有大量的会议在讨论网络相关的技术。而此时也是SDN体现价值的一个重要案例。OpenStack的缺点已经被各种吐槽,我个人 认为OpenStack为了获取最广泛的支持,采取了吸纳百家的策略,就是现在项目众多,耦合性也越来越大;最麻烦的是,对于计算、网络和存储的虚拟化, 它不是采用了一种经过考虑后慎重选择一种最有前途的然后进行专注和持续积累的方式,而是选择了每种技术都支持且经过抽象封装了一层中间层,这就导致的问题 是OpenStack的专注无法集中,开发者的力量被分散,代码需要经过多次的封装,自然也就效率非常低下。商业版本除了修正其固有的BUG外,还必须解 决上述问题。
VXLAN/NVGRE
VXLAN 和NVGRE的两种方案都是为了解决大二层中Vlan ID个数不够的问题,除了卫峰所述的封装导致的传输效率降低和负载均衡受影响外,还会对硬件设备的要求上有进一步提高,据我所知,现在BCM或MVL几乎 只有一两款芯片产品支持,这对OpenFlow的本意来说本身就是个挑战;更别说那些通过收购其他网络公司来完善自己产品布局的某些企业下这些收购后的子 公司,他们的产品更是在SDN上没有什么大的进展。
从ACL中吸收了经验而改进形成的OpenFlow规则,结合现在盛行的SDN概念,已经开出了很多花朵,但是这些花朵能否最后能秋季成熟还是个未 知数。但是OpenFlow确实在QOS分类、实现ACL的防火墙的安全功能、在现有网络上对新协议进行试验都是十分有效的。SDN是一个对现有网络考虑 了兼容性的框架,如果结合具体的业务需求,将OpenFlow的规则利用起来,必能给客户带来收益,给云计算、设备商和芯片商等企业带来发展的机会和激烈 的竞争。OpenFlow到底是会革命成功大放光彩,还是仅是一种过渡形态的昙花一现,可能后者的概率要大一些。
转自:http://itoedr.lofter.com/post/1472ba_6db249d