NVIDIA GPU虚拟化软件vGPU购买指南

概况
英伟达虚拟GPU即 vGPU 解决方案由: 硬件部分 的 GPU (目前仅支持NVIDIA Tesla 系列和 NVIDIA Quadro RTX 6000/8000) GPU 和 软件部分 的 NVIDIA vGPU 构成。通过虚拟化的方式利用 NVIDIA 强大的图形和计算性能,将GPU资源重新划分,以保证GPU资源可以在多个虚拟机之间共享,或者可以将多个GPU分配给一个虚拟机。在 vGPU 解决方案中NVIDIA虚拟GPU软件运行的架构是基于NVIDIA Turing™、Volta™、Pascal™和Maxwell™(M系列已退市)四种体系结构以及四种 vGPU 类型,这些 vGPU 类型使得在 GPU 可以有效的加速虚拟应用程序、虚拟桌面(VDI)、科学计算以及人工智能场景。
一、硬件部分的四种体系架构
1、Maxwell 架构系列GPU

2、Pascal 架构系列GPU

3、Volta 和 Turing 架构 GPU

常用虚拟化的NVIDIA GPUs参数对比一览表

二、软件部分vGPU的分类(基于NVIDIA Virtual GPU 9.0 版本)

1)vComputeServer-面向计算场景进行优化、基于虚拟GPU个数进行授权,且仅支持订阅模式
提供了虚拟化GPU和加速计算密集型服务器工作负载的能力,包括AI,深度学习和数据科学。有了这个,汽车制造商可以使用最新的模拟和计算技术来创建最节省燃料和时尚的设计,研究人员可以分析基因的功能,以更快地开发医疗。
2)Quadro vDWS-支持专业图形和计算场景,基于vGPU数量进行授权
虚拟工作站可通过数据中心提供GPU资源让用户随时随地在任何设备上安全访问数据,用户不再受物理位置的限制,NVIDIA Quadro vDWS 能够进一步发挥Quadro 的优势,实现真正的GPU 加速数据中心,通过数据中心虚拟化应用程序为终端用户如建筑师、工程师和设计师提供专业工作站级别的用户体验。
常用应用程序:Adobe® Creative Cloud®、Allplan ANSYS、Autodesk 3ds Max、Autodesk AutoCAD、Autodesk Maya、Autodesk Revit、Bentley AECOsim Bentley MicroStation、Dassault Systèmes SOLIDWORKS、Esri ArcGIS Pro、Siemens PLM NX等
3)GRID vPC  -面向普通图形加速场景(办公),配合虚拟桌面VDI解决方案,基于vGPU数量授权。
4)GRID vApp -面向普通图形加速场景,配合虚拟应用和共享桌面解决方案,基于vGPU数量授权。
NVIDIA GRID™ 虚拟PC (GRID vPC) 和虚拟应用程序(GRID vApp)  等虚拟化解决方案提供的用户体验与本地PC 几乎别无二致。借助服务器端图形以及全面管理和监控功能,GRID 为您的VDI 环境提供长效的解决方案。为组织中的每台VM(虚拟机)提供GPU 加速能力,为各种现代企业应用程序提供卓越用户体验的解决方案,这些程序包括Microsoft Outlook、Office 2016、网络浏览器、Adobe Photoshop 以及Windows 10 操作系统。成本有效地扩展至整个企业,并将VDI 的覆盖范围扩展到每个成员。
1、NVIDIA GPU 虚拟化软件授权方式:

1)年度订阅模式
如果您是购买的年度订阅模式(租用模式)的 License,则 SUMS 服务已经涵盖在租用模式的 License 中。当租用模式的 License 授权到期,SUMS 也随之到期。年度订阅模式购买一年起。
2)永久授权模式
当您购买的 vGPU License 是永久授权,则需要至少购买三年的 SUMS 服务。SUMS 到期则意味着软 件升级和支持服务也随之停止,软件使用不受影响。
2、NVIDIA GPU 虚拟化软件授权方式:

NVIDIA vGPU 各个版本详细的功能参数如下:

1. 内置 vApps License
2. 控制台显示分辨率限制
3. 最大支持 2 个 4K 或者 4 个 2560×1600 分辨率的显示器
4. Maxwell 架构 GPU 需要 1:1 切割才支持计算(CUDA/OPENCL)
5. M6 仅支持为主显示设备场景
6. 详细的显存切割方式参考:https://docs.nvidia.com/grid/latest/grid-vgpu-user-guide/index.html#virtual-gpu-types-grid

等级保护2.0安全解决方案

应用场景
场景1:大数据智能化应用场景下等级保护建设实践
本场景下安全体系建设以保护业务和大数据的安全为核心目标,基于多云架构、大数据平台等全新IT技术架构建设安全保障体系,打通相互隔离的各级专网,实现数据汇聚融合和智能化应用。


场景2:基于电子政务云IT架构下的等级保护建设实践
结合安全管理、安全技术、安全运营、法律法规及监管四个体系,从做好云平台内生安全开始,全面覆盖云内业务安全、底层平台安全,构建基于政务云IT架构下的一体化安全保障体系。


应用场景3:基于自适应安全架构的等级保护及关基保护合规建设实践

结合关键信息基础设施保护要求,与单位信息化建设同步规划,建设以预测、防御、监测、响应一体化运营为核心的安全保障体系。

导读:自网络安全法颁布,成为网络领域的基本法,我国的网络安全进入了一个新时代。新时代的网络安全观:没有网络安全就没有国家安全,网络安全上升为国家战略,成为总体国家安全观的重要组成部分。

