目录

RDMA-07-单网卡和双网卡方案对比

概述

公司内部采用的是 Netplugin 通过 OvS 创建的一个大二层网络。大二层是指整个容器网络都在同一个二层网络中运行,即所有的容器都在同一个广播域中。这意味着,所有容器都可以直接相互通信,而不需要进行路由或 NAT 等操作。

大二层网络方案的优点包括:

  1. 简单易用: 由于所有容器都在同一个二层网络中,因此不需要进行复杂的路由NAT配置,也不需要管理多个IP地址池或子网
  2. 高性能: 由于容器之间直接通信,因此可以获得更低的延迟和更高的吞吐量
  3. 更好的互操作性: 由于大二层网络与传统的数据中心网络相似,因此可以更容易地与现有的网络基础设施进行集成

然而,大二层网络方案也存在一些缺点:

  1. 安全性风险: 由于所有容器都在同一个二层网络中,因此容器之间的隔离性较差,容器之间的攻击风险较高
  2. 扩展性限制: 由于所有容器都在同一个广播域中,因此容器数量的增加可能会导致广播风暴等问题
  3. 管理复杂度: 由于所有容器都在同一个二层网络中,因此需要仔细管理和规划IP地址和子网,避免冲突和重叠

因此,是否采用大二层网络方案应该根据具体的应用场景和需求来决定。如果需要更高的安全性和扩展性,或者需要与现有的网络基础设施进行更深入的集成,则可以考虑使用其他网络方案,例如基于 VXLAN 的 Overlay 网络。

单网卡

要实现单网卡的 RDMA RoCEv2 容器,首先需要确保网卡支持 RDMA 和 RoCEv2 功能。然后,需要在容器宿主机上配置 SR-IOV 插件,使其能够将物理网卡虚拟化为多个虚拟网卡。接下来,在容器运行时配置中,可以将 SR-IOV 虚拟网卡直接映射到容器内部,从而实现容器对 SR-IOV 虚拟网卡的直接访问。这样,容器就可以使用 RDMA 和 RoCEv2 功能进行高性能的网络通信了。

需要注意的是,SR-IOV 插件需要配合容器运行时使用,不同的容器运行时可能需要不同的配置方式。此外,SR-IOV 虚拟网卡的数量是有限的,需要根据实际情况进行分配和管理。

SR-IOV 插件是需要的,因为不可能让一个物理机上只运行一个容器,又或者让不同的容器通过不同的端口来进行数据包的传输,这样会增加端口管理的复杂度,因此 SR-IOV 插件是需要部署的,比如说 k8s-rdma-shared-dev-plugin,当给容器分配分配到 VF 之后即可。

部署完之后,是否需要用 Multus 来做双网卡呢,这个分两种情况讨论。

服务器上的配置

在 SR-IOV 环境中,要给 Virtual Function (VF) 配置 VLAN,需要按照以下步骤操作: 确认 SR-IOV 环境中的 VF 的名称,例如 enp1s0f0v1. 在 Host 中创建一个 VLAN 接口,可以使用以下命令创建:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
sudo ip link add link enp1s0f0v1 name enp1s0f0v1.100 type vlan id 100
# 其中 enp1s0f0v1 是 VF 的名称,enp1s0f0v1.100 是新的 VLAN 接口名称,100 是要创建的 VLAN ID。
# 给 VLAN 接口配置 IP 地址和其他参数,可以使用以下命令配置:
sudo ip addr add 192.168.0.2/24 dev enp1s0f0v1.100
# 其中 192.168.0.2/24 是要配置的 IP 地址和子网掩码,enp1s0f0v1.100 是 VLAN 接口的名称。
sudo ip link set enp1s0f0v1.100 up
# 这会将 VLAN 接口设置为启用状态。
# 验证 VLAN 接口是否正常工作,可以使用以下命令来验证:
ip addr show enp1s0f0v1.100
# 这会显示 VLAN 接口的详细信息,包括配置的 IP 地址和 VLAN ID。
ping 192.168.0.1 -I enp1s0f0v1.100
# 这会使用 VLAN 接口的 IP 地址发送 ICMP 数据包到另一个 IP 地址 192.168.0.1,以测试 VLAN 接口的连通性。
# 请注意,这些命令是基于 CentOS/RHEL 操作系统,如果您使用的是其他操作系统,请查阅相应的文档以获得更多信息。
/rdma-07-%E5%8D%95%E7%BD%91%E5%8D%A1%E5%92%8C%E5%8F%8C%E7%BD%91%E5%8D%A1%E6%96%B9%E6%A1%88%E5%AF%B9%E6%AF%94/img.png

