什么是 k8s CNI ?

1、什么是 CNI ?

CNI 是容器网络接口 (Container Network Interface)的缩写。定义了容器运行时如何与网络插件进行交互,从而管理容器网络。只要开发者遵循 CNI 定义的规范就可以接入 kubernetes ,为 Pod 创建虚拟网卡、分配 IP 地址、设置路由规则等,这样就实现 "IP-Per-Pod" 网络模型。

CNI 为网络插件定义了一些以系列通用接口,可以使容器运行时与多种不同的网络插件(Flannel、Calico、Cilium等网络插件)进行交互,不同网络插件可以提供不同的网络策略。

2、Flannel 工作原理

Flannel 是一个用于容器网络的 CNI 插件,它的主要功能是为容器提供一个可以互相通信的网络。

那么,Flannel 是通过什么技术来实现容器之间的通信呢?

目前,Flannel 支持三种网络后端 VXLAN、UDP、Host-GW ,基于这些后端技术来实现容器之间的通信的。

2.1、Flannel 的 UDP 模式

UDP 模式,是 Flannel 最早支持的解决容器通信模式,由于性能非常差,所以,现在基本被弃用。

例子:假设有两台宿主机

  • Node 1 container-1,IP 地址是 100.96.1.2,对应的 docker0 网桥的地址是:100.96.1.1/24;
  • Node 2 container-2,IP 地址是 100.96.2.3,对应的 docker0 网桥的地址是:100.96.2.1/24;

容器 A 要访问 容器 B,由于是跨主机不在一个网断里,那么目的地址 100.96.2.3 并不在 Node 1 的 docker0 网桥的网段里,此时会根据路由规则通过容器的网关进入 docker0 网桥,在匹配到 flannel0 设备中,然后 flanneld 看到了这个 IP 包的目的地址,是 100.96.2.3,就把它发送给了 Node 2 宿主机。

flannel0 设备它是一个 TUN 设备,TUN 设备是一种工作在三层(Network Layer)的虚拟网络设备。负责,在操作系统内核和用户应用程序之间传递 IP 包

flanneld 又是如何知道这个 IP 地址对应的容器,是运行在 Node 2 上的呢?通过子网(Subnet),一台宿主机上的所有容器,都属于该宿主机被分配的一个"子网"。

总结:

Flannel UDP 模式提供的其实是一个三层的 Overlay 网络,即:它首先对发出端的 IP 包进行 UDP 封装,然后在接收端进行解封装拿到原始的 IP 包,进而把这个 IP 包转发给目标容器。

缺点:

仅在发出 IP 包的过程中,就需要经过三次用户态与内核态之间的数据拷贝

  • 第一次,用户态的容器进程发出的 IP 包经过 docker0 网桥进入内核态;
  • 第二次,IP 包根据路由表进入 TUN(flannel0)设备,从而回到用户态的 flanneld 进程;
  • 第三次,flanneld 进行 UDP 封包之后重新进入内核态,将 UDP 包通过宿主机的 eth0 发出去。
2.2、Flannel 的 VXLAN 模式

VXLAN 的覆盖网络的设计思想是:在现有的三层网络之上,"覆盖"一层虚拟的、由内核 VXLAN 模块负责维护的二层网络,使得连接在这个 VXLAN 二层网络上的"主机"(虚拟机或者容器都可以)之间,可以像在同一个局域网(LAN)里那样自由通信。当然,实际上,这些"主机"可能分布在不同的宿主机上,甚至是分布在不同的物理机房里。

而 VTEP 设备的作用,其实跟前面的 flanneld 进程非常相似。只不过,它进行封装和解封装的对象,是二层数据帧(Ethernet frame);而且这个工作的执行流程,全部是在内核里完成的(因为 VXLAN 本身就是 Linux 内核中的一个模块)。

2.3、host-gw 模式

工作原理非常简单:

假设现在,Node 1 上的 Infra-container-1,要访问 Node 2 上的 Infra-container-2。当你设置 Flannel 使用 host-gw 模式之后,flanneld 会在宿主机上创建这样一条规则,以 Node 1 为例:

bash 复制代码
$ ip route
...
10.244.1.0/24 via 10.168.0.3 dev eth0