信息安全等级保护是党中央国务院决定在信息系统安全领域实施的基本国策,是国家信息安全保障工作的基本制度和基本方法。

等级保护的工作流程包括,定级、备案、建设整改、等级测评。

等级保护建设核心思想:信息系统的安全设计应基于业务流程自身特点,建立“可信、可控、可管”的安全防护体系,使得系统能够按照预期运行,免受信息安全攻击和破坏。

等级保护2.0安全解决方案

本文主要内容:

  • 网络安全法解读
  • 等级保护2.0安全解决方案
  • 新等级保护差异变化
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案
新时代网络安全等级保护解决方案

NUMA架构的CPU — 真的用好了么?

NUMA简介

这部分将简要介绍下NUMA架构的成因和具体原理,已经了解的读者可以直接跳到第二节。

为什么要有NUMA

在NUMA架构出现前,CPU欢快的朝着频率越来越高的方向发展。受到物理极限的挑战,又转为核数越来越多的方向发展。如果每个core的工作性质都是share-nothing(类似于map-reduce的node节点的作业属性),那么也许就不会有NUMA。由于所有CPU Core都是通过共享一个北桥来读取内存,随着核数如何的发展,北桥在响应时间上的性能瓶颈越来越明显。于是,聪明的硬件设计师们,先到了把内存控制器(原本北桥中读取内存的部分)也做个拆分,平分到了每个die上。于是NUMA就出现了!

NUMA是什么

NUMA中,虽然内存直接attach在CPU上,但是由于内存被平均分配在了各个die上。只有当CPU访问自身直接attach内存对应的物理地址时,才会有较短的响应时间(后称Local Access)。而如果需要访问其他CPU attach的内存的数据时,就需要通过inter-connect通道访问,响应时间就相比之前变慢了(后称Remote Access)。所以NUMA(Non-Uniform Memory Access)就此得名。

numa

我们需要为NUMA做什么

假设你是Linux教父Linus,对于NUMA架构你会做哪些优化?下面这点是显而易见的:

既然CPU只有在Local-Access时响应时间才能有保障,那么我们就尽量把该CPU所要的数据集中在他local的内存中就OK啦~

没错,事实上Linux识别到NUMA架构后,默认的内存分配方案就是:优先尝试在请求线程当前所处的CPU的Local内存上分配空间。如果local内存不足,优先淘汰local内存中无用的Page(Inactive,Unmapped)。 那么,问题来了。。。

NUMA的“七宗罪”

几乎所有的运维都会多多少少被NUMA坑害过,让我们看看究竟有多少种在NUMA上栽的方式:

究其原因几乎都和:“因为CPU亲和策略导致的内存分配不平均”及“NUMA Zone Claim内存回收”有关,而和数据库种类并没有直接联系。所以下文我们就拿MySQL为例,来看看重内存操作应用在NUMA架构下到底会出现什么问题。

MySQL在NUMA架构上会出现的问题

几乎所有NUMA + MySQL关键字的搜索结果都会指向:Jeremy Cole大神的两篇文章:

CPU规模因摩尔定律指数级发展,而总线发展缓慢,导致多核CPU通过一条总线共享内存成为瓶颈
于是NUMA出现了,CPU平均划分为若干个Chip(不多于4个),每个Chip有自己的内存控制器及内存插槽
CPU访问自己Chip上所插的内存时速度快,而访问其他CPU所关联的内存(下文称Remote Access)的速度相较慢三倍左右
于是Linux内核默认使用CPU亲和的内存分配策略,使内存页尽可能的和调用线程处在同一个Core/Chip中
由于内存页没有动态调整策略,使得大部分内存页都集中在CPU 0上
又因为Reclaim默认策略优先淘汰/Swap本Chip上的内存,使得大量有用内存被换出
当被换出页被访问时问题就以数据库响应时间飙高甚至阻塞的形式出现了

imbalance

解决方案

Jeremy Cole大神推荐的三个方案如下,如果想详细了解可以阅读 原文

这三个方案也被业界普遍认可可行,同时在 Twitter 的5.5patch 和 Percona 5.5 Improved NUMA Support 中作为功能被支持。

不过这种三合一的解决方案只是减少了NUMA内存分配不均,导致的MySQL SWAP问题出现的可能性。如果当系统上其他进程,或者MySQL本身需要大量内存时,Innodb Buffer Pool的那些Page同样还是会被Swap到存储上。于是又在这基础上出现了另外几个进阶方案

重新审视问题

如果本文写到这里就这么结束了,那和搜索引擎结果中大量的Step-by-Step科普帖没什么差别。虽然我们用了各种参数调整减少了问题发生概率,那么真的就彻底解决了这个问题么?问题根源究竟是什么?让我们回过头来重新审视下这个问题:

NUMA Interleave真的好么?

为什么Interleave的策略就解决了问题? 借用两张 Carrefour性能测试 的结果图,可以看到几乎所有情况下Interleave模式下的程序性能都要比默认的亲和模式要高,有时甚至能高达30%。究其根本原因是Linux服务器的大多数workload分布都是随机的:即每个线程在处理各个外部请求对应的逻辑时,所需要访问的内存是在物理上随机分布的。而Interleave模式就恰恰是针对这种特性将内存page随机打散到各个CPU Core上,使得每个CPU的负载和Remote Access的出现频率都均匀分布。相较NUMA默认的内存分配模式,死板的把内存都优先分配在线程所在Core上的做法,显然普遍适用性要强很多。 perf1 perf2

