Kubernetes插件:Intel sriov-cni插件简介/修改
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插件简介/修改相关推荐
- 关于kubernetes的CNI插件说明
https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md https://kubernetes.io/zh/docs/co ...
- 如何在 Amazon EKS 中部署 SR-IOV 设备插件
前言 随着云技术和容器的发展,越来越多的基于容器集群的通信负载开始在公有云上运行,通信负载对网络性能要求极高,因此广泛使用 SR-IOV 技术来提升网络的吞吐量和减少抖动,同时降低应用的 CPU 开销 ...
- Kubernetes网络与CNI插件介绍
文章目录 Kubernetes网络总体架构图 kubernetes使用CNI网络插件的工作流程 k8s如何使用CNI kubernetes官方文档介绍CNI CNI简介 CNI原理 参考文献 Kube ...
- kubernetes 【CNI插件】Flannel使用详解
文章目录 1. 介绍 2. Flannel实现原理 2.1 原理说明 2.2 数据转发流程 3. Flannel安装配置 3.1 环境准备 3.2 安装etcd 3.3 安装flannel 3.4 配 ...
- 从零开始入门 K8s | 理解 CNI 和 CNI 插件
简介: 网络架构是 K8s 中较为复杂的方面之一.K8s 网络模型本身对某些特定的网络功能有着一定的要求,因此,业界已经有了不少的网络方案来满足特定的环境和要求.CNI 意为容器网络的 API 接口, ...
- kubelet配置cni插件_从零开始入门 K8s | 理解 CNI 和 CNI 插件
原标题:从零开始入门 K8s | 理解 CNI 和 CNI 插件 作者 | 溪恒 阿里巴巴高级技术专家 本文整理自<CNCF x Alibaba 云原生技术公开课>第 26 讲,点击直达课 ...
- 浅谈k8s cni 插件
目前不论是个人还是企业,在使用k8s时,都会采用CNI作为集群网络方案实现的规范. 在早先的k8s版本中,kubelet代码里提供了networkPlugin,networkPlugin是一组接口,实 ...
- kubelet配置cni插件_Kubernetes CNI网络插件
CNI 容器网络接口,就是在网络解决方案由网络插件提供,这些插件配置容器网络则通过CNI定义的接口来完成,也就是CNI定义的是容器运行环境与网络插件之间的接口规范.这个接口只关心容器的网络连接,在创建 ...
- 理解CNI和CNI插件
理解CNI和CNI插件 本文将主要分享以下几方面的内容: CNI 是什么? Kubernetes 中如何使用 CNI? 哪个 CNI 插件适合我? 如何开发自己的 CNI 插件? 一.CNI 是什么 ...
- 21. 理解CNI和CNI插件
本文由 CNCF + Alibaba 云原生技术公开课 整理而来 CNI CNI 的全称是 Container Network Interface,即容器网络的 API 接口. CNI 是 Kuber ...
最新文章
- mNGS及古细菌DNA检测应用推荐:PCR去污染试剂盒
- word-break:break-all和 word-wrap:break-word区别
- 返回用户指定页面的web服务器
- MIT_18.03_微分方程_Laplace_Transform_拉普拉斯变换_Notes
- 爬虫 无访问权限“_Windows10电脑系统共享打印机无访问权限解决方法
- 第一类Stirling数和第二类Stirling
- 解决笔记本重装问题(VISTA系统改为XP系统)
- 进程间通信————无名管道
- Android10不能用谷歌,谷歌真的很严格,一大波老APP将不能在安卓10.0运行
- 读取gps观测数据o文件的matlab编程,读取GPS观测数据O文件的matlab编程.doc
- Hi3516A开发--电阻分压阻值计算
- 万恶之源的hello world
- css里的英文翻译,css常见英文翻译
- 装配式施工在建筑装修中的应用研究
- CSDN BLOG技术专家群工作平台发布公告
- 从某一点出发沿任意一方向旋转矩阵计算思考与实现
- 超参数优---贝叶斯优化及其改进(PBT优化)
- 时隔二十年,C++又杀回来了!
- 复旦大学计算机系杨希希,复旦大学研究生招生信息网_复旦大学考研信息网-研究生招生报名查询系统...
- 论文阅读:Analyzing Third Party Service Dependencies in Modern Web Services
热门文章
- 视频/图像 人像分割/Matting数据集
- 蓝桥杯2017赛题‘瓷砖样式’
- excel 公式 单引号 concat_excel数据提取技巧:从混合文本中提取数字的万能公式...
- ***大论文中插入Visio不失真方法:word插入viso图片方法
- PhotoMOS MOSFET光控继电器控制电路
- Lambda何晓阳:白皮书不能改是愚蠢的,区块链在探索中前进
- rails 自定义主键_带有Rails 6 Webpacker和turbolink的自定义和第三方javascript指南
- 病毒分析系列2 | 使用PE工具进行初步静态分析
- 双十一运动好物推荐,运动爱好者不能错过的好物清单
- windows平台上编写的python无法在unix_【判断题】在Windows平台上编写的Python程序无法在Unix平台运行...