写点什么

苏宁私有云 SR-IOV 虚拟网络性能优化

  • 2018-11-09
  • 本文字数:4122 字

    阅读完需:约 14 分钟

苏宁私有云SR-IOV虚拟网络性能优化

1. SR-IOV 介绍

SR-IOV 技术是一种基于硬件的虚拟化解决方案,可提高网络性能和可伸缩性。SR-IOV 标准允许在虚拟机之间高效共享 PCIe(Peripheral Component Interconnect Express,快速外设组件互连)设备,并且它是在硬件中实现的,可以获得能够与本机性能媲美的 I/O 性能。SR-IOV 规范定义了新的标准,根据该标准,创建的新设备可允许将虚拟机直接连接到 I/O 设备。


单个 I/O 资源可由许多虚拟机共享。共享的设备将提供专用的资源,并且还使用共享的通用资源。这样,每个虚拟机都可访问唯一的资源。因此,启用了 SR-IOV 并且具有适当的硬件和 OS 支持的 PCIe 设备(例如以太网端口)可以显示为多个单独的物理设备,每个都具有自己的 PCIe 配置空间。


下图展示了针对 PCIe 硬件的 SR-IOV 技术体系示意图。



图 1 SR-IOV 技术体系架构


支持 SR-IOV 的网卡主要功能模块分为:


  • 物理功能 (Physical Function, PF)

  • 支持 SR-IOV 的管理。可以创建 VF,对于网卡,理论上可以创建 256 个 VF。一般情况下, 千兆网卡能支持达 7 个 VF, 万兆网卡能支持达 63 个 VF。

  • 虚拟功能 (Virtual Function, VF)

  • VF 可以理解为一个虚拟网卡,拥有独立内存空间、中断和 Direct Memory Access (DMA)流。VF 是 PF 虚拟出的一个实例,以一个独立的网卡形式展现。VF 是一种轻量级 PCIe 功能,可以与 PF 以及其创建的所有 VF 共享一个或多个物理资源。

  • 交换功能(Layer 2 Classifier/Sorter switch)

  • 这个交换机其实是物理网卡内置的。流量进入物理网卡后,经过这个交换机然后分发到不同的 VF 上。


使用 SR-IOV 技术的主要优点是:


  • 提高虚拟机包转发效率

  • 减少报文在主机内部的传输延时以及延时抖动


由于绕过了主机的协议栈以及 VMM(Virtual Machine Manager),减少了主机在网络报文收发中的资源消耗


同时,由于 SR-IOV 技术使虚拟机通过 PCI-passthrough 的方式直接使用 VF,绕过了主机的内核协议栈以及 VMM,故存在以下局限:


  • Host 无法监控 VF 的状态

  • 安全组无法应用

  • 虚拟机热迁移无法实现,迁移的支持能力不够灵活

  • 对 HA 的支持不太高

  • sriov 不支持 vxlan

2. SR-IOV 性能

本测试对比测试万兆网络中 SRIOV 虚拟机和 OVS 虚拟机在网络负载较高情况下的虚拟网络表现,总结分析,同时为以后 SRIOV 虚拟机和其它类型的虚拟机做对比给出参考。

2.1 测试性能指标

主要对以下几个网络性能指标进行测试:


  1. 负载(OfferedLoad):网络流量负荷百分比,当前流量占端口速率的比例(百分比)

  2. 包速(Frame Per-second):数据包每秒的收/发个数

  3. 平均时延(Average Latency):数据包传输的平均延迟(毫秒,ms)

2.2 测试拓扑图

SR-IOV 测试环境网络拓扑:



Openvswitch 测试环境网络拓扑:


2.3 测试结果









可以看出 SR-IOV 各方面性能都要优于 Openvswitch。

3. SR-IOV 高可用方案

因为采用 SR-IOV,虚拟机流量不经过宿主机操作系统,所以不能在宿主机操作系统层面做高可用,必须在虚拟机内部做高可用。SR-IOV 高可用方案如下图:



(1) vm 挂载不同 pf 的 vf,在 vm 内部配置网卡 bond,可以根据需求选择 balance-rr、active-backup 或者 balance-xor 策略。


(2) vm 挂载的 vf 的 mac 地址必须设置成一样。这样在虚拟机配置网卡 bond 的情况下,仍然可以使用 vf 的 mac spoofing check 功能。


(3) pf 配置 lacp bond,交换机侧配置动态链路聚合,实现聚合带宽的动态调整。

4. OpenStack 创建 SR-IOV 虚拟机过程

Openstack 默认不支持 SR-IOV 的高可用,neutron 中一个逻辑的 port 对应一个 vf 口。所以我们需要对 openstack 进行改造,总体思路是,通过在调用 Neutron Create Port 的 api 时候,对 Port 打上 bond 标签,Nova 在创建虚机的时候通过读取到对应 port 的 bond 标签,为该 port 分配两个 VF 口,并且在分配 VF 口的 pci 资源的时候,默认的把两个 vf 分配在不同的 pf 上。对应在 port 的 binding:profile 上需要展示使用的两个 vf 口的 pci 信息。