也就是说,像MySQL这种外部请求随机性强,各个线程访问内存在地址上平均分布的这种应用,Interleave的内存分配模式相较默认模式可以带来一定程度的性能提升。 此外 各种 论文 中也都通过实验证实,真正造成程序在NUMA系统上性能瓶颈的并不是Remote Acess带来的响应时间损耗,而是内存的不合理分布导致Remote Access将inter-connect这个小水管塞满所造成的结果。而Interleave恰好,把这种不合理分布情况下的Remote Access请求平均分布在了各个小水管中。所以这也是Interleave效果奇佳的一个原因。

那是不是简简单单的配置个Interleave就已经把NUMA的特性和性能发挥到了极致呢? 答案是否定的,目前Linux的内存分配机制在NUMA架构的CPU上还有一定的改进空间。例如:Dynamic Memory Loaction, Page Replication。

Dynamic Memory Relocation 我们来想一下这个情况:MySQL的线程分为两种,用户线程(SQL执行线程)和内部线程(内部功能,如:flush,io,master等)。对于用户线程来说随机性相当的强,但对于内部线程来说他们的行为以及所要访问的内存区域其实是相对固定且可以预测的。如果能对于这把这部分内存集中到这些内存线程所在的core上的时候,就能减少大量Remote Access,潜在的提升例如Page Flush,Purge等功能的吞吐量,甚至可以提高MySQL Crash后Recovery的速度(由于recovery是单线程)。 那是否能在Interleave模式下,把那些明显应该聚集在一个CPU上的内存集中在一起呢? 很可惜,Dynamic Memory Relocation这种技术目前只停留在理论和实验阶段。我们来看下难点:要做到按照线程的行为动态的调整page在memory的分布,就势必需要做线程和内存的实时监控(profile)。对于Memory Access这种非常异常频繁的底层操作来说增加profile入口的性能损耗是极大的。在 关于CPU Cache程序应该知道的那些事的评论中我也提到过,这个道理和为什么Linux没有全局监控CPU L1/L2 Cache命中率工具的原因是一样的。当然优化不会就此停步。上文提到的Carrefour算法和Linux社区的Auto NUMA patch都是积极的尝试。什么时候内存profile出现硬件级别,类似于CPU中 PMU 的功能时,动态内存规划就会展现很大的价值,甚至会作为Linux Kernel的一个内部功能来实现。到那时我们再回过头来审视这个方案的实际价值。

Page Replication 再来看一下这些情况:一些动态加载的库,把他们放在任何一个线程所在的CPU都会导致其他CPU上线程的执行效率下降。而这些共享数据往往读写比非常高,如果能把这些数据的副本在每个Memory Zone内都放置一份,理论上会带来较大的性能提升,同时也减少在inter-connect上出现的瓶颈。实时上,仍然是上文提到的Carrefour也做了这样的尝试。由于缺乏硬件级别(如MESI协议的硬件支持)和操作系统原生级别的支持,Page Replication在数据一致性上维护的成本显得比他带来的提升更多。因此这种尝试也仅仅停留在理论阶段。当然,如果能得到底层的大力支持,相信这个方案还是有极大的实际价值的。

究竟是哪里出了问题

NUMA的问题? NUMA本身没有错,是CPU发展的一种必然趋势。但是NUMA的出现使得操作系统不得不关注内存访问速度不平均的问题。

Linux Kernel内存分配策略的问题? 分配策略的初衷是好的,为了内存更接近需要他的线程,但是没有考虑到数据库这种大规模内存使用的应用场景。同时缺乏动态调整的功能,使得这种悲剧在内存分配的那一刻就被买下了伏笔。

数据库设计者不懂NUMA? 数据库设计者也许从一开始就不会意识到NUMA的流行,或者甚至说提供一个透明稳定的内存访问是操作系统最基本的职责。那么在现状改变非常困难的情况下(下文会提到为什么困难)是不是作为内存使用者有义务更好的去理解使用NUMA?

总结

其实无论是NUMA还是Linux Kernel,亦或是程序开发他们都没有错,只是还做得不够极致。如果NUMA在硬件级别可以提供更多低成本的profile接口;如果Linux Kernel可以使用更科学的动态调整策略;如果程序开发人员更懂NUMA,那么我们完全可以更好的发挥NUMA的性能,使得无限横向扩展CPU核数不再是一个梦想。

基于 Open vSwitch 的 OpenFlow 实践

Open vSwitch 概述

Open vSwitch(下面简称为 OVS)是由 Nicira Networks 主导的,运行在虚拟化平台(例如 KVM,Xen)上的虚拟交换机。在虚拟化平台上,OVS 可以为动态变化的端点提供 2 层交换功能,很好的控制虚拟网络中的访问策略、网络隔离、流量监控等等。
OVS 遵循 Apache 2.0 许可证, 能同时支持多种标准的管理接口和协议。OVS 也提供了对 OpenFlow 协议的支持,用户可以使用任何支持 OpenFlow 协议的控制器对 OVS 进行远程管理控制。

Open vSwitch 概述

在 OVS 中, 有几个非常重要的概念:
  • Bridge: Bridge 代表一个以太网交换机(Switch),一个主机中可以创建一个或者多个 Bridge 设备。
  • Port: 端口与物理交换机的端口概念类似,每个 Port 都隶属于一个 Bridge。
  • Interface: 连接到 Port 的网络接口设备。在通常情况下,Port 和 Interface 是一对一的关系, 只有在配置 Port 为 bond 模式后,Port 和 Interface 是一对多的关系。
  • Controller: OpenFlow 控制器。OVS 可以同时接受一个或者多个 OpenFlow 控制器的管理。
  • datapath: 在 OVS 中,datapath 负责执行数据交换,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。
  • Flow table: 每个 datapath 都和一个“flow table”关联,当 datapath 接收到数据之后, OVS 会在 flow table 中查找可以匹配的 flow,执行对应的操作, 例如转发数据到另外的端口。

