github blog:https://xftony.github.io

sriov-cni简介

sriov-cni是hustcat/sriov-cni开发的一种容器网络插件(Container Network Interface),它使得容器可以直接使用物理机中扩展出来的VF(virtual functions)。Intel在此基础上,为其添加了dpdk功能。本文介绍的sriov-cni的版本为Intel版,修改也是基于Intel版本进行的修改。

sriov-cni代码简介

sriov-cni主要通过调用netlink包将vf修改到容器的namespace下,使得VF可以被容器直接调用。其中VF是指支持SRIOV的物理网卡所虚拟出的一个“网卡”或者说虚出来的一个实例,它会以一个独立网卡的形式呈现出来,每一个VF有它自己独享的PCI配置区域,并且可能与其他VF共享着同一个物理资源(公用同一个物理网口)
根据cni的标准定义两个函数cmdAdd和cmdDel,分别用于VF的添加和删除skel.PluginMain(cmdAdd, cmdDel)
cmdAdd和cmdDel基本是一对反过程,所以这里就只简单介绍一下cmdAdd函数。

 func cmdAdd(args *skel.CmdArgs) error {n, err := loadConf(args.StdinData) // 将输入参数转化为NetConf变量nif err != nil {return fmt.Errorf("failed to load netconf: %v", err)}// 获取container的net命名空间,args.Netns是container的在host中的网络命名空间路径netns, err := ns.GetNS(args.Netns)if err != nil {return fmt.Errorf("failed to open netns %q: %v", netns, err)}defer netns.Close()if n.IF0NAME != "" {args.IfName = n.IF0NAME}// 核心函数,配置VF,将VF移动到container的命名空间if err = setupVF(n, n.IF0, args.IfName, args.ContainerID, netns); err != nil {return fmt.Errorf("failed to set up pod interface %q from the device %q: %v", args.IfName, n.IF0, err)}// 在DPDK 和L2模式下, 无需调用IPAM进行IP分配var result *types.Resultif n.DPDKMode != false || n.L2Mode != false {return result.Print()}// 调用IPAM插件,并返回配置result, err = ipam.ExecAdd(n.IPAM.Type, args.StdinData)if err != nil {return fmt.Errorf("failed to set up IPAM plugin type %q from the device %q: %v", n.IPAM.Type, n.IF0, err)}if result.IP4 == nil {return errors.New("IPAM plugin returned missing IPv4 config")}err = netns.Do(func(_ ns.NetNS) error {return ipam.ConfigureIface(args.IfName, result)})if err != nil {return err}result.DNS = n.DNS//返回分配结果return result.Print()
}

下面简单介绍一下sriov-cni的核心函数setupVF(),其基本实现步骤是,通过if0找到可用的VF,并设置为up,然后将VF移动到container的网络命名空间,重命名为ifName,即container内部看到的网卡名称

