401 Kubernetes网络 (Pod Service Calico Flannel) 4.1-4.4

发布时间 2023-10-20 21:56:53作者: zhan0

一、Pod网络

在K8S集群里,多个节点上的Pod相互通信,要通过网络插件完成,比如Calico网络插件。

使用kubeadm初始化K8S集群时,需要指定一个参数--pod--network-cidr=10.18.0.0/16 它用来定义Pod的网段。配置Calico的时候,也要定义CALICO_IPV4POOL_CIDR的参数,它的值也是Pod的网络。

容器网络尤其是在跨主机容器的网络是非常复杂的。目前主流的容器网络模型哟Docker公司提出的Container Network Model(CNM)模型和CoreOS公司提出的Container Network Interface(CNI)模型。Kubernetes采用了CNI模型。

1、CNI

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

CNI只是定义了对容器网络进行操作和配置的规范。CNI仅关注在创建容器时分配网络资源,和在销毁容器时删除网络资源。常见的CNI产检包括:Calico、flannel、Terway以及Contiv

2、K8S 如何使用CNI插件

K8S通过CNI配置决定使用说明CNI

基本的使用方法为:

首先在每个节点上配置CNI配置文件(/etc/cni/net.d)

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

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

具体的流程如下图所示:

在集群里面创建一个Pod的时候,首先会通过apiserver将Pod的配置写入。apiserver的一些管控组件(比如Scheduler)会调度到某个具体的节点上。Kubelet监听到这个Pod的创建之后,会在本地进行一些创建的操作。当执行到创建网络步骤时,它首先会读取配置目录中的配置文件,配置文件声明使用哪一个插件,然后执行具体的CNI插件的二进制文件,再由CNI插件进入Pod的网络空间去配置Pod的网络。配置完成之后,Kuberlet就完成整个Pod的创建过程,这个Pod就在线了。

3、基于Calico的Pod网络

二、Service网络

Service api资源对象基本类型:ClusterIP 、NodePort、LoadBalancer。

这三种Service,LoadBancer依赖NodePort,而NodePort通常要和ClusterIP一起使用,如果在Service的yaml文件定义type为LoadBalancer,则它会自动创建NodePort,而NodePort会自动创建ClusterIP.

从Pod到Service的网络变化情况:

1)单个Pod之间通信

单个Pod和Pod之间通信只能通过Pod的IP和Port来通信,如下图

2)Pod有多个

当引入Deploy,并为Pod设置多个副本时,提供某一个服务(如Nginx服务)的Pod就不止一个,此时即使知道这些Pod的IP,那访问起来也不方便。需要有一个统一入口,其他Pod通过这个统一入口去请求改服务(Nginx)对应的所有Pod。这时就有了Service资源对象,它主要作用是提供统一入口,只需要一个IP就能访问所有Pod,而这个入口IP就是ClusterIP,就是Service 的IP

3)外部资源访问内部Pod

有了service,很方便为内部的Pod提供入口,但是集群外面不能访问这个内部的资源。于是,就有了NodePort,使用Service的NodePort类型,可将Service的ClusterIP对应的Port映射到每一个Node的IP上,映射出去的Port范围为30000-32767

4)借助公有云负载均衡器

使用NodePort并不方便,访问需要使用Node的IP,如果Node挂掉,就无法访问此资源。解决方案是:借助第三方的负载均衡器,将请求分发到所有的Node上,其地产还是NodePort。

总结:Service为内部Pod的统一入口,内部资源之间可以通过简单的ClusterIP进行通信,而外部资源访问需要借助NodePort的形式,但是需要带长端口,于是又出现LoadBalancer,这种需要借助第三方负责均衡器,将请求分发到每一个NodePort上。

三、网络插件Calico

参考:https://www.cnblogs.com/goldsunshine/p/10701242.html

3.1 Calico是什么

Calico是一个用于容器、虚拟机和主机的开源网络和网络安全解决方案。它是一个纯三层解决方案,利用BGP协议为容器或虚拟机提供IP地址,并提供网络安全功能,包括网络策略和加密。

Calico 通过将网络策略应用于标签和选择器,提供了一种简单而强大的方法来保护容器或虚拟机之间的通信,并限制容器或虚拟机可以访问的网络资源。它还支持基于 Kubernetes 和 OpenStack 等平台的网络自动化和集成。
Calico 的另一个重要特点是其可扩展性。它使用了基于 BGP 的路由技术,这使得它能够轻松地扩展到非常大规模的网络中,而不会降低性能。
由于Calico是一种纯三层的方案,因此可以避免与二层方案相关的数据包封装的操作,中间没有任何的NAT,没有任何的overlay,所以它的转发效率是所有方案中最高的,因为它的包直接走原生TCP/IP的协议栈,它的隔离也因为这个栈而变得好做。因为TCP/IP的协议栈提供了一整套的防火墙的规则,所以它可以通过IPTABLES的规则达到比较复杂的隔离逻辑。 

3.2 Calico架构