Open vSwitch 实验环境配置

OVS 可以安装在主流的 Linux 操作系统中,用户可以选择直接安装编译好的软件包,或者下载源码进行编译安装。
在我们的实验环境中,使用的操作系统是 64 位 Ubuntu Server 12.04.3 LTS,并通过源码编译的方式安装了 Open vSwitch 1.11.0
$ lsb_release -a
No LSB modules are available.
Distributor ID:Ubuntu
Description:Ubuntu 12.04.3 LTS
Release:12.04
Codename:precise
OVS 的源码编译安装方式可以参考官方文档 How to Install Open vSwitch on Linux, FreeBSD and NetBSD
安装完毕后,检查 OVS 的运行情况:
$ ps -ea | grep ovs
12533 ? 00:00:00 ovs_workq
12549 ? 00:00:04 ovsdb-server
12565 ? 00:00:48 ovs-vswitchd
12566 ? 00:00:00 ovs-vswitchd
查看 OVS 的版本信息, 我们安装版本的是 1.11.0

$ ovs-appctl --version
ovs-appctl (Open vSwitch) 1.11.0
Compiled Oct 28 2013 14:17:16
查看 OVS 支持的 OpenFlow 协议的版本
$ ovs-ofctl --version
ovs-ofctl (Open vSwitch) 1.11.0
Compiled Oct 28 2013 14:17:17
OpenFlow versions 0x1:0x4

基于 Open vSwitch 的 OpenFlow 实践

OpenFlow 是用于管理交换机流表的协议,ovs-ofctl 则是 OVS 提供的命令行工具。在没有配置 OpenFlow 控制器的模式下,用户可以使用 ovs-ofctl 命令通过 OpenFlow 协议去连接 OVS,创建、修改或删除 OVS 中的流表项,并对 OVS 的运行状况进行动态监控。
图 1. OpenFlow 的匹配流程

OpenFlow 的匹配流程

Flow 语法说明

在 OpenFlow 的白皮书中,Flow 被定义为某个特定的网络流量。例如,一个 TCP 连接就是一个 Flow,或者从某个 IP 地址发出来的数据包,都可以被认为是一个 Flow。支持 OpenFlow 协议的交换机应该包括一个或者多个流表,流表中的条目包含:数据包头的信息、匹配成功后要执行的指令和统计信息。
当数据包进入 OVS 后,会将数据包和流表中的流表项进行匹配,如果发现了匹配的流表项,则执行该流表项中的指令集。相反,如果数据包在流表中没有发现任何匹配,OVS 会通过控制通道把数据包发到 OpenFlow 控制器中。
在 OVS 中,流表项作为 ovs-ofctl 的参数,采用如下的格式:字段=值。如果有多个字段,可以用逗号或者空格分开。一些常用的字段列举如下:
表 1. 流表常用字段
字段名称 说明
in_port=port 传递数据包的端口的 OpenFlow 端口编号
dl_vlan=vlan 数据包的 VLAN Tag 值,范围是 0-4095,0xffff 代表不包含 VLAN Tag 的数据包
dl_src=<MAC>
dl_dst=<MAC>
匹配源或者目标的 MAC 地址
01:00:00:00:00:00/01:00:00:00:00:00 代表广播地址
00:00:00:00:00:00/01:00:00:00:00:00 代表单播地址
dl_type=ethertype 匹配以太网协议类型,其中:
dl_type=0x0800 代表 IPv4 协议
dl_type=0x086dd 代表 IPv6 协议
dl_type=0x0806 代表 ARP 协议

完整的的类型列表可以参见以太网协议类型列表

nw_src=ip[/netmask]
nw_dst=ip[/netmask]
当 dl_typ=0x0800 时,匹配源或者目标的 IPv4 地址,可以使 IP 地址或者域名
nw_proto=proto 和 dl_type 字段协同使用。
当 dl_type=0x0800 时,匹配 IP 协议编号
当 dl_type=0x086dd 代表 IPv6 协议编号

完整的 IP 协议编号可以参见IP 协议编号列表

table=number 指定要使用的流表的编号,范围是 0-254。在不指定的情况下,默认值为 0。通过使用流表编号,可以创建或者修改多个 Table 中的 Flow
reg<idx>=value[/mask] 交换机中的寄存器的值。当一个数据包进入交换机时,所有的寄存器都被清零,用户可以通过 Action 的指令修改寄存器中的值
对于 add−flow,add−flows 和 mod−flows 这三个命令,还需要指定要执行的动作:actions=[target][,target…]
一个流规则中可能有多个动作,按照指定的先后顺序执行。
常见的操作有:
  • output:port: 输出数据包到指定的端口。port 是指端口的 OpenFlow 端口编号
  • mod_vlan_vid: 修改数据包中的 VLAN tag
  • strip_vlan: 移除数据包中的 VLAN tag
  • mod_dl_src/ mod_dl_dest: 修改源或者目标的 MAC 地址信息
  • mod_nw_src/mod_nw_dst: 修改源或者目标的 IPv4 地址信息
  • resubmit:port: 替换流表的 in_port 字段,并重新进行匹配
  • load:value−>dst[start..end]: 写数据到指定的字段

