需求导向的K8S网络原理分析:Kube-proxy、Flannel、Calico的地位和作用

最近发现自己似乎从来没学明白过Kubernetes网络通信方案,特开一贴复习总结一下。

在k8s中,每个 Pod 都拥有一个独立的 IP 地址,而且假定所有 Pod 都在一个可以直接连通的、扁平的网络空间中。所以不管它们是否允许在同一个 Node(宿主机)中,都要求它可以直接通过对方的 IP 进行访问。用户不需要额外考虑如何建立 Pod 之间的连接,也不需要考虑将容器端口映射到主机端口等问题。同时,外界的

省流,K8s网络的目标是为了实现:

  1. pod之间的互联互通
  2. 对外提供服务

为了实现上述功能,需要为每一个pod都维护完整的网络协议栈,同时,维护pod之间的网络路由。

CNI容器网络接口

首先,当你起了一个裸的、没有网络的pod之后,这个pod是没有任何基于TCP/IP手段和外界进行通信的。你可能只能通过crictl的客户端看到自己起了这么一个pod。

为了建立pod和外界的(基于TCP/IP的)通信,并且将不同pod的网络隔离开,需要为每一个pod构建一个网络命名空间。网络命名空间(Network Namespace)是一种内核级别的隔离机制,用于将不同进程组(比如一个pod就是一个被隔离的进程组)的网络环境隔离开来。每个网络命名空间拥有独立的网络栈,实现网络资源的完全隔离。

具体一点,网络命名空间的核心功能及特性是:

  1. 网络隔离
    不同网络命名空间的进程无法直接通信,需通过跨命名空间的网络设备(如 veth 对、网桥)或物理设备连接。例如,pod A 在命名空间ns1,pod B 在命名空间ns2,它们的(虚拟)物理层、数据链路层、网络层、传输层、应用层都实现了相互独立。
  2. 独立网络栈
    每个命名空间可独立配置 IP 地址、子网、网关、DNS 服务器等。
  3. 轻量级隔离
    相比虚拟机,网络命名空间的资源开销极小,适合容器场景。

我们首先实现同一台物理机内pod之间的相互通信。

为了实现不同网络命名空间之间的通信,需要把若干的pod从物理层到网络层连起来。

我们首先实现(虚拟)物理层和数据链路层的相互连接,这基于veth设备对。

你可以把它想象为一根带有两个水晶头的网线,两端(veth1和veth2)分别插在两个pod上。如下图所示:

在有多个pod的情况下,一般会新建一个公用的虚拟交换机(如图所示的bridge),然后所有的pod都接到这个交换机上,也能通过这个交换机实现pod之间的通信。如下图所示:

图里面这个bridge是一个虚拟网络设备,所以具有网络设备的特征,可以配置IP、MAC地址等;其次,bridge是一个虚拟交换机,和物理交换机有类似的功能。

对于普通的网络设备来说,只有两端,从一端进来的数据会从另一端出去,如物理网卡从外面网络中收到的数据会转发给内核协议栈,而从协议栈过来的数据会转发到外面的物理网络中。

而bridge不同,bridge有多个端口,数据可以从任何端口进来,进来之后从哪个口出去和物理交换机的原理差不多,要看数据包指向的终端MAC地址。

进一步地,我们给pod、网桥都配上IP地址,于是我们实现了同一台物理机内pod之间的相互通信。

进一步地,我们需要实现跨不同主机pod之间的通信。

一种简单的想法是,建一个跨多个主机的bridge不就得了?

这种在已有的网络上通过软件构建一个扩展版虚拟网络的方法,被称为:Overlay Network(覆盖网络)。从实现效果来看,就是把若干个节点上的小bridge整合成了一个大bridge。

Calico和Flannel是overlay network的两种实现方案。

Calico和Flannel

为了实现跨节点之间的数据通信,这就需要calico和flannel出场了。

跨节点数据包路由,主要就是两种情形:

  1. 节点和节点之间能够通过IP直连(三层可达)
  2. 节点和节点之间连接复杂(三层不可达)