验证测试节点访问服务

从Pod看网络的基础网络

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 02:02:0A:BD:1A:EC
          inet addr:10.189.26.236  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::2:aff:febd:1aec/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1451 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:87096 (85.0 KiB)  TX bytes:648 (648.0 B)
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
tunl0     Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          NOARP  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

从 NetPlugin 看,节点收到创建的 Pod 的事件之后,会请求 http://10.199.175.66:9999/plugin/createEndpoint 来创建 EndPoint,同时获取容器的 IP,10.189.26.236。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
time="Feb 20 14:58:28.838520586" level=info msg="Handling \"add pod\" event"
time="Feb 20 14:58:28.840787838" level=info msg="Making REST request to url: http://10.199.175.66:9999/plugin/createEndpoint"
time="Feb 20 14:58:28.840845362" level=debug msg="Initializing admin token \"8daf3fc71fffc82d2a1206a7e0e10127b8ddc3685c27843d3f\"."
time="Feb 20 14:58:28.840860064" level=debug msg="Current authentication method is [token] "
time="Feb 20 14:58:28.840873624" level=debug msg="Contiv cluster post use admin token \"8daf3fc71fffc82d2a1206a7e0e10127b8ddc3685c27843d3f\"."
time="Feb 20 14:58:28.924472324" level=info msg="Results for (http://10.199.175.66:9999/plugin/createEndpoint): &{AssignedTenant:default AssignedNetwork:default-net EndpointConfig:{CommonState:{StateDriver:<nil> ID:default-net.default-e34cb498020d566d0626bc46c5fb943fe492ba936758b21fcdbbc9dd9f442540} PodName:sleep35 NetID:default-net.default EndpointID:e34cb498020d566d0626bc46c5fb943fe492ba936758b21fcdbbc9dd9f442540 ServiceName: EndpointGroupID:0 EndpointGroupKey: IPAddress:10.189.26.236 IPv6Address: MacAddress:02:02:0a:bd:1a:ec HomingHost:qa-k8s-1-node3 IntfName: VtepIP: Labels:map[] ContainerID: ContainerName: Rx_Bandwidth:104857600 Tx_Bandwidth:104857600 IPReservationID:}}\n"
time="Feb 20 14:58:28.924575634" level=debug msg="Got endpoint create resp from master: {AssignedTenant:default AssignedNetwork:default-net EndpointConfig:{CommonState:{StateDriver:<nil> ID:default-net.default-e34cb498020d566d0626bc46c5fb943fe492ba936758b21fcdbbc9dd9f442540} PodName:sleep35 NetID:default-net.default EndpointID:e34cb498020d566d0626bc46c5fb943fe492ba936758b21fcdbbc9dd9f442540 ServiceName: EndpointGroupID:0 EndpointGroupKey: IPAddress:10.189.26.236 IPv6Address: MacAddress:02:02:0a:bd:1a:ec HomingHost:qa-k8s-1-node3 IntfName: VtepIP: Labels:map[] ContainerID: ContainerName: Rx_Bandwidth:104857600 Tx_Bandwidth:104857600 IPReservationID:}}"
time="Feb 20 14:58:28.934579373" level=info msg="Creating Veth pairs with name: vport4489, vvport4489"
time="Feb 20 14:58:29.239697469" level=info msg="Current workmode for netplugin when [CreatePort] in [ovsSwitch] is []"
time="Feb 20 14:58:29.244940343" level=debug msg="==Unlock LocalEpInfoMutex=="
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# cat contiv_cni.conf
{
  "cniVersion": "0.1.0",
  "name": "contiv-poc",
  "type": "contivk8s.bin"
}
# pod的路由
# ip r
default via 10.189.26.1 dev eth0
10.189.26.0/24 dev eth0 proto kernel scope link src 10.189.26.236 # pod的ip
# node的路由
# ip r
default via 10.189.108.1 dev bond0.108
10.189.108.0/23 dev bond0.108  proto kernel  scope link  src 10.189.108.143
169.254.0.0/16 dev bond0  scope link  metric 1007
169.254.0.0/16 dev bond0.108  scope link  metric 1008