func setupVF(conf *NetConf, ifName string, podifName string, cid string, netns ns.NetNS) error {var vfIdx intvar infos []os.FileInfovar pciAddr string//通过ifName获取if0,即mm, err := netlink.LinkByName(ifName)if err != nil {return fmt.Errorf("failed to lookup master %q: %v", conf.IF0, err)}// 通过读取/sys/class/net/<if0>/device/sriov_numvfs 文件获取VF个数vfTotal, err := getsriovNumfs(ifName)if err != nil {return err}if vfTotal <= 0 {return fmt.Errorf("no virtual function in the device %q: %v", ifName)}//遍历PF目录下的VF,找到一个满足条件的VFfor vf := 0; vf <= (vfTotal - 1); vf++ {vfDir := fmt.Sprintf("/sys/class/net/%s/device/virtfn%d/net", ifName, vf)if _, err := os.Lstat(vfDir); err != nil {if vf == (vfTotal - 1) {return fmt.Errorf("failed to open the virtfn%d dir of the device %q: %v", vf, ifName, err)}continue}infos, err = ioutil.ReadDir(vfDir)if err != nil {return fmt.Errorf("failed to read the virtfn%d dir of the device %q: %v", vf, ifName, err)}if (len(infos) == 0) && (vf == (vfTotal - 1)) {return fmt.Errorf("no Virtual function exist in directory %s, last vf is virtfn%d", vfDir, vf)}if (len(infos) == 0) && (vf != (vfTotal - 1)) {continue}if len(infos) == maxSharedVf {conf.Sharedvf = true}if len(infos) <= maxSharedVf {vfIdx = vf//获取PCI地址, host上“/sys/class/net/<if0>/device/<VF>”pciAddr, err = getpciaddress(ifName, vfIdx)if err != nil {return fmt.Errorf("err in getting pci address - %q", err)}break} else {return fmt.Errorf("mutiple network devices in directory %s", vfDir)}}// VF NIC nameif len(infos) != 1 && len(infos) != maxSharedVf {return fmt.Errorf("no virutal network resources avaiable for the %q", conf.IF0)}if conf.Sharedvf != false && conf.L2Mode != true {return fmt.Errorf("l2enable mode must be true to use shared net interface %q", conf.IF0)}if conf.Vlan != 0 {if err = netlink.LinkSetVfVlan(m, vfIdx, conf.Vlan); err != nil {return fmt.Errorf("failed to set vf %d vlan: %v", vfIdx, err)}if conf.Sharedvf {if err = setSharedVfVlan(ifName, vfIdx, conf.Vlan); err != nil {return fmt.Errorf("failed to set shared vf %d vlan: %v", vfIdx, err)}}}//如果是dpdk模式,为DPDKConf结构体赋值,if conf.DPDKMode != false {conf.DPDKConf.PCIaddr = pciAddrconf.DPDKConf.Ifname = podifNameconf.DPDKConf.VFID = vfIdx//配置文件以 containID-If0name 方式命名, 将其保存在conf.CNIDir目录下,即配置文件中cniDir,默认“/var/lib/cni/sriov”//注意在k8s中这里的containID是pod中pod-container的id,而不是pod内真正执行服务的container的id。if err = savedpdkConf(cid, conf.CNIDir, conf); err != nil {return err}//调用dpdk_tool脚本,更新VF驱动,划重点return enabledpdkmode(&conf.DPDKConf, infos[0].Name(), true)}// Sort links name if there are 2 or more PF links found for a VF;if len(infos) > 1 {// sort Links FileInfo by their Link indicessort.Sort(LinksByIndex(infos))}for i := 1; i <= len(infos); i++ {vfDev, err := netlink.LinkByName(infos[i-1].Name())if err != nil {return fmt.Errorf("failed to lookup vf device %q: %v", infos[i-1].Name(), err)}//调用netlink库函数实现set link up, 类似`ip link set $link up`if err = netlink.LinkSetUp(vfDev); err != nil {return fmt.Errorf("failed to setup vf %d device: %v", vfIdx, err)}// 将VF移动到container的命名空间,类似`ip link set $link netns $ns`if err = netlink.LinkSetNsFd(vfDev, int(netns.Fd())); err != nil {return fmt.Errorf("failed to move vf %d to netns: %v", vfIdx, err)}}return netns.Do(func(_ ns.NetNS) error {ifName := podifNamefor i := 1; i <= len(infos); i++ {if len(infos) == maxSharedVf && i == len(infos) {ifName = podifName + fmt.Sprintf("d%d", i-1)}//将该VF重命名为ifNameerr := renameLink(infos[i-1].Name(), ifName)if err != nil {return fmt.Errorf("failed to rename %d vf of the device %q to %q: %v", vfIdx, infos[i-1].Name(), ifName, err)}// for L2 mode enable the pod net interfaceif conf.L2Mode != false {err = setUpLink(ifName)if err != nil {return fmt.Errorf("failed to set up the pod interface name %q: %v", ifName, err)}}}return nil})
}

sriov修改版介绍

sriov实现了container中调用host VF的功能,在使用时也发现了一切不足之处(或许是我了解不足导致的误解,如是,请指正),例如:

1、sriov-cni在保存dpdk配置的后,若dpdk驱动更新可能失败,但是配置不会被删除;
2、在k8s下使用,其保存dpdk配置的时候,使用的是pod-container-id(k8s会为每个pod创建一个container以提供相应网络服务等),对于container无法识别其被分配到的VF,因为container可以看到所有的包括分配给其他container的VF;(这里它目的可能只是为了保存删除时需要的信息,但是container内存在需要使用其dpdk信息的场景,所以可以修改一下)
3、sriov-cni进保存dpdk模式的配置信息,对于普通的sriov不会进行配置信息的保存;
4、不支持直接使用PF。

对应修改:

1、保存dpdk配置文件和开启dpdk驱动的代码顺序对调,保证在启动更新成功的情况下才会保存配置文件;
2、配置文件路径添加一级容器网络命名空间ID,从而使得容器内可以识别自身的配置文件;
3、添加netconf的配置保存;
4、类似VF,添加setupPF(),实现与setupVF()基本一致。

针对上述的“问题”,我做了一个修改版的,亲测可用。 自提
把这个/bin/sriov文件放到/opt/cni/bin/下即可