解决方案也很简单,对于三层可达的网络,可以直接配置节点的路由表进行转发。对于三层不可达的网络,搭一个隧道实现网络穿透就可以了。

从这个视角看,Calico和Flannel两个插件虽然名字不太一样,但是实现的功能大同小异。

calico中,主要提供两种跨node包路由的模式:

  • BGP 模式:在三层可达的时候,Calico 在每个节点上运行 BGP 客户端,将 Pod 的 IP 路由信息通过 BGP 协议通告给其他节点。pod间流量直接通过路由规则进行转发。
  • IPIP 模式:当两个节点不在同一子网(三层不可达)时,Calico 将Pod间数据包的外边再包一层IP 头,通过隧道实现传输。

flannel中,也提供两种跨节点包路由的方式:

  • VXLAN模式:VXLAN 是 Linux 内核原生支持的网络虚拟化技术,通过在 IP 包内封装二层以太网帧,实现跨节点的虚拟二层网络。原理和Calico的IPIP模式类似。
  • Host-gateway模式:直接利用节点的物理网络进行路由,无需隧道封装,通过将 Pod 子网的路由直接指向目标节点的物理 IP,实现跨节点通信。

Kube-proxy

在前文中,我们已经通过calico / flannel等技术实现了同一个集群内pod的互联互通。但是仍然有一些比较关键的需求需要解决。

在实际使用集群的过程中,pod启动时的IP是随机分配的,这意味着访问集群内部pod必不能用硬编码方式实现。此外, Pod 实例会动态变化,需要设计动态服务发现和动态负载均衡方案。要在pod不断的变化的IP中追求不变,并且抓住这个不变实现集群内部pod的访问。

K8S的解决方案是service+DNS。Service里记录了pod的标签和端口映射规则(只是一个配置文件)。在用户向集群提交service的配置后,集群会创建和service同名的endpoint对象,用于根据service记录的标签去匹配对应的某些pod。用户在访问某些特定pod的时候,只需要访问service/endpoint的IP即可,由endpoint实现流量的路由和负载均衡。

由于endpoint的IP也在变,所以集群内引入了DNS机制,为每一个service都赋予了一个域名,通过service域名访问对应的pod。

为了实现上述功能,需要不断地监控pod的状态,进而实现路由转发。Kube-proxy提供了这样的解决方案。

kube - proxy 会持续监控 API Server,当 Service 或 Endpoint 资源发生变更时,kube - proxy 会通过list-watch手段获取这些信息。

kube - proxy 根据这些信息更新本地的iptables/ipvs规则,这些规则决定了如何将流量从 Service 的 IP 和端口转发到后端的 Pod。

references

https://segmentfault.com/a/1190000009491002

https://learn.lianglianglee.com

https://zhuanlan.zhihu.com/p/439920165

https://blog.csdn.net/weixin_42587823/article/details/144938902

相关推荐
申尧强3 分钟前
Flink Credit-based机制解析
java·网络·flink
Neolock41 分钟前
Next.js 中间件鉴权绕过漏洞 (CVE-2025-29927) 复现利用与原理分析
网络·web安全·中间件·cve·next.js
Hello.Reader1 小时前
使用nohup和--remove-source-files在后台运行rsync并记录日志
运维·服务器·网络
黎明晓月1 小时前
Docker容器的kafka在VM虚拟机挂起重新运行之后连接异常解决
docker·容器·kafka
钟离墨笺2 小时前
【网络协议】【http】http 简单介绍
网络·网络协议·http
vortex52 小时前
如何为 Debian 和 Kali 系统更换软件源并更新系统
linux·运维·网络·网络安全·渗透测试·debian·kali
ssr——ssss3 小时前
网络华为HCIA+HCIP 防火墙
网络·华为·智能路由器
阿瑾06183 小时前
【网络】Socket套接字
linux·网络·c++·网络协议
chairon4 小时前
Ansible:playbook实战案例
运维·服务器·网络·ansible
王伯爵4 小时前
5G网络中A端口和Z端口
网络·5g·php