我的理解,Pod 的流量,先到 Pod 内的默认路由,eth0,eth0 实际是 ovs-switch 上的 vvport,如果目的地是在本节点,那么在 ovs-switch 就可以直接转发,如果是节点外的地址,就会走 node 上的路由。

直觉上,感觉只要插一条路由进去,就可以让 Pod 能够通信。

IP列表

IP 用途 其他
10.199.100.34 RDMA
10.199.100.35 RDMA
10.189.108.142 普通节点 验证网络
10.189.108.143 普通节点 -

HostNetwork

Pod-to-Pod

VLAN

1
2
3
4
# cat /proc/net/vlan/config
VLAN Dev name	 | VLAN ID
Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
bond0.108      | 108  | bond0

OVS

查询网桥。

1
2
# ovs-vsctl list-br
vlanbr0

将物理网卡桥接到网桥。

1
2
3
# ovs-vsctl show
        Port "bond0"
            Interface "bond0"

Pod 会将网卡桥接到网桥,实现同一个节点中的 Pod 的通信。

1
2
3
ovs-vsctl list interface
# ovs-ofctl dump-flows vlanbr0
cookie=0x0, duration=108285454.358s, table=0, n_packets=47448111827, n_bytes=8505336986295, priority=0 actions=NORMAL

远程直接内存访问 (RDMA) 是一种远程内存管理功能,它允许服务器到服务器的数据直接在应用程序内存之间移动,而无需任何 CPU 参与。RDMA over Converged Ethernet (RoCE) 是一种在无损以太网上以极低延迟提供高效数据传输的机制。随着可靠以太网上数据中心融合的进步,具有 RoCE 的 ConnectX® 以太网适配卡系列使用经过验证的高效 RDMA 传输,为以 10GigE 和 40GigE 链路速度在主流数据中心应用中部署 RDMA 技术提供平台。ConnectX® 以太网适配卡系列及其硬件卸载支持利用以太网上的这种高效 RDMA 传输 (InfiniBand) 服务,为财务、数据库、存储和内容交付等性能关键型和事务密集型应用程序提供超低延迟网络。 在以太网链路层上使用 RDMA 应用程序时,应注意以下几点:

  1. 结构中不需要子网管理器 (SM)。因此,需要与 SM 通信的操作在 RoCE 中以不同的方式进行管理。这不会影响 API,只会影响使用 API 时需要执行的操作,例如加入多播组
  2. 由于LID是InfiniBand协议栈的二层属性,不为端口设置,查询端口时显示为0
  3. 使用 RoCE,不会为 RC QP 设置备用路径。因此,不支持 APM(另一种高可用性和 InfiniBand 协议的一部分)
  4. 由于 SM 不存在,查询路径是不可能的。因此,在建立连接之前,路径记录结构必须填充相关值。因此,建议使用 RDMA-CM 建立连接,因为它负责填充路径记录结构
  5. VLAN 标记的以太网帧携带一个 3 位优先级字段。该字段的值是通过取 SL 字段的 3 个最低有效位从 IB SL 字段导出的
  6. RoCE 流量不会显示在关联的以太网设备的计数器中,因为它由硬件卸载并且不通过以太网网络驱动程序。RoCE 流量与 InfiniBand 流量统计在同一个地方;/sys/class/infiniband/<设备>/ports/<端口号>/counters/

RoCEv2