实践操作 OpenFlow 命令

在本例中, 我们会创建一个不连接到任何控制器的 OVS 交换机,并演示如何使用 ovs-octl 命令操作 OpenFlow 流表。
创建一个新的 OVS 交换机
$ ovs-vsctl add-br ovs-switch
创建一个端口 p0,设置端口 p0 的 OpenFlow 端口编号为 100(如果在创建端口的时候没有指定 OpenFlow 端口编号,OVS 会自动生成一个)。
$ ovs-vsctl add-port ovs-switch p0 -- set Interface p0 ofport_request=100
设置网络接口设备的类型为“internal”。对于 internal 类型的的网络接口,OVS 会同时在 Linux 系统中创建一个可以用来收发数据的模拟网络设备。我们可以为这个网络设备配置 IP 地址、进行数据监听等等。
$ ovs-vsctl set Interface p0 type=internal
$ ethtool -i p0
driver: openvswitch
version:
firmware-version:
bus-info:
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
为了避免网络接口上的地址和本机已有网络地址冲突,我们可以创建一个虚拟网络空间 ns0,把 p0 接口移入网络空间 ns0,并配置 IP 地址为 192.168.1.100
$ ip netns add ns0
$ ip link set p0 netns ns0
$ ip netns exec ns0 ip addr add 192.168.1.100/24 dev p0
$ ip netns exec ns0 ifconfig p0 promisc up
使用同样的方法创建端口 p1、p2
表 2. 创建的端口信息
端口 说明
p0 IP 地址: 192.168.1.100/24
网络名称空间: ns0
网络接口 MAC 地址: 66:4e:cc:ae:4d:20
OpenFlow Port Number: 100
p1 IP 地址: 192.168.1.101/24
网络名称空间: ns1
网络接口 MAC 地址: 46:54:8a:95:dd:f8
OpenFlow Port Number: 101
p2 IP 地址: 192.168.1.102/24,
网络名称空间: ns2
网络接口 MAC 地址: 86:3b:c8:d0:44:10
OpenFlow Port Number: 102
创建所有的端口之后, 查看 OVS 交换机的信息
$ ovs-vsctl show
30282710-d401-4187-8e13-52388f693df7
Bridge ovs-switch
Port "p0"
Interface "p0"
type: internal
Port "p2"
Interface "p2"
type: internal
Port "p1"
Interface "p1"
type: internal
Port ovs-switch
Interface ovs-switch
type: internal
使用 ovs-ofctl 创建并测试 OpenFlow 命令
  1. 查看 Open vSwitch 中的端口信息。从输出结果中,可以获得交换机对应的 datapath ID (dpid),以及每个端口的 OpenFlow 端口编号,端口名称,当前状态等等。
    $ ovs-ofctl show ovs-switch
    OFPT_FEATURES_REPLY (xid=0x2): dpid:00001232a237ea45
    n_tables:254, n_buffers:256
    capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
    actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST
    SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE
    100(p0): addr:54:01:00:00:00:00
    config: PORT_DOWN
    state: LINK_DOWN
    speed: 0 Mbps now, 0 Mbps max
    101(p1): addr:54:01:00:00:00:00
    config: PORT_DOWN
    state: LINK_DOWN
    speed: 0 Mbps now, 0 Mbps max
    102(p2): addr:54:01:00:00:00:00
    config: PORT_DOWN
    state: LINK_DOWN
    speed: 0 Mbps now, 0 Mbps max
    LOCAL(ovs-switch): addr:12:32:a2:37:ea:45
    config: 0
    state: 0
    speed: 0 Mbps now, 0 Mbps max
    OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
    如果想获得网络接口的 OpenFlow 编号,也可以在 OVS 的数据库中查询
    $ ovs-vsctl get Interface p0 ofport
    100
    查看 datapath 的信息
    $ ovs-dpctl show
    system@ovs-system:
    lookups: hit:12173 missed:712 lost:0
    flows: 0
    port 0: ovs-system (internal)
    port 1: ovs-switch (internal)
    port 2: p0 (internal)
    port 3: p1 (internal)
    port 4: p2 (internal)
  2. 屏蔽数据包
    屏蔽所有进入 OVS 的以太网广播数据包
    $ ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
    屏蔽 STP 协议的广播数据包
    $ ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
  3. 修改数据包
    添加新的 OpenFlow 条目,修改从端口 p0 收到的数据包的源地址为 9.181.137.1
    $ ovs-ofctl add-flow ovs-switch "priority=1 idle_timeout=0,
    in_port=100,actions=mod_nw_src:9.181.137.1,normal"
    从端口 p0(192.168.1.100)发送测试数据到端口 p1(192.168.1.101)
    $ ip netns exec ns0 ping 192.168.1.101
    在接收端口 p1 监控数据,发现接收到的数据包的来源已经被修改为 9.181.137.1
    $ ip netns exec ns1 tcpdump -i p1 icmp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on p1, link-type EN10MB (Ethernet), capture size 65535 bytes
    15:59:16.885770 IP 9.181.137.1 > 192.168.1.101: ICMP echo request, id 23111, seq 457, length 64
    15:59:17.893809 IP 9.181.137.1 > 192.168.1.101: ICMP echo request, id 23111, seq 458, length 64
  4. 重定向数据包
    添加新的 OpenFlow 条目,重定向所有的 ICMP 数据包到端口 p2
    $ ovs-ofctl add-flow ovs-switch idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:102
    从端口 p0 (192.168.1.100)发送数据到端口 p1(192.168.1.101)
    $ ip netns exec ns0 ping 192.168.1.101
    在端口 p2 上监控数据,发现数据包已被转发到端口 p2
    $ ip netns exec ns3 tcpdump -i p2 icmp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on p2, link-type EN10MB (Ethernet), capture size 65535 bytes
    16:07:35.677770 IP 192.168.1.100 > 192.168.1.101: ICMP echo request, id 23147, seq 25, length 64
    16:07:36.685824 IP 192.168.1.100 > 192.168.1.101: ICMP echo request, id 23147, seq 26, length 64
  5. 修改数据包的 VLAN Tag
    除了使用“ping”、“tcpdump”和“iperf” 等 Linux 命令以外,我们也可以使用 OVS 提供的 ovs-appctl ofproto/trace 工具来测试 OVS 对数据包的转发状况。ovs-appctl ofproto/trace 可以用来生成测试用的模拟数据包,并一步步的展示 OVS 对数据包的流处理过程。在以下的例子中,我们演示一下如何使用这个命令:
    修改端口 p1 的 VLAN tag 为 101,使端口 p1 成为一个隶属于 VLAN 101 的端口
    $ ovs-vsctl set Port p1 tag=101

    现在由于端口 p0 和 p1 属于不同的 VLAN,它们之间无法进行数据交换。我们使用 ovs-appctl ofproto/trace 生成一个从端口 p0 发送到端口 p1 的数据包,这个数据包不包含任何 VLAN tag,并观察 OVS 的处理过程
    $ ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=66:4e:cc:ae:4d:20,
    dl_dst=46:54:8a:95:dd:f8 -generate
    Flow:metadata=0,in_port=100,vlan_tci=0x0000,dl_src=66:4e:cc:ae:4d:20,
    dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000
    Rule: table=0 cookie=0 priority=0
    OpenFlow actions=NORMAL
    no learned MAC for destination, flooding

    Final flow: unchanged
    Relevant fields: skb_priority=0,in_port=100,vlan_tci=0x0000/0x1fff,
    dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000,nw_frag=no
    Datapath actions: 4,1
    在第一行输出中,“Flow:”之后的字段描述了输入的流的信息。由于我们没有指定太多信息,所以多数字段 (例如 dl_type 和 vlan_tci)被 OVS 设置为空值。
    在第二行的输出中,“Rule:” 之后的字段描述了匹配成功的流表项。
    在第三行的输出中,“OpenFlow actions”之后的字段描述了实际执行的操作。
    最后一段以”Final flow”开始的字段是整个处理过程的总结,“Datapath actions: 4,1”代表数据包被发送到 datapath 的 4 和 1 号端口。
    创建一条新的 Flow:对于从端口 p0 进入交换机的数据包,如果它不包含任何 VLAN tag,则自动为它添加 VLAN tag 101
    $ ovs-ofctl add-flow ovs-switch "priority=3,in_port=100,dl_vlan=0xffff,
    actions=mod_vlan_vid:101,normal"
    再次尝试从端口 p0 发送一个不包含任何 VLAN tag 的数据包,发现数据包进入端口 p0 之后, 会被加上 VLAN tag101, 同时转发到端口 p1 上
    $ ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=66:4e:cc:ae:4d:20,
    dl_dst=46:54:8a:95:dd:f8 –generate
    Flow: metadata=0,in_port=100,vlan_tci=0x0000,dl_src=66:4e:cc:ae:4d:20,
    dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000
    Rule: table=0 cookie=0 priority=3,in_port=100,vlan_tci=0x0000
    OpenFlow actions=mod_vlan_vid:101,NORMAL
    forwarding to learned port

    Final flow: metadata=0,in_port=100,dl_vlan=101,dl_vlan_pcp=0,dl_src=66:4e:cc:ae:4d:20,
    dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000
    Relevant fields: skb_priority=0,in_port=100,vlan_tci=0x0000/0x1fff,dl_src=66:4e:cc:ae:4d:20,
    dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000,nw_frag=no
    Datapath actions: 3
    反过来从端口 p1 发送数据包,由于 p1 现在是带有 VLAN tag 101 的 Access 类型的端口,所以数据包进入端口 p1 之后,会被 OVS 添加 VLAN tag 101 并发送到端口 p0
    $ ovs-appctl ofproto/trace ovs-switch in_port=101,dl_dst=66:4e:cc:ae:4d:20,
    dl_src=46:54:8a:95:dd:f8 -generate
    Flow: metadata=0,in_port=101,vlan_tci=0x0000,dl_src=46:54:8a:95:dd:f8,
    dl_dst=66:4e:cc:ae:4d:20,dl_type=0x0000
    Rule: table=0 cookie=0 priority=0
    OpenFlow actions=NORMAL
    forwarding to learned port

    Final flow: unchanged
    Relevant fields: skb_priority=0,in_port=101,vlan_tci=0x0000,dl_src=46:54:8a:95:dd:f8,
    dl_dst=66:4e:cc:ae:4d:20,dl_type=0x0000,nw_frag=no
    Datapath actions: push_vlan(vid=101,pcp=0),2
  6. 其他 OpenFlow 常用的操作
    查看交换机中的所有 Table
    ovs-ofctl dump-tables ovs-switch
    查看交换机中的所有流表项
    ovs−ofctl dump−flows ovs-switch
    删除编号为 100 的端口上的所有流表项
    ovs-ofctl del-flows ovs-switch "in_port=100"
    查看交换机上的端口信息
    ovs-ofctl show ovs-switch

