如何在 Amazon EKS 中部署 SR-IOV 设备插件

前言

随着云技术和容器的发展,越来越多的基于容器集群的通信负载开始在公有云上运行,通信负载对网络性能要求极高,因此广泛使用 SR-IOV 技术来提升网络的吞吐量和减少抖动,同时降低应用的 CPU 开销。

SR-IOV 的全称是 Single Root I/O Virtualization,SR-IOV 标准允许在虚拟机之间高效共享 PCIe(快速外设组件互连)设备,由于它是在硬件中实现的,所以可以获得能够与本机性能接近的 I/O 性能。SR-IOV 使用 physical functions (PF) 和 virtual functions (VF) 为 SR-IOV 设备管理全局功能。PF 包含 SR-IOV 功能的完整 PCIe 设备,PF 作为普通的 PCIe 设备被发现、管理和配置 。PF 通过分配 VF 来配置和管理 SR-IOV 功能。

VF 是轻量级 PCIe 功能(I/O 处理)的 PCIe 设备,每个 VF 都是通过 PF 来生成管理的,VF 的具体数量限制受限于 PCIe 设备自身配置及驱动程序的支持,启用 SR-IOV 后,主机将在一个物理 NIC 上创建单个 PF 和多个 VF。VF 的数量取决于配置和驱动程序支持。

Amazon EKS 是一项托管服务,借助该服务,您可以轻松在亚马逊云科技上运行 Kubernetes,而无需安装和操作您自己的 Kubernetes 控制面板或工作线程节点。Kubernetes 会将容器安排到各个逻辑分组以便进行管理和查找,然后在 Amazon Elastic Compute Cloud (Amazon EC2) 实例集群上启动它们。

本文介绍如何在 Amazon EKS 中安装 SR-IOV 设备插件,从而可以实现通信负载不需要进行部署文件修改就可以在云上进行部署,同时可以在 Pod 层面进行灵活配置 EC2 的接口 IP 地址。

SR-IOV 网络设备插件介绍

SR-IOV 网络设备插件可以帮助 K8s 对宿主机的网络资源 SR-IOV 的虚拟功能(VF)和 PCI 物理功能(PF)进行发现和宣告。

3581b1ccb1f4d4bbdb08fae5049e343e.png

该插件可以实现如下功能:

  • 支持基于内核和命名空间(UIO and VFIO)的设备的驱动

  • 允许使用 K8S 的 selector 进行资源分组

  • 允许用户可以自由定义资源名称

  • 检测 Kubelet 重启并且自动重注册

  • 检测链路状态并相应地更新 VFs 资源状态

  • 以最小的开销支持新的设备类型

使用该插件部署负载的时候,需要和其他的 CNI 一起使用:

(1)支持基于设备的网络开通的 CNI 插件,譬如 Multus,或者 DANM 插件

该插件可以获取 Pod 的已经分配的网络设备的信息

(2)具备消费分配给 Pod 的网络设备的 CNI,譬如 SR-IOV CNI, VPC CNI

该插件可以在 Pod 创建的时候,使用插件已知的信息,将分配好的 SR-IOV 的 VF 注入到 Pods 网络的命名空间。在 Pod 删除的时候,重置并释放 VF 信息。

部署 SR-IOV 设备插件前提条件:

  • 一个已经创建成功的 EKS 集群,使用 EC2 作为 worker,并且可以 ssh 登录

  • EKS 集群上安装了 Multus 插件,并且使用 EC2 作为计算资源。EC2 上创建多网口,可以参考使用如下文章提供的方案:

    https://aws.amazon.com/cn/blogs/containers/amazon-eks-now-supports-multus-cni/

  • 本机安装 kubectl 软件,可以参考如下链接进行安装:

    https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html

部署 SR-IOV 网络设备插件步骤

(1)创建 ConfigMap,运行如下命令:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": {
                "resourceName": "sriov_dpdk_n3",
                "selectors": {
                    "vendors": ["1d0f"],
                    "devices": ["ec20"],
                    "drivers": ["ena"],
                    "pciAddresses": ["0000:00:06.0"]
                }
            }            
    }
EOF

左滑查看更多

其中:

  • resourceName 可以根据实际配置命名

  • vendors 和 drivers 请不要修改

  • drivers 可以填 ena,表示直接使用 ena 网卡

  • pciAddresses 需要根据实际要配置的网络接口填写,登录到 Worker 的 EC2,运行 dmesg 命令,寻找如下关键词:

ena 0000:00:06.0: Elastic Network Adapter (ENA) found at mem febf4000, mac addr 0a:e1:52:6c:01:9d

左滑查看更多

根据 mac 地址(0a:e1:52:6c:01:9d)可以匹配到相应的 PciAddresses(0000:00:06.0

),我们还需要匹配接口名称和 mac 地址,运行如下命令:

