{"value":"前言\n\n随着云技术和容器的发展,越来越多的基于容器集群的通信负载开始在公有云上运行,通信负载对网络性能要求极高,因此广泛使用 SR-IOV 技术来提升网络的吞吐量和减少抖动,同时降低应用的 CPU 开销。\n\n\n\nSR-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 功能。\n\n\n\nVF 是轻量级 PCIe 功能(I/O 处理)的 PCIe 设备,每个 VF 都是通过 PF 来生成管理的,VF 的具体数量限制受限于 PCIe 设备自身配置及驱动程序的支持,启用 SR-IOV 后,主机将在一个物理 NIC 上创建单个 PF 和多个 VF。VF 的数量取决于配置和驱动程序支持。\n\n\n\n[Amazon EKS](https://aws.amazon.com/cn/eks/?trk=cndc-detail) 是一项托管服务,借助该服务,您可以轻松在亚马逊云科技上运行 Kubernetes,而无需安装和操作您自己的 Kubernetes 控制面板或工作线程节点。Kubernetes 会将容器安排到各个逻辑分组以便进行管理和查找,然后在 Amazon Elastic Compute Cloud (Amazon EC2) 实例集群上启动它们。\n\n\n\n本文介绍如何在 [Amazon EKS](https://aws.amazon.com/cn/eks/?trk=cndc-detail) 中安装 SR-IOV 设备插件,从而可以实现通信负载不需要进行部署文件修改就可以在云上进行部署,同时可以在 Pod 层面进行灵活配置 EC2 的接口 IP 地址。\n\n\n\n\n\nSR-IOV 网络设备插件介绍\n\nSR-IOV 网络设备插件可以帮助 K8s 对宿主机的网络资源 SR-IOV 的虚拟功能(VF)和 PCI 物理功能(PF)进行发现和宣告。\n\n\n\n![4c5c45d3caf596dfb13b7bc596ac3a03.png](https://dev-media.amazoncloud.cn/4ac443080828488c965332724eead59f_4c5c45d3caf596dfb13b7bc596ac3a03.png)\n\n\n该插件可以实现如下功能:\n\n\n\n支持基于内核和命名空间(UIO and VFIO)的设备的驱动\n\n允许使用 K8S 的 selector 进行资源分组\n\n允许用户可以自由定义资源名称\n\n检测 Kubelet 重启并且自动重注册\n\n检测链路状态并相应地更新 VFs 资源状态\n\n以最小的开销支持新的设备类型\n\n\n\n使用该插件部署负载的时候,需要和其他的 CNI 一起使用:\n\n\n\n(1)支持基于设备的网络开通的 CNI 插件,譬如 Multus,或者 DANM 插件\n\n\n\n该插件可以获取 Pod 的已经分配的网络设备的信息\n\n\n\n(2)具备消费分配给 Pod 的网络设备的 CNI,譬如 SR-IOV CNI, VPC CNI\n\n\n\n该插件可以在 Pod 创建的时候,使用插件已知的信息,将分配好的 SR-IOV 的 VF 注入到 Pods 网络的命名空间。在 Pod 删除的时候,重置并释放 VF 信息。\n\n\n\n部署 SR-IOV 设备插件前提条件:\n\n\n\n一个已经创建成功的 EKS 集群,使用 EC2 作为 worker,并且可以 ssh 登录\n\nEKS 集群上安装了 Multus 插件,并且使用 EC2 作为计算资源。EC2 上创建多网口,可以参考使用如下文章提供的方案:\n\nhttps://aws.amazon.com/cn/blogs/containers/amazon-eks-now-supports-multus-cni/\n\n\n\n本机安装 kubectl 软件,可以参考如下链接进行安装:\n\nhttps://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html\n\n\n\n部署 SR-IOV 网络设备插件步骤\n\n(1)创建 ConfigMap,运行如下命令:\n\n\n![c800074a4af10550bdea13c77f0d6be.jpg](https://dev-media.amazoncloud.cn/d0b3cc6535924b0da2a425c74061c706_c800074a4af10550bdea13c77f0d6be.jpg)\n\n其中:\n\n\nresourceName 可以根据实际配置命名\n\nvendors 和 drivers 请不要修改\n\ndrivers 可以填 ena,表示直接使用 ena 网卡\n\npciAddresses 需要根据实际要配置的网络接口填写,登录到 Worker 的 EC2,运行 dmesg 命令,寻找如下关键词:\n\n\n![fe34179641d5e9403e1896784b508ee.jpg](https://dev-media.amazoncloud.cn/fb9263342e584206835349670b65afb0_fe34179641d5e9403e1896784b508ee.jpg)\n\n\n\n根据 mac 地址(0a:e1:52:6c:01:9d)可以匹配到相应的 PciAddresses(0000:00:06.0\n\n),我们还需要匹配接口名称和 mac 地址,运行如下命令:\n\n\n![093715ab9220c6f67793eee7090de6a.png](https://dev-media.amazoncloud.cn/a0fc920cd5844a819d5f927cf77798d4_093715ab9220c6f67793eee7090de6a.png)\n\n\n\n这样我们就得到 PciAddresses:0000:00:06.0对应的接口是 eth2。该对应信息在创建网络和测试 pod 的时候需要。\n\n\n\n(2)创建 daemonset\n\n\n\n从如下链接获取 sriovdp-daemonset.yam 文件:\n\n\n\nhttps://github.com/k8snetworkplumbingwg/sriov-network-device-plugin/blob/master/deployments/k8s-v1.16/sriovdp-daemonset.yaml\n\n\n\n运行:\n\n\n![692b048db95a5c9f9d8c997f5d6d4d3.png](https://dev-media.amazoncloud.cn/c953e3071d0f4130a6bdee4893964812_692b048db95a5c9f9d8c997f5d6d4d3.png)\n\n\n\n运行成功后,运行如下命令:\n\n\n![f40cbc95a6e69fd0246dcb922e0ad69.png](https://dev-media.amazoncloud.cn/1ca6150b8e604e3693bb4e4785dc74fe_f40cbc95a6e69fd0246dcb922e0ad69.png)\n\n\n\n\n其中ip-192-168-2-97.cn-northwest-1.compute.internal是由kubectl get nodes得到的。\n\n\n\n我们可以看到如下信息,SR-IOV 设备就成为了 pod 的一个可以分配的网络资源:\n\n\n![d86db1fe4a52d24b773ba8120efb01d.png](https://dev-media.amazoncloud.cn/4dcb4e01624640b99596463fba8df08b_d86db1fe4a52d24b773ba8120efb01d.png)\n\n\n\n使用和验证 SR-IOV 设备插件\n\n使用SRIOV插件,首先我们需要创建一个 NetworkAttachmentDefinition,修改并运行如下命令,其中:\n\n\n\nType 填入 host-device\n\ndevice 填入我们使用的 EC2 的网络接口名字,示例为 eth2\n\nPciBusID 填入网络接口对应的 PciBusID\n\n\n![b950d6f5dc79af035dd7a4780aaf599.png](https://dev-media.amazoncloud.cn/48acb0879f9b4b3287ef8de803f38553_b950d6f5dc79af035dd7a4780aaf599.png)\n\n\n创建一个testpod,指定网络设备为我们创建的 NetworkAttachmentDefinition:sriov-net1-n3,运行如下命令:\n\n\n![9e2f84f6994602c1040913a9221bbee.png](https://dev-media.amazoncloud.cn/3af9c7de4cfa488da5a65b6faadac444_9e2f84f6994602c1040913a9221bbee.png)\n\n\n\n下面我们来测试一下这个接口,首先登录到我们创建的 Pod,运行如下命令:\n\n\n\n![67bffc0662d10539cbba4cd5190a4a0.png](https://dev-media.amazoncloud.cn/d35b6a2a2b274b08a98553cda87bdbb0_67bffc0662d10539cbba4cd5190a4a0.png)\n\n\n\n\n我们还需要安装一些工具进行 IP 配置以及测试:\n\n\n\n![b6d89eeaf18e78a88d30516be236997.png](https://dev-media.amazoncloud.cn/6d08811b8a474c10b0a6545b5abe818e_b6d89eeaf18e78a88d30516be236997.png)\n\n\n运行:\n\n\n\n![7e10cd1f5bd564525002afeb410ae54.png](https://dev-media.amazoncloud.cn/5ae9f136cf94493494594358c56c5193_7e10cd1f5bd564525002afeb410ae54.png)\n\n\n\n\n其中 eth0 是 EKS 给 pod 创建的默认接口,这里可以看到我们创建的 SR-IOV 接口 net1:\n\n\n\n![8ba6adae6e3e83757d1410a6c9c21c3.png](https://dev-media.amazoncloud.cn/65ed795b92f04ab689b67c85f8c66a4c_8ba6adae6e3e83757d1410a6c9c21c3.png)\n\n\n\n此时,如果我们登录到该 pod 对应的 EC2 上运行 ifconfig,会发现对应的接口 eth2 已经不可见,已经被我们的 testpod 独占。\n\n\n\n运行以下命令,可以给 net1 配置 IP 地址(此处以192.168.2.111为例),因为 eth2 被 Pod 独占,因此我们可以给 pod 配置任意的在 eth2 所关联的子网的 IP 地址。如果配置的 IP 地址和 EC2 的 eth2 不一样,我们必须要关闭 EC2 的 Source / destination check 才可以使该 IP 地址生效:\n\n\n\n![c6e9c9c2e40abc1bcd806e0c6432ec2.png](https://dev-media.amazoncloud.cn/5f81d23e11584693b107f6505ec3c178_c6e9c9c2e40abc1bcd806e0c6432ec2.png)\n\n\n\n配置完毕,运行如下命令进行测试:\n\n\n![55f00f48610cee820353f4b48b906ed.png](https://dev-media.amazoncloud.cn/2eb8dc98e47c4a8a8edcd22abdb81775_55f00f48610cee820353f4b48b906ed.png)\n\n\n\n\n\n看到 ping 回复包,表示配置成功。\n\n\n\n总结\n\n本文详细介绍如何在 [Amazon EKS](https://aws.amazon.com/cn/eks/?trk=cndc-detail) 上部署 SR-IOV 设备插件,介绍了如何使用该插件,如何设置参数,以及如何获取相应的参数和它们之间的对应关系,通过部署 SR-IOV 设备插件,使用 SR-IOV 的应用可以平滑从其他的云平台迁移到亚马逊云平台以及 EKS。\n\n\n![1666362954774.png](https://dev-media.amazoncloud.cn/cfd73b3eec314a5a9747aef2536b778b_1666362954774.png)\n\n","render":"<p>前言</p>\n<p>随着云技术和容器的发展,越来越多的基于容器集群的通信负载开始在公有云上运行,通信负载对网络性能要求极高,因此广泛使用 SR-IOV 技术来提升网络的吞吐量和减少抖动,同时降低应用的 CPU 开销。</p>\n<p>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 功能。</p>\n<p>VF 是轻量级 PCIe 功能(I/O 处理)的 PCIe 设备,每个 VF 都是通过 PF 来生成管理的,VF 的具体数量限制受限于 PCIe 设备自身配置及驱动程序的支持,启用 SR-IOV 后,主机将在一个物理 NIC 上创建单个 PF 和多个 VF。VF 的数量取决于配置和驱动程序支持。</p>\n<p>Amazon EKS 是一项托管服务,借助该服务,您可以轻松在亚马逊云科技上运行 Kubernetes,而无需安装和操作您自己的 Kubernetes 控制面板或工作线程节点。Kubernetes 会将容器安排到各个逻辑分组以便进行管理和查找,然后在 Amazon Elastic Compute Cloud (Amazon EC2) 实例集群上启动它们。</p>\n<p>本文介绍如何在 Amazon EKS 中安装 SR-IOV 设备插件,从而可以实现通信负载不需要进行部署文件修改就可以在云上进行部署,同时可以在 Pod 层面进行灵活配置 EC2 的接口 IP 地址。</p>\n<p>SR-IOV 网络设备插件介绍</p>\n<p>SR-IOV 网络设备插件可以帮助 K8s 对宿主机的网络资源 SR-IOV 的虚拟功能(VF)和 PCI 物理功能(PF)进行发现和宣告。</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/4ac443080828488c965332724eead59f_4c5c45d3caf596dfb13b7bc596ac3a03.png\\" alt=\\"4c5c45d3caf596dfb13b7bc596ac3a03.png\\" /></p>\n<p>该插件可以实现如下功能:</p>\n<p>支持基于内核和命名空间(UIO and VFIO)的设备的驱动</p>\n<p>允许使用 K8S 的 selector 进行资源分组</p>\n<p>允许用户可以自由定义资源名称</p>\n<p>检测 Kubelet 重启并且自动重注册</p>\n<p>检测链路状态并相应地更新 VFs 资源状态</p>\n<p>以最小的开销支持新的设备类型</p>\n<p>使用该插件部署负载的时候,需要和其他的 CNI 一起使用:</p>\n<p>(1)支持基于设备的网络开通的 CNI 插件,譬如 Multus,或者 DANM 插件</p>\n<p>该插件可以获取 Pod 的已经分配的网络设备的信息</p>\n<p>(2)具备消费分配给 Pod 的网络设备的 CNI,譬如 SR-IOV CNI, VPC CNI</p>\n<p>该插件可以在 Pod 创建的时候,使用插件已知的信息,将分配好的 SR-IOV 的 VF 注入到 Pods 网络的命名空间。在 Pod 删除的时候,重置并释放 VF 信息。</p>\n<p>部署 SR-IOV 设备插件前提条件:</p>\n<p>一个已经创建成功的 EKS 集群,使用 EC2 作为 worker,并且可以 ssh 登录</p>\n<p>EKS 集群上安装了 Multus 插件,并且使用 EC2 作为计算资源。EC2 上创建多网口,可以参考使用如下文章提供的方案:</p>\n<p>https://aws.amazon.com/cn/blogs/containers/amazon-eks-now-supports-multus-cni/</p>\n<p>本机安装 kubectl 软件,可以参考如下链接进行安装:</p>\n<p>https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html</p>\n<p>部署 SR-IOV 网络设备插件步骤</p>\n<p>(1)创建 ConfigMap,运行如下命令:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/d0b3cc6535924b0da2a425c74061c706_c800074a4af10550bdea13c77f0d6be.jpg\\" alt=\\"c800074a4af10550bdea13c77f0d6be.jpg\\" /></p>\n<p>其中:</p>\n<p>resourceName 可以根据实际配置命名</p>\n<p>vendors 和 drivers 请不要修改</p>\n<p>drivers 可以填 ena,表示直接使用 ena 网卡</p>\n<p>pciAddresses 需要根据实际要配置的网络接口填写,登录到 Worker 的 EC2,运行 dmesg 命令,寻找如下关键词:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/fb9263342e584206835349670b65afb0_fe34179641d5e9403e1896784b508ee.jpg\\" alt=\\"fe34179641d5e9403e1896784b508ee.jpg\\" /></p>\n<p>根据 mac 地址(0a:e1:52:6c:01:9d)可以匹配到相应的 PciAddresses(0000:00:06.0</p>\n<p>),我们还需要匹配接口名称和 mac 地址,运行如下命令:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/a0fc920cd5844a819d5f927cf77798d4_093715ab9220c6f67793eee7090de6a.png\\" alt=\\"093715ab9220c6f67793eee7090de6a.png\\" /></p>\n<p>这样我们就得到 PciAddresses:0000:00:06.0对应的接口是 eth2。该对应信息在创建网络和测试 pod 的时候需要。</p>\n<p>(2)创建 daemonset</p>\n<p>从如下链接获取 sriovdp-daemonset.yam 文件:</p>\n<p>https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin/blob/master/deployments/k8s-v1.16/sriovdp-daemonset.yaml</p>\n<p>运行:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/c953e3071d0f4130a6bdee4893964812_692b048db95a5c9f9d8c997f5d6d4d3.png\\" alt=\\"692b048db95a5c9f9d8c997f5d6d4d3.png\\" /></p>\n<p>运行成功后,运行如下命令:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/1ca6150b8e604e3693bb4e4785dc74fe_f40cbc95a6e69fd0246dcb922e0ad69.png\\" alt=\\"f40cbc95a6e69fd0246dcb922e0ad69.png\\" /></p>\n<p>其中ip-192-168-2-97.cn-northwest-1.compute.internal是由kubectl get nodes得到的。</p>\n<p>我们可以看到如下信息,SR-IOV 设备就成为了 pod 的一个可以分配的网络资源:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/4dcb4e01624640b99596463fba8df08b_d86db1fe4a52d24b773ba8120efb01d.png\\" alt=\\"d86db1fe4a52d24b773ba8120efb01d.png\\" /></p>\n<p>使用和验证 SR-IOV 设备插件</p>\n<p>使用SRIOV插件,首先我们需要创建一个 NetworkAttachmentDefinition,修改并运行如下命令,其中:</p>\n<p>Type 填入 host-device</p>\n<p>device 填入我们使用的 EC2 的网络接口名字,示例为 eth2</p>\n<p>PciBusID 填入网络接口对应的 PciBusID</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/48acb0879f9b4b3287ef8de803f38553_b950d6f5dc79af035dd7a4780aaf599.png\\" alt=\\"b950d6f5dc79af035dd7a4780aaf599.png\\" /></p>\n<p>创建一个testpod,指定网络设备为我们创建的 NetworkAttachmentDefinition:sriov-net1-n3,运行如下命令:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/3af9c7de4cfa488da5a65b6faadac444_9e2f84f6994602c1040913a9221bbee.png\\" alt=\\"9e2f84f6994602c1040913a9221bbee.png\\" /></p>\n<p>下面我们来测试一下这个接口,首先登录到我们创建的 Pod,运行如下命令:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/d35b6a2a2b274b08a98553cda87bdbb0_67bffc0662d10539cbba4cd5190a4a0.png\\" alt=\\"67bffc0662d10539cbba4cd5190a4a0.png\\" /></p>\n<p>我们还需要安装一些工具进行 IP 配置以及测试:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/6d08811b8a474c10b0a6545b5abe818e_b6d89eeaf18e78a88d30516be236997.png\\" alt=\\"b6d89eeaf18e78a88d30516be236997.png\\" /></p>\n<p>运行:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/5ae9f136cf94493494594358c56c5193_7e10cd1f5bd564525002afeb410ae54.png\\" alt=\\"7e10cd1f5bd564525002afeb410ae54.png\\" /></p>\n<p>其中 eth0 是 EKS 给 pod 创建的默认接口,这里可以看到我们创建的 SR-IOV 接口 net1:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/65ed795b92f04ab689b67c85f8c66a4c_8ba6adae6e3e83757d1410a6c9c21c3.png\\" alt=\\"8ba6adae6e3e83757d1410a6c9c21c3.png\\" /></p>\n<p>此时,如果我们登录到该 pod 对应的 EC2 上运行 ifconfig,会发现对应的接口 eth2 已经不可见,已经被我们的 testpod 独占。</p>\n<p>运行以下命令,可以给 net1 配置 IP 地址(此处以192.168.2.111为例),因为 eth2 被 Pod 独占,因此我们可以给 pod 配置任意的在 eth2 所关联的子网的 IP 地址。如果配置的 IP 地址和 EC2 的 eth2 不一样,我们必须要关闭 EC2 的 Source / destination check 才可以使该 IP 地址生效:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/5f81d23e11584693b107f6505ec3c178_c6e9c9c2e40abc1bcd806e0c6432ec2.png\\" alt=\\"c6e9c9c2e40abc1bcd806e0c6432ec2.png\\" /></p>\n<p>配置完毕,运行如下命令进行测试:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/2eb8dc98e47c4a8a8edcd22abdb81775_55f00f48610cee820353f4b48b906ed.png\\" alt=\\"55f00f48610cee820353f4b48b906ed.png\\" /></p>\n<p>看到 ping 回复包,表示配置成功。</p>\n<p>总结</p>\n<p>本文详细介绍如何在 Amazon EKS 上部署 SR-IOV 设备插件,介绍了如何使用该插件,如何设置参数,以及如何获取相应的参数和它们之间的对应关系,通过部署 SR-IOV 设备插件,使用 SR-IOV 的应用可以平滑从其他的云平台迁移到亚马逊云平台以及 EKS。</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/cfd73b3eec314a5a9747aef2536b778b_1666362954774.png\\" alt=\\"1666362954774.png\\" /></p>\n"}