暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

突破云原生网络性能瓶颈

watson 2024-06-23
250

0. 目录

1. 垫话
2. 前言
3. 加速虚拟机到加速容器的转变
4. 传统 workloads 与 CNF
5. Kubernetes CNI 插件以及 Multus 如何融入其中
6. SR-IOV for 容器
7. 通过 vDPA 加速 CNF
8. 总结

1. 垫话

本文乃对 Red Hat 《Breaking cloud native network performance barriers》一文的翻译(系列文章第 11 篇)。

2. 前言

前面的系列文章讨论了 virtio 网络及其在虚拟机中的应用。我们从原生的 vhost-net/virtio-net 架构,到 vhost-user/virtio-pmd 架构,再到 vDPA(vHost Data Path Acceleration,译者注:vDPA 中的 v,网上文章有多种版本:virtual、virtio、vHost),vDPA 架构将 virtio ring 布局打通给 NIC,以给 VMs 提供 wirespeed/wirelatency。
本文我们讨论使用 vDPA 为容器(基于 Kubernetes 编排的整体解决方案)提供 wirespeed/wirelatency 的 L2(译者注:二层,数据链路层)接口。我们将演示如何将 vDPA 接口和 DPDK 库相结合,以加速容器化网络功能(Containerized Network Functions,CNFs)。使用 Multus CNI(https://github.com/k8snetworkplumbingwg/multus-cni)插件将 vDPA 接口作为容器的辅助接口。
本文阐释该解决方案所涉及的主要组件,以及它们工作在一起的架构大图。我们假设读者对 Kubernetes、容器网络接口(Container Network Interface,CNI)以及 NFV 概念(如 VNF 和 CNF)有个总体了解。
介于此项工作还在完善中,后续不会提供相应的深入、实操文章。目前有很多社区在讨论该解决方案产品化的各项技术,我们会给出相关 repos 的链接(repos 由社区维护更新)。
计划在 2019 年 11 月(译者注:原文发表于同年的 10 月份)的 Kubecon NA Red Hat 展台上,与我们一直在合作的几家公司共同展示将 vDPA 应用于 CNFs 的 PoC 演示。

3. 加速虚拟机到加速容器的转变

为啥我们要讨论对容器的加速呢?
虚拟化可以带来硬件的独立性(译者注:应该指的是虚拟机内部的硬件与 host 可以无关)、弹性以及更容易的可复制性,尽管隔离性上很棒,但虚拟机通常都太重,因为在不同的虚拟机间搬移数据需要做额外的数据拷贝。故而业界转而切换到容器,通过利用 cgroups 和 Linux namespaces 实现更轻量的解决方案,并保持有效的隔离性以及更好的可移植性。不同于虚拟机,每个容器(大部分)只包含应用程序,而不是一个完整的操作系统。
为最大化发挥容器的威力,业界需要自动化部署及管理容器的编排工具。Kubernetes 作为容器编排工具之一,具有优秀的应用程序生命周期及简洁的网络访问管理能力。
业界对容器技术潜力挖掘的兴趣已经远远超越了传统 IT。通信服务供应商也希望在他们的专用网络中充分发挥容器的优势,他们的网络既有 edge 也有 core 的需求,这正是容器技术可以充分发挥的地方。需要特别指出的是,edge 使用场景的独特网络需求给 Kubernetes 带来了新的挑战。
具体工程实践中,这意味着供应商希望能够像加速虚拟机网络那样加速容器网络,虚拟机场景下所说的是 VNF(virtual network functions,虚拟网络功能),容器场景下所说的是 CNF(containerized network functions,容器化网络功能)。注意,在本系列中我们只讨论 L2 和 L3 的流量加速(类似上面对虚拟机的讨论),不会关注更高的网络层级。
VNFs 是软件形式的网络设备,例如路由器、防火墙、负载均衡,等,工程实践中,它们会被部署为一个或多个虚拟机。而 CNFs 只是容器化网络功能,仅对可移植性进行增强,而不是整个操作系统。

4. 传统 workloads 与 CNF

我们先澄清一下运行传统 IT workload 的典型容器与一个 CNF 之间的区别:
在一个典型应用中,Kubernetes pod(包括容器) 所提供的单一网络接口(eth0)足以满足大多数使用场景,并且还可以通过扩展 Kubernetes 网络模型以允许应用程序(通过 flannel、calico 或其他 CNI)访问集群外部。
但是电信行业的使用场景往往有着根本性的不同。它们可能需要在 L3 做路由功能:封装、解封装或 L2/L3 功能,同时还需要在大流量工况下保持低延迟。而以上这些功能无法仅通过 Kubernetes CNI 所提供的单 eth0 接口来完成,这也是我们要讨论 CNFs 以及如何加速它们的原因。
为了应对这些需求所带来的挑战,我们需要提供其他网络接口,以在标准的 Kubernetes 网络之外支持直接访问这些高容量的 L2/L3 网络。下一节中,我们将会讨论如何通过部署 Multus 方案来解决此难题。

5. Kubernetes CNI 插件以及 Multus 如何融入其中

基础的 Kubernetes 网络模型已经相当成功,对于很多应用程序来说已经足够。该方法的优点在于应用程序开发人员通常不需要了解底层的网络细节。Kubernetes 通过将 pod 对应用程序开发者呈现为一个带有单一接口的单一 host,以隐藏网络的复杂性。下图中我们可以看到标准 Kubernetes 网络模型的简洁性:
图片
图 1
Kubernetes 网络通过 CNI 插件实现在 Linux 容器中部署额外的网络功能。通常来说,这些 CNI 插件通过 overlays、IPAM、ingress、egress 等等来对 Kubernetes 网络进行扩展。举例来说,为企业级网络 fabric 添加 OVN(https://github.com/kubeovn/kube-ovn) 。它为通用的网络接口提供通用的 L3 网络服务(如 overlay)。
Kubernetes 网络非常适合网络服务应用,如 nginx。然而,网络 core 和 edge 对网络功能的需求大相径庭。Kubernetes 有一种 "let us do the driving" 的网络处理方法(译者注:意思是 Kubernetes 挺适合用来搞定容器网络的?)。尽管对于大多数应用程序开发者来说,Kubernetes 是一个优秀的容器编排平台,但其本身可能无法满足有高级网络服务需求的应用程序。
为了给 CNFs 提供更高级的网络服务,我们需要高速 L2 或 L3 接口进行直接数据收发的能力,而这肯定无法通过 Kubernetes 目前所提供的网络来完成。CNFs 需要在  Kubernetes 为 pod 所提供的“简单”接口(即 eth0)之外,支持更快的访问能力。需要能够为 Kubernetes pod “attach” 一个额外的网络接口,其允许应用程序通过第 2 层或第 3 层直接进行大流量的读写操作。 
幸运的是,有方案可以达成此目的。2017 年引入的 CNI 插件 Multus(https://github.com/k8snetworkplumbingwg/multus-cni),支持给 pod 添加多个网络接口。这些额外的接口允许将 pod attach 到额外的 layer3 domains、网络,或者“raw”layer2 接口上。需要强调的是,这些额外的网络接口完全独立于 Kubernetes 的网络设置,但仍可享受 Kubernetes 生命周期管理(attach、detach 等)机制所带来的便捷。
下图中可以看到通过部署 Multus CNI 给一个 pod 增添多个网络接口。Kubernetes pods 中除了 eth0 这个标准网络接口之外,还有一个额外的 net0 网络接口,其 attach 到未关联的外部 namespace 上,而该 namespace 可以是一个 host-based 数据平面(译者注:意思就是 host 上软件实现的后端设备,DPDK 或 vhost 等)或是一个外部的物理网络(译者注:支持 VF 的 SR-IOV 或 vDPA NIC 硬件)。同理,我们还可以添加 net1、net2,等等。
图片
图 2
注意:
  • Multus 是一个支持给 pod 添加多个网络接口的 CNI 插件。我们的场景下,先安装 Multus,Multus 安装好之后,使用另外一个 CNI 插件来提供一个额外的网络接口。
  • 如前文所言,正是由于 Multus 的存在,使得多种 CNI 插件的所用成为可能。Multus 允许对指定 pod 多次调用同一 delegate CNI 插件,或者对指定 pod 调用多个不同的 delegate(译者注:意思就是可以给一个 pod 创建多个同类型接口,或者多个不同类型的接口)。这使得可以给 pod 添加多个具有相同或不同特性的额外接口。
一个额外的接口需要一个 CNI 插件以及一个 device 插件。CNI 插件的作用是可以让新的接口被 Kubernetes 服务管理起来,device 插件的作用是提供 node 上硬件 specific 资源的细节信息(译者注:SR-IOV 或 vDPA 的 VFs)。本文例子中,device 插件提供了所新增网络接口的细节信息。

6. SR-IOV for 容器

本节聚焦可以支持一个 CNF 和一个物理 NIC 直连的 CNI 插件们。Single Root Input-Output Virtualization(SR/IOV) 作为一个已得到广泛应用的技术,由 NIC vendor 提供,可用于支持在用户空间直接对 NIC 进行访问。
SR-IOV 允许高性能加速物理网卡将其极高的带宽能力分割成多个 virtual functions(VF),并将这些 VF 给到一个虚拟机或用户空间应用程序(译者注:DPDK)进行 direct I/O。
本文例子展示如何让 VNFs 通过使用该技术,由一个零拷贝接口在 layer2 或 layer3 上直接访问高速网卡。
SR-IOV 同样也被广泛应用于 CNFs 上。它所提供的优势有:低延迟,充分利用基于硬件的 QoS,通过使用基于 DPDK 的用户空间网络实现高吞吐。本文后面会讲解如何通过这些技术来支持高速加速接口。
下面的例子演示用户空间网络。CNF 连接到 DPDK 并在 DPDK 中使用 virtio-user PMD。
后面会展示如何将 vDPA 和容器连起来。不过先讨论一下 SR-IOV 是怎么玩起来的,后续会看到它其实和 vDPA 很类似。SR-IOV 的内部细节,参考本号《vDPA 简介》《vDPA 深入》。
SR-IOV 的一个掣肘之处在于其有 vendor 硬件的 specific 依赖(译者注:guest 需要安装 vendor 硬件的 specific 驱动)。当应用于 CNFs 场景时,除非所有 node 上部署的 NICs 是完全一样的,否则在 node 之间想做到完全 portable 的 network function assignment,是很困难的。
要向 pod 添加带有额外网络接口的多个 CNIs,需要先安装 Multus。下图展示了使用基于 DPDK 的 CNF 架构图,其数据面完全 bypass 了 Linux 内核,IO 数据通过 SR-IOV 直接在 pod 的用户空间和 NIC VF 之间传递。
下图展示在 Kubernetes 中如何部署 SR-IOV:
图片
图 3
注意:
  • SR-IOV CNI 接口同时与 pod 和物理 NIC 打交道:其为 pod 提供加速接口(我们称之为 net0-SR-IOV),同时其对 NIC 进行配置(通过 NIC 的 PF 或 primary function)以设置给到 pod 的 VF 的属性。
  • SR-IOV device 插件负责在使用 SR-IOV 接口创建一个 pod 时,对 SR-IOV 资源(VFs)进行管理。其会连接至 Kubernetes device plugin manager。
  • 应用程序中的 vendor-VF-PMD 作为 DPDK 库的一部分,作用是对 NIC VFs 的控制面和数据面进行管理。
  • net0-SR-IOV 接口连接到 vendor-VF-PMD,并提供了一个访问物理 NIC 的接入点。
  • 具体施工中,我们会将容器用户空间直接映射给物理 NIC,从而通过零拷贝方案为 pod 实现接近 wirespeed/wirelatency。
  • 如前文所言,每一家 vendor 通过 SR-IOV 实现了其自己独有的数据面和控制面(举个例子,ring layout);因此每家不同 vendor NIC 需要不同的 vendor-VF-PMD。
上面这张 SR-IOV 大图中,我们通过部署 Multus 从而使用 SR-IOV CNI。要在 Kubernetes 中部署 SR-IOV,还需要使用 SR-IOV CNI(https://github.com/k8snetworkplumbingwg/sriov-cni)以及 device 插件。https://github.com/intel/SR-IOV-network-device-plugin 中有 SR-IOV CNI 的源码以及构建运行指南。

7. 通过 vDPA 加速 CNF

vDPA 是另一个给容器提供高性能网络接口的手法。vDPA 类似 SR-IOV,NIC 给用户空间 CNF 提供一个 virtual function,同样的,其可以将一个高速 NIC 和一个用户空间 DPDK 程序打通,从而作为一个 CNF。
虽然应用范围很广,但 SR-IOV 有其着实蛋疼之处,比如 ring 结构对于每个 vendor 的 NIC 来说都是独有的。同时,不同 NIC 的配置和控制各不相同,以及对每个 VF 缺少统一的配置、可选项。正是因为这些限制,VFs 需要部署在特定的裸金属服务器上,也就意味着 VNFs 在 host 之间的迁移不是那么容易的。
与之相反,vDPA 定义了统一的 virtio buffering scheme 开放标准(类似 virtio-user),NIC vendors 可以实现该标准。类似上面 SR-IOV 的例子,vDPA 接口也会导出 virtual function,但它相对 SR-IOV 的优势在于,其 ring layout 是遵循 virtio 标准的,这使得 CNF 更具可移植性。
至于 vDPA 与 SR-IOV 之间对比的细节以及其所能带来的价值,参考此前的几篇文章:《vDPA 简介》《vDPA 深入》。
下面继续讨论在 Kubernetes CNFs 中使用 vDPA。从 Kubernetes 看来,vDPA 与 SR-IOV 的相似之处在于其也包含了一个 CNI 插件和 device 插件。不过,它包含了一个 SR-IOV 所没有的额外组件,即 vDPA daemonset(守护进程集),vDPA daemonset 作用是与 NIC 通信并配置好 virtio buffering scheme。
在 vDPA 的加持下,如同 SR-IOV,数据面可以直接从 NIC VF 给到 pod 中的用户空间内存。
图片
图 4
注意:
  • vDPA CNI 同时与 pod 和物理 NIC 打交道(类似 SR-IOV):其为 pod 提供加速接口(这里称之为 virtio mdev 接口),同时其对 NIC 进行配置(通过 NIC 的 PF 或 primary function)以设置给到 pod 的 VF 的属性。vDPA 的作用就是通过 vDPA 框架以及 vendor vDPA 内核驱动,对不同 vendor 的 NIC 进行统一抽象。
  • vDPA device 插件负责在使用 vDPA 接口创建一个 pod 时,对 VF 资源进行管理(类似 SR-IOV)。其会连接至 Kubernetes device plugin manager。
  • 应用程序中的 virtio-net-PMD 作为 DPDK 库的一部分,作用是对控制面和数据面进行管理。这里需要强调的是,vDPA 与前文所述的 SR-IOV 的重要不同之处在于,不论使用哪个 vendor 的 NIC,所使用的 CNF 始终不变。具体来说,请注意,上图中无论我们使用的是哪个 vendor 的 NIC,pod 里面总是一个 virtio-net-PMD。
  • net0-virtio mdev 接口连接到 virtio-net-PMD,并提供对物理 NIC 的访问。不同之处在于,其在数据面中使用标准的 virtio ring layout,并使用 vDPA 作为标准的控制面。
  • vDPA 框架 + vDPA vendor 驱动是这一切能玩得转的核心所在。这里不再展开相关技术细节(《vDPA 简介》、《vDPA 深入》),从大图上来看,该部分提供了一个框架,每个 NIC vendor 都可以接入该框架。如此,只要 NIC vendor 在硬件中支持 virtio ring layout,它就可以维护自己独有的控制面,并通过添加自家的内核驱动(驱动接入此框架)来为容器和 vDPA CNIs 提供标准的 vDPA 接口。
  • 正如在 SR-IOV 例子中所指出的,具体施工中我们是将容器用户空间直接映射到物理 NIC,从而通过零拷贝实现这个 pod 的 wirespeed/wirelatency。
如前言部分所言,在 Kubernetes 中启用 vDPA 的工作尚在进行之中,社区正在讨论将该解决方案产品化到上游的可行之法。在这个 PoC 中我们做了一系列假设,并通过可能并非是最优解的方式将各组件连接起来,旨在演示所阐述的工作流原型。
本文以及 Kubecon POC 的例子中,我们将 vDPA 实现为一个 DPDK 用户空间实现,而不是使用 virtio-mdev 和 vhost-mdev 的 vDPA 内核实现。
vDPA deployment 项目(https://github.com/redhat-nfvpe/vdpa-deployment)包含了大多数最新的细节,以及如何将这些不同组件攒到一起的操作指导。

8. 总结

我们讨论了 Kubernetes 环境中基于 vDPA 加速的 CNFs。本文一上来对 Kubernetes 网络做了基本解释,并讨论了 CNFs 的一些特殊需求,而这些需求是基础 Kubernetes 网络接口所无法满足的,随后介绍了如何通过 Multus 在 pod 中启用额外的网络接口,并解释了这些额外的网络接口是怎样与用户空间的 DPDK 程序一起使用的。
本文中,我们还涉及了 SR-IOV CNF 加速,并讨论如何在 Kubernetes 中部署 SR-IOV CNI。讨论了 SR-IOV 的优势,以及与 Kubernetes 协同使用时的蛋疼之处。随后讨论通过开放标准接口来使用加速 NIC 的 vDPA 机制。最后,重点讨论了 vDPA 如何缓解 SR-IOV 的某些蛋疼之处,并审视了如何将 vDPA 整合进 Kubernetes。
回到电信行业的使用场景,我们相信将 vDPA 接口添加至 pods(通过 Multus)并使用 DPDK 是一个强有力的 pod 程序加速手段。vDPA 通过一个开放标准的方式(与 SR-IOV 相对)为 pods 提供 wirespeed/wirelatency。长远来看,vDPA 还会支持更高级的旨在取代 SR-IOV VFs 的技术(比如 scalable IOV)。此外,鉴于电信公司目前在 VNFs 上的巨大投入,我们认为将同一个 vDPA 内核接口同时应用于容器和虚拟机的能力,对未来的 brownfield 部署是至关重要的。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论