组件介绍:

  • Felix:Calico Agetnt,在K8S集群的每台节点上,主要负责管理和维护该节点上的网络和安全策略,如网络接口管理和监听、路由、ARP管理、ACL管理和同步、状态上报等。
  • ETCD:分布式键值存储,用来存储网络元数据、安全策略以及节点的状态信息,确保Calico网络状态的一致性和准确性,可以和K8S的etcd何用
  • BGP Client(BIRD):跟Felix一样,每一个节点上都部署GBP Client,主要吧Felix写入Kernel的路由信息分发到当前Calico网络,确保各节点间的通信的有效性。
  • BGP Route Reflector(BIRD):在大型网络中,仅仅使用BGP Client形成mesh全网互联的方案会导致规模现在,所有节点之间两辆互联,需要N^2个连接,可使用BGP的Router Reflector的方法,会使用BGP Client仅与特定RR节点互联并做路由同步,从而大大减少连接数,可大规模部署使用。

关键点:

  • Felix会定期查询Etcd数据库,从而获取到IP变化信息,比如说用户在这台机器上创建了一个容器,增加了一个IP等。当它发现数据变更后,比如用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。
  • BIRD是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。

3.3 Calico三种网络工作模式

模式   说明   特点

VXLAN

封包, 在vxlan设备上将pod发来的数据包源、目的mac替换为本机vxlan网卡和对端节点vxlan网卡的mac。外层udp目的ip地址根据路由和对端vxlan的mac查fdb表获取 只要k8s节点间三层互通, 可以跨网段, 对主机网关路由没有特殊要求。各个node节点通过vxlan设备实现基于三层的“二层”互通, 三层即vxlan包封装在udp数据包中, 要求udp在k8s节点间三层可达;二层即vxlan封包的源mac地址和目的mac地址是自己的vxlan设备mac和对端vxlan设备mac。
IPIP 封包,在tunl0设备上将pod发来的数据包的mac层去掉,留下ip层封包。 外层数据包目的ip地址根据路由得到。相当于建立了隧道,把两个本来不通的节点网络通过点对点连接起来。 只要k8s节点间三层互通, 可以跨网段, 对主机网关路由没有特殊要求。解包、封包都会造成一定的资源损耗。 适用于互相访问的pod不在同一个网段中、跨网段访问的场景。外层封装的ip能够解决跨网段的路由问题。
GBP 边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP 不用封包解包,通过bgp协议可实现pod网络在主机间的三层可达, k8s节点不跨网段时和flannel的host-gw相似,支持跨网段,跨网段时,需要主机网关路由也充当BGP Speaker能够学习到pod子网路由并实现pod子网路由的转发。总之bgp适用于大规模网络场景。

3.4 IPIP模式

默认网络模式即IPIP模式,在所有节点查看网络,会有tunl0 网卡

node-1-231

node-1-232

node-1-233 

查看pod

分析

  1. ng-deploy-7b7ff4f9bc-d2g65 在node-1-233上,它的IP为 10.244.154.56
  2. 如果10.244.154.56要访问另外一个ng-deploy-7b7ff4f9bc-s27c9,其IP为10.244.167.190
  3. 它会找路由 10.244.167.128/26 via 192.168.1.231 dev tunl0 proto bird onlink,这条路由对应着node-1-231的节点IP 192.168.1.231,所以它通过这个IP就能找到10.244.167.190

以上可以说明,IPIP模式就是将节点与节点之间建立了一条隧道,并且建立了对应的路由信息,Pod之间通信时只需要知道目标IP所对应的路由就可以直接访问到对应的节点IP,从而达到对方的Pod。

3.5 BGP 模式

将IPIP改为GBP

# kubectl  get ds -n kube-system
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
calico-node   4         4         4       4            4           kubernetes.io/os=linux   22d
kube-proxy    4         4         4       4            4           kubernetes.io/os=linux   22d

更新calico-node配置

kubectl edit ds calico-node -n kube-system  #会进入vim编辑模式
搜索下面两行
        - name: CALICO_IPV4POOL_IPIP
          value: Always

在它的下面增加:
        - name: CALICO_AUTODETECTION_METHOD
          value: interface=ens33
          
# kubectl edit ds calico-node -n kube-system
daemonset.apps/calico-node edited

 更改ippool,保存即可生效

kubectl edit ippool  #会进入vim编辑模式
搜索ipipMode
将ipipMode: Always 改为 ipipMode: Never

# kubectl edit ippool
ippool.crd.projectcalico.org/default-ipv4-ippool edited

 查看ip,会发现四台机器的tunl0都没有IP地址

 

 再查看route 使用BGP面膜是不在显示tunl0

 

使用ng-deploy 两个Pod,ng-deploy-7b7ff4f9bc-d2g65( 10.244.154.56 )到 ng-deploy-7b7ff4f9bc-s27c9 (10.244.167.190 )时 他的路由是0.244.167.128/26 via 192.168.1.231 dev ens33 proto bird ,不需要借助tunl,可以通过ens33直接访问。

 

 