通过 Floodlight 管理 OVS

一方面,OpenFlow 控制器可以通过 OpenFlow 协议连接到任何支持 OpenFlow 的交换机,控制器通过和交换机交换流表规则来控制数据流向。另一方面, OpenFlow 控制器向用户提供的界面或者接口,用户可以通过界面对网络架构进行动态的修改,修改交换机的流表规则等等。Floodlight 是一个基于 Apache 协议,使用 Java 开发的企业级 OpenFlow 控制器。我们在下面的例子中演示如何安装 Floodlight,并连接管理 OVS 的过程。
Floodlight 的安装过程非常简单,在另外一台机器上, 下载 Floodlight 源码并编译
$ git clone git://github.com/floodlight/floodlight.git
$ cd floodlight/
$ ant
$ java -jar target/floodlight.jar
运行 Floodlight
$ java -jar floodlight.jar
在安装了 OVS 交换机的节点上,配置 OVS 交换机 ovs-switch,使用 Floodlight 作为控制器。默认情况下,Floodlight 在端口 6633 上进行监听,我们使用 ovs-vsctl 命令配置 OVS 交换机使用 TCP 协议连接到 Floodlight(IP 地址为 9.181.137.182,端口号 6633)。对于一个 OVS 交换机来说,可以同时配置一个或者多个控制器
$ ovs-vsctl set-controller ovs-switch tcp:9.181.137.182:6633
当 OVS 交换机连接到 Floodlight 控制器后,理论上所有的流表规则应该交给控制器来建立。由于 OVS 交换机和控制器之间是通过网络通讯来传递数据的,所以网络连接失败会影响到 Flow 的建立。针对这种情况,OVS 提供了两种处理模式:
  • standlone: 默认模式。如果 OVS 交换机超过三次无法正常连接到 OpenFlow 控制器,OVS 交换机自己会负责建立流表。在这种模式下,OVS 和常见的 L2 交换机相似。与此同时,OVS 也会继续尝试连接控制器,一旦网络连接恢复,OVS 会再次切换到使用控制器进行流表管理。
  • secure: 在 secure 模式下,如果 OVS 无法正常连接到 OpenFlow 控制器,
    OVS 会不停的尝试与控制器重新建立连接,而不会自己负责建立流表。