4.1 调用 neutron api 创建 sriov 的 port

调用 neutron 接口创建 sriov port,在 profile 中对 Port 打上 bond 标签,这里无需赘述。命令如下:


neutron port-create --binding:vnic_type=direct --binding:profile type=dict bond=true
复制代码

4.2 调用 nova api 创建虚拟机

入口为 nova/api/openstack/compute/servers 的 create 方法,检查一系列参数和 policy,然后调用 compute_api 的 create 方法:



compute_api 是 nova/compute/api.py 模块,在该文件中找到 create 方法,该方法接着调用_create_instance 方法,在_create_instance 方法中调用_validate_and_build_base_options 方法对所有的输入参数和策略做检查,并且封装 pci 请求。封装 pci 请求的方法是 nova/network/neutronv2/api.py 的 create_pci_requests_for_sriov_ports 方法,该方法会先调用 neutron api 获取 port 的 vnic_type、phynet_name、bond 属性,根据 bond 属性确定 vf 的数量(bond 为 true,vf 的数量是 2,否则 vf 数量是 1)。



返回到 nova/compute/api.py 的_create_instance 方法,该方法接着调用 compute_task_api 的 schedule_and_build_instances 方法:



compute_task_api 是 nova/conductor/api.py 模块。这里没有执行什么操作,直接调用了 conductor_compute_rpcapi 的 schedule_and_build_instances 方法:



该方法远程过程调用 api,即 nova/conductor/rpcapi.py 模块,该方法会对版本进行检查,然后调用 RPC:



cast 表示异步调用,schedule_and_build_instances 是远程调用的方法,kw 是传递的参数。现在 nova-api 任务完成,此时会响应用户请求,虚拟机状态为 building。

4.3 nova conductor

nova-api 向 nova-conductor 发起 RPC 调用,进程跳到 nova-conductor 服务,入口为 nova/conductor/manager.py 的 schedule_and_build_instances 方法,该方法首先调用了_schedule_instances 方法,在_schedule_instances 方法中调用了 scheduler_client 的 select_destinations 方法:



这个方法最终调用到 nova/scheduler/client/query.py 下的 select_destinations 方法,执行 RPC 的调用。



RPC 封装同样是在 scheduler 的 rpcapi 中实现。该方法 RPC 调用代码如下:



Call 表示同步调用,此时 nova-conductor 并不会退出,而是堵塞等待直到 nova-scheduler 返回。因此当前状态为 nova-conductor 为 blocked 状态,等待 nova-scheduler 返回,nova-scheduler 接管任务。

4.4 nova scheduler

nova scheduler 中入口为 nova/scheduler/manager.py 模块的 select_destinations 方法,该方法会调用 driver 的 select_destinations 方法,这里的 driver 是调度算法实现,通过 filters 过滤掉不满足条件的计算节点,剩下的节点通过 weigh 方法计算权值,最后选择权值高的作为候选计算节点返回。最后 nova-scheduler 返回调度结果的 hosts 集合,任务结束,返回到 nova-conductor 服务。


nova/scheduler/manager.py



nova/scheduler/driver.py



nova/scheduler/filter_scheduler.py


4.5 nova condutor

回到 nova-conductor 的 schedule_and_build_instances 方法,nova-conductor 等待 nova-scheduler 返回后,拿到调度的计算节点列表。因为可能同时启动多个虚拟机,因此循环调用了 compute_rpcapi 的 build_and_run_instance 方法。



Compute_rpcpai 位于 nova/compute/rpcapi 模块,该方法向 nova-compute 发起 RPC 请求:



发起的是异步 RPC,因此 nova-conductor 任务结束,进入 nova-compute 服务。

4.6 nova compute

入口是 nova/compute/manager.py 的 build_and_run_instance 方法,该方法会调用_do_build_and_run_instance 方法,该方法会更新虚拟机状态,然后调用_build_and_run_instance 方法,该方法会预先声明占用计算节点的资源。



其中在 instance_claim 方法中会处理 pci 的请求,instance_claim→claim_instance(nova/pci/manager.py)→_claim_instance →consume_requests(nova/pci/stats.py),在 nova/pci/stats.py 中会根据不同的网卡把 pci 资源分为不同的 pool。



在 consume_requests 方法中会具体分配 pci 资源也就是 vf,



先根据剩余可用的 vf 的数量将 pool 进行排序,如果 port 的 bond 属性为 false,则 count 数量为 1,则从可用 vf 数量最多的 pool 中分配一个 vf,这样使不同网卡的负载尽量均衡。如果 port 的 bond 属性为 true,则 count 数量为 2,则从两个 pool 中各分配一个 vf,达到高可用的目的。