ifconfig | grep -3 '0a:e1:52:6c:01:9d'
eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 172.31.12.46  netmask 255.255.240.0  broadcast 172.31.15.255
        inet6 fe80::8e1:52ff:fe6c:19d  prefixlen 64  scopeid 0x20<link>
        ether 0a:e1:52:6c:01:9d  txqueuelen 1000  (Ethernet)
        RX packets 1133569  bytes 320227183 (305.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1291997  bytes 799804159 (762.7 MiB)

左滑查看更多

这样我们就得到 PciAddresses:0000:00:06.0对应的接口是 eth2。该对应信息在创建网络和测试 pod 的时候需要。

(2)创建 daemonset

从如下链接获取 sriovdp-daemonset.yam 文件:

https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin/blob/master/deployments/k8s-v1.16/sriovdp-daemonset.yaml

运行:

kubectl apply -f  sriovdp-daemonset.yaml

左滑查看更多

运行成功后,运行如下命令:

kubectl get nodes
kubectl  describe node ip-192-168-2-97.cn-northwest-1.compute.internal

左滑查看更多

其中ip-192-168-2-97.cn-northwest-1.compute.internal是由kubectl get nodes得到的。

我们可以看到如下信息,SR-IOV 设备就成为了 pod 的一个可以分配的网络资源:

Allocatable:
  attachable-volumes-aws-ebs:         25
  cpu:                                                 15890m
  ephemeral-storage:                        18242267924
  hugepages-1Gi:                              8Gi
  intel.com/sriov_dpdk_n3:               1
  memory:                                         20676900Ki
  pods:                                              234

左滑查看更多

使用和验证 SR-IOV 设备插件

使用SRIOV插件,首先我们需要创建一个 NetworkAttachmentDefinition,修改并运行如下命令,其中:

  • Type 填入 host-device

  • device 填入我们使用的 EC2 的网络接口名字,示例为 eth2

  • PciBusID 填入网络接口对应的 PciBusID

cat <<EOF | kubectl apply -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: sriov-net1-n3
spec:
  config: '{
      "cniVersion": "0.3.1",
      "type": "host-device",
      "device": "eth2",
      "pciBusID": "0000:00:06.0"
    }'
EOF

左滑查看更多

创建一个testpod,指定网络设备为我们创建的 NetworkAttachmentDefinition:sriov-net1-n3,运行如下命令:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: testpod1
  annotations:
    k8s.v1.cni.cncf.io/networks: sriov-net1-n3
spec:
  containers:
  - name: test-ubuntu
    image: public.ecr.aws/ubuntu/ubuntu:latest
    securityContext:
      allowPrivilegeEscalation: true
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"]
    imagePullPolicy: IfNotPresent
    command: ["sh", "-c", "trap : TERM INT; sleep infinity & wait"]
    args: [ "while true; do sleep 300000; done;" ]
EOF

左滑查看更多

下面我们来测试一下这个接口,首先登录到我们创建的 Pod,运行如下命令:

Kubectl exec -it testpod1 -- sh

左滑查看更多

我们还需要安装一些工具进行 IP 配置以及测试:

apt-get update
apt-get install net-tools
apt-get install iputils-ping
apt-get install 
apt-get install sudo

运行:

ifconfig -a

其中 eth0 是 EKS 给 pod 创建的默认接口,这里可以看到我们创建的 SR-IOV 接口 net1:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 192.168.2.7  netmask 255.255.255.255  broadcast 0.0.0.0
        ether 56:96:46:56:54:4a  txqueuelen 0  (Ethernet)
        RX packets 9823  bytes 23050026 (23.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7280  bytes 517793 (517.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

net1: flags=4098<BROADCAST,MULTICAST>  mtu 9001
        ether 02:b1:a5:4e:52:ea  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

左滑查看更多

此时,如果我们登录到该 pod 对应的 EC2 上运行 ifconfig,会发现对应的接口 eth2 已经不可见,已经被我们的 testpod 独占。

运行以下命令,可以给 net1 配置 IP 地址(此处以192.168.2.111为例),因为 eth2 被 Pod 独占,因此我们可以给 pod 配置任意的在 eth2 所关联的子网的 IP 地址。如果配置的 IP 地址和 EC2 的 eth2 不一样,我们必须要关闭 EC2 的 Source / destination check 才可以使该 IP 地址生效:

ifconfig net1 192.168.2.111 
sudo ifconfig net1 up

配置完毕,运行如下命令进行测试:

# ping 192.168.2.1 -I net1
PING 192.168.2.1 (192.168.2.1) from 192.168.2.111 net1: 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=20 ttl=255 time=0.058 ms

左滑查看更多

看到 ping 回复包,表示配置成功。

总结

本文详细介绍如何在  Amazon EKS 上部署 SR-IOV 设备插件,介绍了如何使用该插件,如何设置参数,以及如何获取相应的参数和它们之间的对应关系,通过部署 SR-IOV 设备插件,使用 SR-IOV 的应用可以平滑从其他的云平台迁移到亚马逊云平台以及 EKS。

本篇作者

0f03891b75e3afe982ef308a365da26c.jpeg

赵康

亚马逊云科技解决方案架构师,专注于 telco 以及相关的领域云架构设计和咨询。

6e454295894a9fc606d399dcc651e3d3.png

莫梓元

亚马逊云科技解决方案架构师,有着超过5年的云计算领域从业经验,工作中担任过解决方案、售前、研发、实施、运维等多种角色。加入亚马逊云科技之前,作为技术骨干负责中国联通基于 OpenStack 的沃云平台自研工作。

db2ce5a21a087a4c007ee30b3805aebe.gif

afafcc0c6457b48847950f42c06ea6ce.gif

听说,点完下面4个按钮

就不会碰到bug了!

53981d6a82bfccbbdc38ec79099c061f.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值