写点什么

苏宁私有云 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:002865

评论

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

编辑距离的计算

zikcheng

算法 编辑距离

如何成为一名具备产品思维的软件工程师?

顾强

产品 开发者 职场

使用gitlab ci构建IOS包并发送通知消息到企业微信

Zoe

ios ci gitlab

干货分享:分布式场景之刚性事务-2PC详解

奈学教育

分布式

SQL 找出 100 以内的质数

zero

sql MySQ

亲密爱人

Janenesome

爱情

视频 | 5款免费翻译软件实测对比,从花花董花花的被删微博到北京话“你丫给我站住了”都能翻译

赵新龙

翻译

MySQL实战四十五讲基础篇总结(一)

一个有志气的DB

MySQL

任何事物当中的百分之九十都是垃圾?

池建强

互联网 信息噪声

工信部报告显示:电话越打越少 、短信越发越多……这是怎么回事?

赵新龙

短信 工信部

都在这儿了!5月 Flink 社区发版、更新汇总

Apache Flink

大数据 flink 流计算 实时计算

霸榜 GitHub,一款开源的 Linux 神器!

GitHubDaily

GitHub Linux 编程 开发者工具 计算机网络

MySQL实战四十五讲基础篇总结(三)

一个有志气的DB

MySQL mysql事务

【教你如何写作】参与创作,领取 InfoQ 编辑训练营内训课程

InfoQ写作社区官方

写作平台 投稿 热门活动

程序员的晚餐 | 5 月 19 日 蒜香鸡腿,味道令人惊讶

清远

美食

Java开发架构篇:初识领域驱动设计DDD落地

小傅哥

设计模式 领域驱动设计 DDD 小傅哥 架构设计

【玩转写作社区】Markdown & 快捷键详解

InfoQ写作社区官方

写作平台 markdown 编辑器 快捷键 玩转写作平台

有趣的解谜:Python Challenge

封不羁

Python

spring事务原理

年轮

spring 源码分析

单例模式——独一无二的对象

大头星

Java 面试 设计模式 单例模式

Flink Weekly | 每周社区动态更新-20200513

Apache Flink

大数据 flink 实时计算

回顾 | Apache Flink Meetup 杭州站圆满结束(附PPT下载)

Apache Flink

大数据 flink 流计算 实时计算

识别代码中的坏味道(四)

Page

敏捷开发 面向对象 重构 CleanCode 代码坏味道

为什么window.open只是打开了一个空白页

阡陌r

Java 踩坑 网络协议

一款Python实用神器,5 行 Python 代码 实现一键批量扣图

狂师

Python 学习 效率工具 开发者工具 开发

如何讲好故事

Bob Jiang

Flink 与 Hive 的磨合期

Apache Flink

大数据 flink 实时计算

比特币为什么值两万亿?

Haiyung

比特币

物联网技术栈之通信技术

老任物联网杂谈

物联网 通信

你是不是对副业有什么误解?

一尘观世界

程序员 副业 认知提升 思维方式 格局

MySQL实战四十五讲基础篇总结(二)

一个有志气的DB

MySQL 日志

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