当前位置: 首页 > 科技观察

一开始就了解一下容器网络接口CNI

时间:2023-03-12 12:28:26 科技观察

周末写这篇文章的时候,发现自己可能给自己挖了个大坑。整个Kubernetes网关相关的内容会非常复杂和庞大。深入探索Kubernetes网络模型和网络通信理解容器网络接口CNI源码分析(本文):从kubelet和容器运行时看CNI的使用从FlannelKubernetesVXLAN网络CiliumCNI和eBPF学习...看看能学到什么一步到位~在《深入探索 Kubernetes 网络模型和网络通信》一文中,我们介绍了网络命名空间(networknamespace)在Kubernetes网络模型中的工作原理,并通过实例分析了pod之间的流量传输路径。整个传输过程需要各种组件的参与,这些组件与pod有着相同的生命周期,伴随着pod的创建和销毁。容器的维护由kubelet委托给容器运行时(containerruntime),容器的网络命名空间由容器运行时委托的网络插件完成。创建pod(容器)网络namespace创建interface创建veth为namespace网络设置静态路由配置以太网桥分配IP地址创建NAT规则...在上一篇文章中我们也提到了不同的网络插件有不同的Kubernetes网络模型的实现,主要侧重于跨节点的pod间通信的实现。用户可以根据自己的需要选择合适的网络插件,这离不开CNI(容器网络接口)。这些网络插件实现了CNI标准,可以很好地与容器编排系统和运行时集成。runtime-with-cniCNI是什么?CNI是CNCF下的一个项目。除了提供最重要的规范[1]、用于CNI和应用程序集成的库[2]以及用于实现CNI插件的CLI`cnitool`[3]和一个可引用的插件[4]。在发布本文时,最新版本是v1.1.2。CNI只关注容器的网络连接,并在容器销毁时清理/释放分配的资源。正因为如此,即使容器发展迅速,CNI仍然可以保持简单并得到广泛支持[5]。CNI规范CNI的规范包括以下几个部分:网络配置文件格式容器运行时与网络插件交互的协议插件的执行过程,会将其他插件的执行过程委托给执行结果返回给运行时的数据类型1.网络配置格式这里贴出规范中的配置示例。规范[6]定义了网络配置的格式,包括必填字段、可选字段以及每个字段的功能。示例用法定义了一个名为dbnet的网络,并配置了插件bridge和tuning这两个插件。CNI插件一般分为两种:接口插件(interfaceplug-in):用于创建网络接口,如例子中的网桥。链式插件(chained):用于调整创建的网络接口,如例子中的调整。{"cniVersion":"1.0.0","name":"dbnet","plugins":[{"type":"bridge",//插件具体参数"bridge":"cni0","keyA":["somemore","pluginspecific","configuration"],"ipam":{"type":"host-local",//ipamspecific"subnet":"10.1.0.0/16","gateway":“10.1.0.1”,“路线”:[{“dst”:“0.0.0.0/0”}]},“dns”:{“名称服务器”:[“10.1.0.1”]}},{“类型”:“调整”,“能力”:{“mac”:真},“sysctl”:{“net.core.somaxconn”:“500”}},{“类型”:“portmap”,“能力”:{"portMappings":true}}]}2.容器运行时与网络插件交互的协议CNI为容器运行时提供了四种不同的操作[7]:ADD——将容器添加到网络中,或者修改配置DEL-from删除网络中的容器,或者取消修改CHECK-检查容器网络是否正常,如果容器网络有问题,返回错误VERSION-显示插件的版本说明给define操作的输入输出内容。主要核心字段为:CNI_COMMAND:以上四种操作之一CNI_CONTAINERID:容器IDCNI_NETNS:容器的隔离域,如果使用网络命名空间,这里的值为网络命名空间的地址CNI_IFNAME:要在container创建的接口名称,如eth0CNI_ARGS:执行时传递的参数CNI_PATH:插件可执行文件的路径3.插件CNI的执行过程转换ADD、DELETE和CHECK操作容器上的网络配置成一个附件。容器网络配置的运行需要一个或多个插件共同运行,因此插件有一定的执行顺序。例如,在前面的示例配置中,必须先创建接口,然后才能调整接口。以ADD操作为例,一般先执行接口插件,再执行链式插件。上一个插件的输出PrevResult和下一个插件的配置会作为下一个插件的输入。如果它是第一个插件,它将把网络配置作为输入的一部分。插件可以使用前一个插件的PrevResult作为自己的输出,或者用自己的操作更新PrevResult。最后一个plugin的输出PrevResult作为CNI的执行结果返回给containerruntime,containerruntime会保存修改后的结果作为其他操作的输入。DELETE的执行顺序刚好和ADD的顺序相反。必须删除接口上的配置或释放分配的IP,才能删除容器网络接口。DELETE操作的输入是容器运行时保存的ADD操作的结果。cni-plugin-execution-flow除了定义单个操作中插件的执行顺序外,还对操作的并行操作和重复操作进行了解释[8]。4.插件委托有一些操作,无论出于何种原因,都不能合理地作为一个松散链接的插件来实现。相反,CNI插件可能希望将某些功能委托给另一个插件。一个常见的例子是IPAddressManagement(简称IPAM),主要是为容器接口分配/回收IP地址,管理路由等。CNI定义了第三种插件——IPAM插件。CNI插件可以在适当的时候调用IPAM插件,IPAM插件将执行结果返回给客户端。IPAM插件会根据指定的协议(如dhcp)、本地文件中的数据,或网络配置文件中ipam字段中的信息完成操作:分配IP、设置网关、路由等。"ipam":{"type":"host-local",//特定于ipam"subnet":"10.1.0.0/16","gateway":"10.1.0.1","routes":[{"dst":“0.0.0.0/0”}]}5。执行结果插件可以返回以下三种结果之一,规范定义了结果的格式[9]。Success:还会包含PrevResult信息,比如ADD操作返回容器runtime后的PrevResult。错误:包含必要的错误信息。version:这是VERSION操作的返回结果。LibraryCNI的库是指`libcni`[10],用于CNI和应用的集成,定义了CNI相关的接口和配置。类型CNI接口{AddNetworkList(ctxcontext.Context,net*NetworkConfigList,rt*RuntimeConf)(types.Result,error)CheckNetworkList(ctxcontext.Context,net*NetworkConfigList,rt*RuntimeConf)errorDelNetworkList(ctxcontext.Context,net*NetworkConfigList,rt*RuntimeConf)错误GetNetworkListCachedResult(net*NetworkConfigList,rt*RuntimeConf)(types.Result,error)GetNetworkListCachedConfig(net*NetworkConfigList,rt*RuntimeConf)([]byte,*RuntimeConf,error)AddNetwork(ctxcontext.上下文,网络*NetworkConfig,rt*RuntimeConf)(类型。结果,错误)CheckNetwork(ctxcontext.Context,net*NetworkConfig,rt*RuntimeConf)错误DelNetwork(ctxcontext.Context,net*NetworkConfig,rt*RuntimeConf)错误GetNetworkCachedResult(net*NetworkConfig,rt*RuntimeConf)(types.Result,error)GetNetworkCachedConfig(net*NetworkConfig,rt*RuntimeConf)([]byte,*RuntimeConf,错误)ValidateNetworkList(ctxcontext.Context,net*NetworkConfigList)([]string,error)ValidateNetwork(ctxcontext.Context,net*NetworkConfig)([]string,error)}以部分网络代码为例:func(c*CNIConfig)addNetwork(ctxcontext.Context,name,cniVersionstring,net*NetworkConfig,prevResulttypes.Result,rt*RuntimeConf)(types.Result,error){...返回调用.ExecPluginWithResult(ctx,pluginPath,newConf.Bytes,c.args("ADD",rt),c.exec)}执行逻辑很简单:找到可执行文件,加载网络配置,执行ADD操作结果处理总结本文学习了CNI规范的内容和网络插件的执行过程,对CNI抽象的网管接口有了一个大概的了解。下一篇文章将结合源码分析,了解kubelet、容器运行时、CNI网络插件是如何交互的。参考https://www.tigera.io/learn/guides/kubernetes-networking/kubernetes-cni/https://github.com/containernetworking/cnihttps://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/参考[1]规范:https://github.com/containernetworking/cni/blob/main/SPEC.md[2]库:https://github.com/containernetworking/cni/blob/main/libcni[3]cnitool:https://github.com/containernetworking/cni/blob/main/cnitool[4]可参考插件:https://github.com/containernetworking/plugins[5]广泛支持:https://github.com/containernetworking/cni/blob/main/README.md#who-is-using-cni[6]规范:https://github.com/containernetworking/cni/blob/main/SPEC.md#section-1-network-configuration-format[7]四种不同的操作:https://github.com/containernetworking/cni/blob/master/SPEC.md#cni-operations[8]]CNI也解释了并行操作和重复操作的操作:https://github.com/containernetworking/cni/blob/main/SPEC.md#lifecycle--ordering[9]结果格式:https://github.com/containernetworking/cni/blob/main/SPEC.md#section-5-result-types[10]libcni:https://github.com/containernetworking/cni/tree/main/libcni