回到 nova/compute/manager.py 的 build_and_run_instance 方法,这个方法接下来会调用 spawn_n 方法,开始真正创建虚拟机。这里不同的虚拟机技术对应不同的 driver,其中 libvrit 的 driver 对应 nova/virt/libvirt/driver.py。从 spawn 方法开始,会先获取 instance 的磁盘、镜像、网络等信息,然后生成 instance 的 xml 文件。



在_get_guest_xml 方法中会调用_get_guest_config 方法,其中 sriov 网卡的部分如下:



这里如果 port 的 bond 为 true,则会将两块网卡的信息写入 xml 文件中。


回到 spawn 方法,接下来会调用_create_domain_and_network 方法,该方法会调用 plug_vifs 方法创建 qbr 和 qvo,接着创建虚拟机,虚拟机状态为 pause。然后等待 neutron-server 的消息,如果等到消息后将虚拟机状态改为 running,否则超时没有等到,则将虚拟机销毁。


4.7 neutron sriov agent

在 neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py 中 daemon_loop 方法会定时检测 vf 的状态变化,如果有 vf 发生变化,进入 process_network_devices 方法,在该方法中,会根据 vf 的状态是添加更改删除做不同的处理。



其中在 treat_devices_added_updated 方法中,如果 port 的 bond 为 true,需要更新两个 vf 的状态:



然后会调用 rpc,通知 neutron-server 更新状态。



这里是同步调用,neutron-server 接收到消息后,会向 nova 发送更新 port 的消息,接着 nova compute 会 resume 状态是 pause 的虚拟机。


至此,带有 sriov 高可用网卡的虚拟机创建完成。


作者


李伟杰,苏宁云网络架构师,长期从事云计算的研发工作,在云计算虚拟网络和 SDN 网络方面有专业的研究,现在负责苏宁云虚拟网络产品设计及研发。


陈玮,苏宁云高级研发工程师,有多年云计算网络研发经验,现在负责苏宁云网络产品的研发。


2018-11-09 18:002637

评论

发布
暂无评论
发现更多内容

药物研发的商业模式问题

lidaobing

28天写作 药物研发

基因编辑食品,能否端上我们的餐桌?

脑极体

「架构师训练营 4 期」 第三周 - 001

凯迪

架构师训练营第十三周作业

丁乐洪

精选算法面试-哈希表

李孟聊AI

面试 算法 哈希 28天写作

如何实现CentOS服务器的扩容??

冰河

Linux centos 扩容 服务器

游戏夜读 | 游戏作品的生命力

game1night

OSPF的八大特点介绍

使用DevSecOps保护CI / CD管道

啸天

DevSecOps 应用安全 开发安全

智能合约业务场景探索(一)

石君

智能合约 28天写作

项目管理系列(4)-另类减肥法

Ian哥

28天写作

绩效管理,上下同心者胜(一)

一笑

管理 绩效 28天写作

读《一入阿里“误终生”》,我喜欢上了小马哥

李忠良

28天写作

我做了回视频,告诉你需要用到哪些工具

和牛

工具

Redis布隆过滤器原理与实践

Java redis 面试

Windows文件夹还能更改颜色?

程序员的时光

程序员 七日更 28天写作

Android面试总结(一)

我就感觉到快

android进阶之光!双非渣本Android四年磨一剑,进阶学习资料!

欢喜学安卓

android 程序员 面试 移动开发

HDFS杂谈:ACL访问控制列表

罗小龙

hadoop hdfs acl 28天写作

Lambda 和 Stream API

大海

Java Lambda Stream<T>

生产服务器内存泄漏的排查过程与优化解决方案

冰三郎

Java jdk 问题排查 jetty

自动驾驶感知功能一般都有啥?(28天写作 Day9/28)

mtfelix

自动驾驶 28天写作

阿里P8大神分享的并发编程笔记,颠覆了我以往“正确“的认知

Java 程序员 面试 并发编程

日语复习 Day03【~あまり(に)】

IT蜗壳-Tango

程序员 七日更 日语语法

概率论DEMO

rainbow

android开发要学什么语言!掌握这些Android开发热门前沿知识,挥泪整理面经

欢喜学安卓

android 程序员 面试 移动开发

「架构师训练营 4 期」 第三周 - 002

凯迪

28天瞎写的第二百二十天:独立设计维哈柯文云输入法的故事

树上

28天写作

一款dubbo服务可视化调试工具

程序员架构进阶

dubbo 工具 RPC 服务化 28天写作

写在开课前

5x

一篇让你彻底理解网关是什么的文章

Java架构师迁哥

苏宁私有云SR-IOV虚拟网络性能优化_服务革新_李伟杰_InfoQ精选文章