RoCE v2 在 ConnectX®-3 Pro 及更高版本的适配卡上受支持。 RoCE 协议的直接扩展使流量能够在 IP 第 3 层环境中运行。此功能是通过对 RoCE 数据包格式进行简单修改而获得的。代替 RoCE 中使用的 GRH,IP 可路由 RoCE 数据包携带一个 IP 标头,允许穿越 IP L3 路由器和一个 UDP 标头(仅限 RoCEv2),用作 RDMA 传输协议数据包的无状态封装层。 提议的 RoCEv2 数据包使用明确区分数据报的众所周知的 UDP 目标端口值。与使用 UDP 封装的其他协议类似,UDP 源端口字段用于携带不透明的流标识符,允许网络设备实现数据包转发优化(例如ECMP),同时保持对协议标头格式细节的不可知。 此外,由于此更改只影响线路上的数据包格式,并且由于使用 RDMA 语义数据包是在 AP 下方生成和使用的事实,因此应用程序可以以完全透明的方式在任何形式的 RDMA 服务上无缝运行。

/rdma-07-%E5%8D%95%E7%BD%91%E5%8D%A1%E5%92%8C%E5%8F%8C%E7%BD%91%E5%8D%A1%E6%96%B9%E6%A1%88%E5%AF%B9%E6%AF%94/img.png

参考配置

https://download.lenovo.com/servers/mig/2021/05/25/53912/mlnx-lnvgy_dd_nic_cx.ib-5.3-1.0.0.1-0_rhel7_x86-64.pdf

单节点PF

通过 RDMA 的 device plugin 给容器挂上 RDMA 设备,可以正常通过 ib_write_bw 的测试。

单节点多VF

VF 挂载还有点问题,需要花点时间再研究一下。

为什么需要SRIOV

RDMA(Remote Direct Memory Access)是一种高性能网络协议,它可以在不经过操作系统的情况下,直接在网络设备之间传输数据。RDMA网络卡通常使用InfiniBand或RoCE(RDMA over Converged Ethernet)等协议。而SR-IOV(Single Root Input/Output Virtualization)则是一种虚拟化技术,它可以将一块物理网卡虚拟化成多个逻辑网卡,每个逻辑网卡都可以被分配给不同的虚拟机或容器使用。

在使用RDMA网卡时,SR-IOV插件可以提供以下几个优点:1

  1. 提高网络性能: RDMA网卡可以直接访问物理内存,从而实现低延迟、高吞吐量的数据传输。但是,如果多个虚拟机或容器共享一块RDMA网卡,可能会造成网络拥塞,导致性能下降。通过使用SR-IOV插件,可以将一块物理RDMA网卡虚拟化成多个逻辑网卡,从而避免多个虚拟机或容器之间的竞争,提高网络性能
  2. 提高网络安全: 通过将物理RDMA网卡虚拟化成多个逻辑网卡,可以将不同的虚拟机或容器隔离开来,从而提高网络安全性
  3. 简化网络配置: 通过SR-IOV插件,可以在虚拟机或容器中直接使用虚拟化的逻辑网卡,而不需要在物理网卡上进行复杂的网络配置

因此,在使用RDMA网卡时,SR-IOV插件可以提供更好的网络性能、安全性和可管理性。

Netplugin的二层原理

Contiv netplugin 实现二层网络的原理是基于 Linux 的虚拟网络设备技术。当容器启动时,Contiv netplugin 会创建一个 veth 设备对,将其中一个端口连接到容器的虚拟网络接口中,将另一个端口连接到宿主机的网络接口中,从而将容器和宿主机的网络连接在一起。

HostNetwork的时候网络是怎么桥接的

使用的主机的网络命名空间。

参考资料

  1. OpenVswitch初探-VLAN篇
  2. Contiv netplugin部署文档
  3. 替代IB交换机,如何选择数据中心100G低时延网络设备
  4. RoCEv2/EVPN-VXLAN/MC-LAG部署
  5. 高性能计算:RoCE技术分析及应用
警告
本文最后更新于 2023年4月9日,文中内容可能已过时,请谨慎参考。