设置 OVS 的连接模式为 secure 模式
    $ ovs-vsctl set Bridge ovs-switch fail-mode=secure
查看 OVS 的状态,“is_connected:true”代表 OVS 已经成功连接到了 Floodlight
$ ovs-vsctl show
30282710-d401-4187-8e13-52388f693df7
Bridge ovs-switch
Controller "tcp:9.181.137.182:6633"
is_connected: true
Port ovs-switch
Interface ovs-switch
type: internal
Port "p0"
Interface "p0"
type: internal
Port "p1"
tag: 101
Interface "p1"
type: internal
Port "p2"
Interface "p2"
type: internal
通过访问 Floodlight 提供的 Web 管理界面 http://<Host Address>:8080/ui/index.html,我们可以查看 Floodlight 控制器的状态以及所有连接到 Floodlight 的交换机列表
图 2. Floodlight 主界面

Floodlight 主界面

选中某个 OpenFlow 交换机, 查看其中的端口列表和流表信息
图 3. 查看 OpenFlow 交换机的详细信息

查看 OpenFlow 交换机的详细信息

通过 Floodlight 的 RESTAPI,添加两条新的规则让端口 p0 和 p1 可以相互通讯。注意:替换命令行中的 switch 的 ID 为交换机的 datapath ID
curl -d '{"switch": "00:00:0e:f9:05:6b:7c:44", "name":"my-flow1", "cookie":"0","priority":"32768",
"ingress-port":"100","active":"true", "actions":"output=flood"}'
http://9.181.137.182:8080/wm/staticflowentrypusher/json

curl -d '{"switch": "00:00:0e:f9:05:6b:7c:44", "name":"my-flow2", "cookie":"0","priority":"32768",
"ingress-port":"101","active":"true", "actions":"output=flood"}'
http://9.181.137.182:8080/wm/staticflowentrypusher/json
验证是否能从端口 p0 发送数据包到 p1
$ ip netns exec ns0 ping -c4 192.168.1.101
PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data.
64 bytes from 192.168.1.101: icmp_req=1 ttl=64 time=0.027 ms
64 bytes from 192.168.1.101: icmp_req=2 ttl=64 time=0.018 ms
64 bytes from 192.168.1.101: icmp_req=3 ttl=64 time=0.023 ms
64 bytes from 192.168.1.101: icmp_req=4 ttl=64 time=0.022 ms

--- 192.168.1.101 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2998ms
rtt min/avg/max/mdev = 0.018/0.022/0.027/0.005 ms
在 OVS 端也可以看到,流表规则已经被 OVS 同步到本地。
$ ovs-ofctl dump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0xa0000000000000, duration=335.122s, table=0, n_packets=347, n_bytes=28070,
idle_age=1, in_port=100 actions=FLOOD
cookie=0xa0000000000000, duration=239.892s, table=0, n_packets=252, n_bytes=24080,
idle_age=0, in_port=101 actions=FLOOD
通过 Floodlight 的 RestAPI,查看交换机上的流表规则
curl http://9.181.137.182:8080/wm/staticflowentrypusher/list/00:00:0e:f9:05:6b:7c:44/json
通过 Floodlight 的 RestAPI,删除交换机上的流表规则
curl http://9.181.137.182:8080/wm/staticflowentrypusher/clear/00:00:0e:f9:05:6b:7c:44/json