这条路由规则的含义是:

  • 目的 IP 地址属于 10.244.1.0/24 网段的 IP 包,应该经过本机的 eth0 设备发出去(即:dev eth0);
  • 并且,它下一跳地址(next-hop)是 10.168.0.3(即:via 10.168.0.3)

这样,这个数据帧就会从 Node 1 通过宿主机的二层网络顺利到达 Node 2 上。

当然,Flannel 子网和主机的信息,都是保存在 Etcd 当中的。flanneld 只需要 WACTH 这些数据的变化,然后实时更新路由表即可。

3、Calico

不过,不同于 Flannel 通过 Etcd 和宿主机上的 flanneld 来维护路由信息的做法,Calico 项目使用了一个"BGP"来自动地在整个集群中分发路由信息。

BGP 的全称是 Border Gateway Protocol,即:边界网关协议。它是一个 Linux 内核原生就支持的、专门用在大规模数据中心里维护不同的"自治系统"之间路由信息的、无中心的路由协议。

4、cilium 工作原理

4.1 概述

Cilium 是 kubernetes 的 CNI 网络解决方案,Cilium 在设计和实现上,基于Linux的一种新的内核技术 eBPF,可以在Linux内部动态插入强大的安全性、可观测性和网络控制逻辑,及安全策略。可以在不修改应用程序代码或容器配置的情况下进行应用和更新。

3.2 架构

参考 Cilium 官方的架构,Cilium 位于容器编排系统 和 Linux Kernel之间,向上可以通过编排平台为容器进行网络以及相应的安全配置,向下可以通过在Linux内核挂载eBPF程序,来控制容器网络的转发行为以及安全策略执行。

bash 复制代码
kubectl exec -it test-1-7cd5798f46-vzf9s -n test-1 bash

root@u18-161:~# kubectl exec -it test-1-7cd5798f46-vzf9s -n test-1 bash
root@test-1-7cd5798f46-vzf9s:/# route -n
Kernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 10.244.0.26 0.0.0.0 UG 0 0 0 eth0
10.244.0.26 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
root@test-1-7cd5798f46-vzf9s:/# arp
root@test-1-7cd5798f46-vzf9s:/#

Flannel 的工作原理如下:

  1. 每个节点上的 Flannel 会为主机分配一个唯一的子网,这个子网可以由用户自定义或者由 Flannel 自动生成。

  2. 当容器启动时,容器运行时会调用 CNI 插件,通过 CNI 接口请求 Flannel 为容器分配一个 IP 地址。

  3. Flannel 会根据容器所在的节点以及容器所在节点的子网信息,为容器分配一个唯一的 IP 地址,并将这个 IP 地址返回给容器运行时。

  4. 容器运行时会将这个 IP 地址配置到容器的网络接口上,从而使容器可以与其他容器或者主机进行通信。

  5. 当容器需要访问其他节点上的容器时,Flannel 会使用虚拟网络设备 TUN/TAP 将数据包封装,然后通过底层网络(如 VXLAN、UDP)传输到目标节点上的 Flannel,再解封装数据包将其交给目标容器。

Calico 是一个开源的容器网络解决方案,它使用 BGP 协议来实现容器之间的通信。其工作原理如下:

  1. 每个节点上的 Calico Agent 会为主机分配一个唯一的 IP 地址,并将这个 IP 地址作为节点的标识符。

  2. 当容器启动时,容器运行时会调用 CNI 插件,通过 CNI 接口请求 Calico 为容器分配一个 IP 地址。

  3. Calico 会为容器分配一个唯一的 IP 地址,并将这个 IP 地址配置到容器的网络接口上。

  4. 当容器需要与其他容器通信时,容器会将数据包发送到目标 IP 地址,如果目标 IP 地址与本地节点的 IP 地址属于同一个子网,则数据包会直接发送到目标容器;如果目标 IP 地址与本地节点的 IP 地址不属于同一个子网,则数据包会被封装成 BGP 路由,并通过 BGP 协议传输到目标节点上。

  5. 目标节点上的 Calico Agent 接收到数据包后,会解封装数据包,并将数据包交给目标容器。

