21. 理解CNI和CNI插件

本文由 CNCF + Alibaba 云原生技术公开课 整理而来

CNI

CNI 的全称是 Container Network Interface,即容器网络的 API 接口。

CNI 是 Kubernetes 中标准的一个调用网络实现的接口。Kubelet 通过这个标准的 API 来调用不同的网络插件以实现不同的网络配置方式。实现了这个接口的就是 CNI 插件,它实现了一系列的 CNI API 接口。常见的 CNI 插件包括 CalicoFlannelTerwayWeave Net 以及 Contiv


Kubernetes 使用 CNI

Kubernetes 通过 CNI 配置文件来决定使用什么 CNI。基本的使用方法为:

1. 首先在每个结点上配置 CNI 配置文件(/etc/cni/net.d/xxnet.conf),其中 xxnet.conf 是某一个网络配置文件的名称;

2. 安装 CNI 配置文件中所对应的二进制插件;

3. 在这个节点上创建 Pod 之后,Kubelet 就会根据 CNI 配置文件执行前两步所安装的 CNI 插件;

4. 上步执行完之后,Pod 的网络就配置完成了。

具体的流程如下图所示:

在这里插入图片描述

在集群里面创建一个 Pod 的时候,首先会通过 ApiServerPod 的配置写入,ApiServer 的一些管控组件(比如 Scheduler)会调度到某个具体的节点上去。Kubelet 监听到这个 Pod 的创建之后,会在本地进行一些创建的操作。

当执行到创建网络这一步骤时,首先它会读取配置目录中的配置文件,配置文件里面会声明所使用的是哪一个插件,然后去执行具体的 CNI 插件的二进制文件,再由 CNI 插件进入 Pod 的网络空间去配置 Pod 的网络。配置完成之后,Kubelet 也就完成了整个 Pod 的创建过程,这个 Pod 就在线了。

作为一个用户去使用 CNI 插件的话就比较简单,因为很多 CNI 插件都已提供了一键安装的能力。以常用的 Flannel 为例,只需要使用 kubectl apply Flannel 的一个 Deploying 模板,它就能自动地将配置、二进制文件安装到每一个节点上去。

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

安装完之后,整个集群的 CNI 插件就安装完成了。

因此,如果只是去使用 CNI 插件的话,其实很多 CNI 插件已经提供了一键安装的脚本,无需关心 Kubernetes 内部是如何配置的以及如何调用 API 的。


CNI 插件选择

社区有很多的 CNI 插件,比如 Calico, Flannel, Terway 等。那么在一个具体的生产环境中,要选择哪一个 CNI 插件呢?

这就要从 CNI 的几种实现模式说起,需要根据不同的场景选择不同的实现模式,再去选择对应的具体某一个插件。

通常来说,CNI 插件可以分为三种:Overlay、路由、Underlay

在这里插入图片描述

Overlay 模式:典型特征是容器独立于主机的 IP 段,这个 IP 段进行跨主机网络通信时是通过在主机之间创建隧道的方式,将整个容器网段的包全都封装成底层的物理网络中主机之间的包。
              该方式的好处在于它不依赖于底层网络;
 

路由模式:主机和容器也分属不同的网段,它与 Overlay 模式的主要区别在于它的跨主机通信是通过路由打通,无需在不同主机之间做一个隧道封包。
          但路由打通就需要部分依赖于底层网络,比如说要求底层网络有二层可达的一个能力;
 

Underlay 模式:容器和宿主机位于同一层网络,两者拥有相同的地位。容器之间网络的打通主要依靠于底层网络。因此该模式是强依赖于底层能力的。

了解了以上三种常用的实现模式之后,再根据自己的环境、需求判断可由哪一种模式进行实现,再在对应的模式中去找 CNI 插件。不过社区中有那么多插件,它们又都属于哪种模式?如何进行选择呢?怎么挑选适合自己的呢?可以从以下 3 个方面来考虑。

在这里插入图片描述

  • 环境限制:
虚拟化环境:虚拟化环境(例如 OpenStack)中的网络限制较多,比如不允许机器之间直接通过二层协议访问,必须要带有 IP 地址这种三层的才能去做转发,限制某一个机器只能使用某些 IP 等。
            在这种被做了强限制的底层网络中,只能去选择 Overlay 的插件,常见的有 Flannel-vxlan, Calico-ipip, Weave 等等;
 