总结

通过本文的讲述和实验,我们了解了 Open vSwitch 以及 OpenFlow 的基本概念,以及通过 OpenFlow 协议修改 Open vSwitch 中的流表项,最后演示了如何使用 Floodlight 连接 Open vSwitch 并进行管理。

Open vSwitch的ovs-vsctl命令详解

Introduction

Open vSwitch中有多个命令,分别有不同的作用,大致如下:
  • ovs-vsctl用于控制ovs db
  • ovs-ofctl用于管理OpenFlow switch 的 flow
  • ovs-dpctl用于管理ovs的datapath
  • ovs-appctl用于查询和管理ovs daemon
本文主要介绍ovs-vsctl。以下命令查询主机上已有的 OVS bridge,以及其中的 port。
ovs-vsctl show  
例子
$ ovs-vsctl show
fc562da8-fb36-4d62-8b47-5502e72069dc
Bridge br-vxlan
Port "vxlan0"
Interface "vxlan0"
type: vxlan
options: {remote_ip="10.10.10.1"}
Port br-vxlan
Interface br-vxlan
type: internal
Port "veth2"
Interface "veth2"
ovs_version: "2.5.0"

Bridge 相关命令

创建 bridge

创建bridge(或switch,以下统称为bridge) br0
使用选项--may-exist后,若欲创建的bridge已存在,该命令什么也不做,也不报错。
ovs-vsctl [--may-exist] add-br br0  

删除bridge

删除 bridge br0
使用选项--if-exists后,若欲删除的bridge不存在,该命令什么也不做,也不报错。
ovs-vsctl [--if-exists] del-br br0  

查询已有的 bridge

ovs-vsctl list-br  

端口相关命令

添加端口

添加端口(物理端口或vNIC)eth1到bridge eth1中
ovs-vsctl [--may-exist] add-port br0 eth1  

创建 bond

在br0上创建一个bond了eth0,eth1和eth2的bond端口bond0
# ovs-vsctl add-bond <bridge> <port> <iface...>
ovs-vsctl add-bond br0 bond0 eth0 eth1 eth2

移除端口

从br0上移除端口eth1
ovs-vsctl [--if-exists] del-port br0 eth1  

列出端口

列出br0上的端口(不包括internal port)
ovs-vsctl list-ports br0  

查看端口详细数据

列出OVS中端口eth1的详细数据
$ ovs-vsctl list interface eth1

OpenFlow 控制器相关

添加控制器

# ovs-vsctl set-controller <bridge> <target...>
ovs-vsctl set-controller br0 tcp:1.2.3.4:6633

# 设置多个controller
ovs-vsctl set-controller br0 tcp:1.2.3.4:6633 tcp:4.3.2.1:6633

# 添加使用unix socket通信的controller
ovs-vsctl set-controller br0 unix:/var/run/xx/xx.sock

移除控制器

ovs-vsctl del-controller br0  

查询 brige 上已配置的控制器

ovs-vsctl get-controller br0  

VLAN 相关

配置端口为Access口

设置br0中的端口eth0为VLAN 10的access口
ovs-vsctl set port eth0 tag=10  
添加eth1到指定bridge br0中,同时将其配置成指定VLAN 10的access端口
ovs-svctl add-port br0 eth1 tag=10  

配置端口为Trunk口

在br0上添加port eth1为VLAN 9,10,11的trunk
ovs-vsctl add-port br0 eth1 trunk=9,10,11  

VXLAN 相关

在bridge ovs0中添加远端IP为10.10.10.1的VXLAN endpoint端口vxlan0
# key=100表示设置vni为100,不设置默认为0
ovs-vsctl add-port ovs0 vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=10.10.10.1 options:key=100

# 不设key值,vni默认为0
ovs-vsctl add-port ovs0 vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=10.10.10.1

# key=flow的话,表示该port的vni可以通过openflow的actions来进行设置
# 如: actions=set_field:100->tun_id
# 或: actions=set_tunnel:100
ovs-vsctl add-port ovs0 vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=10.10.10.1 options:key=flow

其他

Atomic operation

一条命令创建bridge br0的,并添加eth0到br0中
ovs-vsctl add-br br0 -- add-port br0 eth0  

创建 internal port

OVS internal port 可以配置IP地址,普通 port 上配置的IP地址是不起作用的。在 br0 上创建一个internal port in0:
ovs-vsctl add-br br0 in0 -- set interface in0 type=internal  
ip addr add 10.10.10.10/24 dev in0

# 创建internal port的同时将其设置为VLAN 10的access port
ovs-vsctl add-br br0 in1 tag=10 -- set interface in1 type=internal
ip addr add 20.20.20.20/24 dev in1

设置 OpenFlow port id

# 将已在ovs中的端口veth1的OpenFlow端口设置成100
ovs-vsctl set interface veth1 ofport_request=100

# 将端口veth1添加到bridge br0中,并将veth1的OpenFlow端口设置成200
ovs-vsctl add-port br0 veth1 -- set interface veth1 ofport_request=200
{% admonition note Note %} OpenFlow的端口 id 在设置 flow 的匹配字段 in_port 以及 actions 字段的 output 中都会用到。 
可以通过命令ovs-ofctl show br0来查看 br0 中各端口的 OpenFlow 端口 id,该 id 并不求是按顺序的。 {% endadmonition %}

设置OpenFlow版本

ovs-vsctl set bridge br0 protocols=OpenFlow10,OpenFlow12,OpenFlow13