Cilium 是一个开源的容器网络解决方案,它使用 Linux 内核中的 eBPF(Extended Berkeley Packet Filter)技术来实现容器之间的通信。其工作原理如下:

  1. Cilium Agent 在每个节点上运行,并通过 Linux 内核中的 eBPF 技术来监控所有容器之间的网络通信。

  2. 当容器启动时,容器运行时会调用 CNI 插件,通过 CNI 接口请求 Cilium 为容器分配一个 IP 地址。

  3. Cilium 会为容器分配一个唯一的 IP 地址,并将这个 IP 地址配置到容器的网络接口上。

  4. 当容器之间需要通信时,Cilium Agent 会根据容器的标签信息和网络策略来判断是否允许通信,并使用 eBPF 技术来实现容器之间的通信。

  5. Cilium 还支持通过集成 Istio 来实现服务网格,从而可以对服务之间的通信进行更细粒度的控制和管理。

总之,Cilium 的主要作用是为容器提供一个可以互相通信的网络,并且它的实现方式是使用 Linux 内核中的 eBPF 技术来实现容器之间的通信。这种方式可以使得容器网络的性能更高,同时还支持更细粒度的网络策略和服务网格功能。

参考:

5、总结

Kubernetes通过一个叫做CNI的接口,维护了一个单独的网桥来代替docker0。这个网桥的名字就叫作:CNI网桥,它在宿主机上的设备名称默认是:cni0。

容器"跨主通信"的三种主流实现方法:UDP、host-gw、VXLAN。 之前介绍了UDP和VXLAN,它们都属于隧道模式,需要封装和解封装。接下来介绍一种纯三层网络方案,host-gw模式和Calico项目

Host-gw模式通过在宿主机上添加一个路由规则:

<目的容器IP地址段> via <网关的IP地址> dev eth0

IP包在封装成帧发出去的时候,会使用路由表里的"下一跳"来设置目的MAC地址。这样,它就会通过二层网络到达目的宿主机。

这个三层网络方案得以正常工作的核心,是为每个容器的IP地址,找到它所对应的,"下一跳"的网关。所以说,Flannel host-gw模式必须要求集群宿主机之间是二层连通的,如果宿主机分布在了不同的VLAN里(三层连通),由于需要经过的中间的路由器不一定有相关的路由配置(出于安全考虑,公有云环境下,宿主机之间的网关,肯定不会允许用户进行干预和设置),部分节点就无法找到容器IP的"下一条"网关了,host-gw就无法工作了。

Calico

Calico项目提供的网络解决方案,与Flannel的host-gw模式几乎一样,也会在宿主机上添加一个路由规则: <目的容器IP地址段> via <网关的IP地址> dev eth0

其中,网关的IP地址,正是目的容器所在宿主机的IP地址,而正如前面所述,这个三层网络方案得以正常工作的核心,是为每个容器的IP地址,找到它所对应的,"下一跳"的网关。区别是如何维护路由信息:

Host-gw : Flannel通过Etcd和宿主机上的flanneld来维护路由信息 Calico: 通过BGP(边界网关协议)来实现路由自治,所谓BGP,就是在大规模网络中实现节点路由信息共享的一种协议。

隧道技术(需要封装包和解包,因为需要伪装成宿主机的IP包,需要三层链通):Flannel UDP / VXLAN / Calico IPIP 三层网络(不需要封包和解封包,需要二层链通):Flannel host-gw / Calico 普通模式

相关推荐
qq_338032922 小时前
k8s总结
云原生·容器·kubernetes·k8s
老衲の少女心5 小时前
【容器】k8s学习笔记基础部分(三万字超详细)
笔记·学习·kubernetes
LeonNo115 小时前
k8s,诞生历史
云原生·容器·kubernetes
古人诚不我欺5 小时前
kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装
云原生·容器·kubernetes
爱学测试的李木子8 小时前
Docker常用命令总结~
运维·软件测试·测试工具·docker·容器
恋喵大鲤鱼9 小时前
微服务设计原则——功能设计
微服务·云原生·架构
元气满满的热码式10 小时前
Centos7.9安装docker
运维·docker·容器
China_Yanhy10 小时前
[k8s]报错:Cannot connect to the Docker daemon at unix:///var/run/docker.sock
docker·kubernetes·unix
码农秃头老李11 小时前
系列1:基于Centos-8.6部署Kubernetes (1.24-1.30)
linux·kubernetes·centos
魏 无羡11 小时前
linux CentOS系统上卸载Kubernetes(k8s)
linux·kubernetes·centos