物理机环境:物理机环境中底层网络的限制较少,比如在同一个交换机下面直接做一个二层的通信。对于这种集群环境,可以选择 Underlay 或者路由模式的插件。
            Underlay 意味着可以直接在一个物理机上插多个网卡或者是在一些网卡上做硬件虚拟化;路由模式就是依赖于 Linux 的路由协议做一个打通。
            这样就避免了像 vxlan 的封包方式导致的性能降低。这种环境下可选的插件包括 clico-bgp, flannel-hostgw, sriov 等等;
 

公有云环境:公有云环境也是虚拟化,因此底层限制也会较多。但每个公有云都会考虑适配容器,提升容器的性能,因此每家公有云可能都提供了一些 API 去配置一些额外的网卡或者路由这种能力。
            在公有云上,要尽量选择公有云厂商提供的 CNI 插件以达到兼容性和性能上的最优。比如 Aliyun 就提供了一个高性能的 Terway 插件。

环境限制考虑完之后,我们心中应该都有一些选择了,知道哪些能用、哪些不能用。在这个基础上,我们再去考虑功能上的需求。

  • 功能需求:
安全需求:Kubernetes 支持 NetworkPolicy,就是可以通过 NetworkPolicy 的一些规则去支持“Pod 之间是否可以访问”这类策略。
          但不是每个 CNI 插件都支持 NetworkPolicy 的声明,如果大家有这个需求,可以选择支持 NetworkPolicy 的一些插件,比如 Calico, Weave 等;


是否需要集群外的资源与集群内的资源互联互通:应用最初都是在虚拟机或者物理机上,容器化之后,应用无法一下就完成迁移,因此就需要传统的虚拟机或者物理机能跟容器的 IP 地址互通。
          为了实现这种互通,就需要两者之间有一些打通的方式或者直接位于同一层。此时可以选择 Underlay 的网络,比如 sriov 这种就是 Pod 和以前的虚拟机或者物理机在同一层。
          也可以使用 calico-bgp,此时它们虽然不在同一网段,但可以通过它去跟原有的路由器做一些 BGP 路由的一个发布,这样也可以打通虚拟机与容器;

 

Kubernetes 的服务发现与负载均衡的能力:Kubernetes 的服务发现与负载均衡就是 Service,但并不是所有的 CNI 插件都能实现这两种能力。
          比如很多 Underlay 模式的插件,在 Pod 中的网卡是直接用的 Underlay 的硬件,或者通过硬件虚拟化插到容器中的,这个时候它的流量无法走到宿主机所在的命名空间,因此也无法应用 kube-proxy 在宿主机配置的规则。

          这种情况下,插件就无法访问到 K8s 的服务发现。因此大家如果需要服务发现与负载均衡,在选择 Underlay 的插件时就需要注意它们是否支持这两种能力。

经过功能需求的过滤之后,能选的插件就很少了。经过环境限制和功能需求的过滤之后,如果还剩下 3、4 种插件,可以再来考虑性能需求。

  • 性能需求:

可以从 Pod 的创建速度和 Pod 的网络性能来衡量不同插件的性能。

Pod 的创建速度:当创建一组 Pod 时,比如业务高峰来了,需要紧急扩容,这时比如扩容了 1000 个 Pod,就需要 CNI 插件创建并配置 1000 个网络资源。
                Overlay 和路由模式在这种情况下的创建速度是很快的,因为它是在机器里面又做了虚拟化,所以只需要调用内核接口就可以完成这些操作。
                但对于 Underlay 模式,由于需要创建一些底层的网络资源,所以整个 Pod 的创建速度相对会慢一些。因此对于经常需要紧急扩容或者创建大批量的 Pod 这些场景,
                应该尽量选择 Overlay 或者路由模式的网络插件;

Pod 的网络性能:主要表现在两个 Pod 之间的网络转发、网络带宽、PPS 延迟等这些性能指标上。Overlay 模式的性能较差,因为它在节点上又做了一层虚拟化,还需要去封包,
                封包又会带来一些包头的损失、CPU 的消耗等,如果对网络性能的要求比较高,比如说机器学习、大数据这些场景就不适合使用 Overlay 模式。
                这种情形下通常选择 Underlay 或者路由模式的 CNI 插件。

猜你喜欢

转载自blog.csdn.net/miss1181248983/article/details/113131515
cni
21.