四、网络插件Flannel

参考  https://blog.yingchi.io/posts/2020/8/k8s-flannel.htmlhttps://juejin.cn/post/6994825163757846565

4.1 Flannel简介


Flannel也是一个CNI插件,它的功能跟Calico一样,为K8S集群中的Pod提供网络支撑。

Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务。

Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的Pod能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的Pod能够直接通过内网IP通信。简单来说,它的功能是让集群中的不同节点主机创建的Pod都具有全集群唯一的虚拟IP地址。

Flannel实质上是一种“覆盖网络(overlaynetwork)”,也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持udp、vxlan、host-gw、aws-vpc、gce和alloc路由等数据转发方式。

核心关键点:

  • 网络配置:Flannel 配置存储在etcd中。Flannel节点会从etcd中读取这些配置信息,并根据配置创建和管理网络。
  • 子网分配:Flannel会为每个节点分配一个不重叠的子网,以便在节点上运行的Pod可以使用该子网内的IP。这样,集群内的每个Pod都将具有唯一的IP地址。
  • 数据包封装与转发:Flannel使用数据包封装技术(例如 VXLAN、UDP 等)将Pod之间的通信封装为跨节点的通信。当一个节点上的Pod 需要与另一个节点上的Pod通信时,源节点上的Flannel程序会将数据包封装,添加上目标子网信息,并将封装后的数据包发送到目标节点。目标节点上的Flannel程序会解封装数据包,并将其转发给目标Pod。
  • 兼容性:Flannel可以与k8s中的其他网络插件(如 Calico)一起使用,以实现更复杂的网络功能。这使得Flannel可以很好地适应不同的集群环境和需求。
工作模式:
  • UDP 模式:使用设备 flannel.0 进行封包解包,不是内核原生支持,频繁地内核态用户态切换,性能非常差,目前官方不建议使用了;
  • VxLAN 模式:使用 flannel.1 进行封包解包,内核原生支持,性能较强;
  • host-gw 模式:无需 flannel.1 这样的中间设备,直接宿主机当作子网的下一跳地址,性能最强;

4.2 Flannel 架构

Fannel最主要有两个组件:

  1. flanneld:控制面,运行在用户态,负责为宿主机分配子网,并监听Etcd,维护宿主机的FDB/ARP跟路由表。
  2. flannel.1:数据面,运行在内核态,作为VTEP,VXLAN数据包的封装跟解包。

4.3 VxLAN模式

VxLAN的设计思想是: 在现有的三层网络之上,“覆盖”一层虚拟的、由内核VxLAN模块负责维护的二层网络,使得连接在这个VxLAN二层网络上的“主机”(虚拟机或容器都可以),可以像在同一个局域网(LAN)里那样自由通信。 为了能够在二层网络上打通“隧道”,VxLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端,叫VTEP:VxLAN Tunnel End Point(虚拟隧道端点)
 
VXLAN是Flannel默认和推荐的模式。当我们使用默认配置安装Flannel时,它会为每个节点分配一个24位子网,并在每个节点上创建两张虚机网卡: cni0 和 flannel.1 。
  • cni0 是一个网桥设备,节点上所有的Pod都通过veth pair的形式与cni0相连。 
  • flannel.1 则是一个VXLAN类型的设备,充当VTEP的角色,实现对VXLAN报文的封包解包。
同一个节点内的Pod之间通信,只需要通过cni0即可,而我们要讨论的重点是跨节点通信。
假设两个节点Node1和Node2,两个节点上分别有两个Pod:PodA和PodB,现在Node1上的PodA要和Node2上的PodB通信,通信过程如下:
大致概括一下整个过程:
 
  • 发送端:在PodA中发起 ping 10.244.1.21 ,ICMP 报文经过 cni0 网桥后交由 flannel.1 设备处理。 Flannel.1 设备是一个VXLAN类型的设备,负责VXLAN封包解包。 因此,在发送端,flannel.1 将原始L2报文封装成VXLAN UDP报文,然后从 eth0 发送。
  • 接收端:Node2收到UDP报文,发现是一个VXLAN类型报文,交由 flannel.1 进行解包。根据解包后得到的原始报文中的目的IP,将原始报文经由 cni0 网桥发送给PodB。

 

4.4 host-gw网络模式

跟VxLAN不同,host-gw模式下没有flannel.1虚拟网卡,无需建立VxLAN隧道。但它有个缺点,必须要保证各Node在同一个网段。
 
 
Flanneld 模式的工作原理,就是将每个Flannel子网的下一跳,设置成了该子网对应的宿主机的 IP 地址,也就是说,宿主机(host)充当了这条容器通信路径的“网关”(Gateway),这正是 host-gw 的含义。
所有的子网和主机的信息,都保存在 Etcd 中,flanneld 只需要 watch 这些数据的变化 ,实时更新路由表就行了。 
核心是IP包在封装成桢的时候,使用路由表的“下一跳”设置上的MAC地址,这样可以经过二层网络到达目的宿主机