Kubernetes插件:Intel sriov-cni插件简介/修改相关推荐

  1. 关于kubernetes的CNI插件说明

    https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md https://kubernetes.io/zh/docs/co ...

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

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

  3. Kubernetes网络与CNI插件介绍

    文章目录 Kubernetes网络总体架构图 kubernetes使用CNI网络插件的工作流程 k8s如何使用CNI kubernetes官方文档介绍CNI CNI简介 CNI原理 参考文献 Kube ...

  4. kubernetes 【CNI插件】Flannel使用详解

    文章目录 1. 介绍 2. Flannel实现原理 2.1 原理说明 2.2 数据转发流程 3. Flannel安装配置 3.1 环境准备 3.2 安装etcd 3.3 安装flannel 3.4 配 ...

  5. 从零开始入门 K8s | 理解 CNI 和 CNI 插件

    简介: 网络架构是 K8s 中较为复杂的方面之一.K8s 网络模型本身对某些特定的网络功能有着一定的要求,因此,业界已经有了不少的网络方案来满足特定的环境和要求.CNI 意为容器网络的 API 接口, ...

  6. kubelet配置cni插件_从零开始入门 K8s | 理解 CNI 和 CNI 插件

    原标题:从零开始入门 K8s | 理解 CNI 和 CNI 插件 作者 | 溪恒 阿里巴巴高级技术专家 本文整理自<CNCF x Alibaba 云原生技术公开课>第 26 讲,点击直达课 ...

  7. 浅谈k8s cni 插件

    目前不论是个人还是企业,在使用k8s时,都会采用CNI作为集群网络方案实现的规范. 在早先的k8s版本中,kubelet代码里提供了networkPlugin,networkPlugin是一组接口,实 ...

  8. kubelet配置cni插件_Kubernetes CNI网络插件

    CNI 容器网络接口,就是在网络解决方案由网络插件提供,这些插件配置容器网络则通过CNI定义的接口来完成,也就是CNI定义的是容器运行环境与网络插件之间的接口规范.这个接口只关心容器的网络连接,在创建 ...

  9. 理解CNI和CNI插件

    理解CNI和CNI插件 本文将主要分享以下几方面的内容: CNI 是什么? Kubernetes 中如何使用 CNI? 哪个 CNI 插件适合我? 如何开发自己的 CNI 插件? 一.CNI 是什么 ...

  10. 21. 理解CNI和CNI插件

    本文由 CNCF + Alibaba 云原生技术公开课 整理而来 CNI CNI 的全称是 Container Network Interface,即容器网络的 API 接口. CNI 是 Kuber ...

最新文章

  1. mNGS及古细菌DNA检测应用推荐:PCR去污染试剂盒
  2. word-break:break-all和 word-wrap:break-word区别
  3. 返回用户指定页面的web服务器
  4. MIT_18.03_微分方程_Laplace_Transform_拉普拉斯变换_Notes
  5. 爬虫 无访问权限“_Windows10电脑系统共享打印机无访问权限解决方法
  6. 第一类Stirling数和第二类Stirling
  7. 解决笔记本重装问题(VISTA系统改为XP系统)
  8. 进程间通信————无名管道
  9. Android10不能用谷歌,谷歌真的很严格,一大波老APP将不能在安卓10.0运行
  10. 读取gps观测数据o文件的matlab编程,读取GPS观测数据O文件的matlab编程.doc
  11. Hi3516A开发--电阻分压阻值计算
  12. 万恶之源的hello world
  13. css里的英文翻译,css常见英文翻译
  14. 装配式施工在建筑装修中的应用研究
  15. CSDN BLOG技术专家群工作平台发布公告
  16. 从某一点出发沿任意一方向旋转矩阵计算思考与实现
  17. 超参数优---贝叶斯优化及其改进(PBT优化)
  18. 时隔二十年,C++又杀回来了!
  19. 复旦大学计算机系杨希希,复旦大学研究生招生信息网_复旦大学考研信息网-研究生招生报名查询系统...
  20. 论文阅读:Analyzing Third Party Service Dependencies in Modern Web Services

热门文章

  1. 视频/图像 人像分割/Matting数据集
  2. 蓝桥杯2017赛题‘瓷砖样式’
  3. excel 公式 单引号 concat_excel数据提取技巧:从混合文本中提取数字的万能公式...
  4. ***大论文中插入Visio不失真方法:word插入viso图片方法
  5. PhotoMOS MOSFET光控继电器控制电路
  6. Lambda何晓阳:白皮书不能改是愚蠢的,区块链在探索中前进
  7. rails 自定义主键_带有Rails 6 Webpacker和turbolink的自定义和第三方javascript指南
  8. 病毒分析系列2 | 使用PE工具进行初步静态分析
  9. 双十一运动好物推荐,运动爱好者不能错过的好物清单
  10. windows平台上编写的python无法在unix_【判断题】在Windows平台上编写的Python程序无法在Unix平台运行...