在K8S中,kube-proxy ipvs原理是什么?
好的,我们来深入探讨一下 Kubernetes 中 kube-proxy
的 IPVS 模式原理。这是一个非常精彩的设计,它利用了 Linux 内核的强大功能来实现高性能的服务负载均衡。
核心思想
IPVS (IP Virtual Server) 是 LVS (Linux Virtual Server) 项目的核心组成部分,它工作在内核层面,实现了传输层(第四层,L4)的负载均衡。
kube-proxy
的 IPVS 模式基本原理是:将 Kubernetes Service 的 ClusterIP
(VIP) 和 NodePort
等,映射到 Linux 内核中的一个 IPVS 虚拟服务(Virtual Service)。对这个虚拟服务的请求,会被 IPVS 负载均衡到后端的真实服务器(Real Server),也就是实际的 Pod IP 上。
kube-proxy
的角色不再是通过插入大量的 iptables 规则来直接处理数据包,而是变成了 IPVS 的控制器。它负责调用 Linux 内核的 IPVS 接口来创建和管理这些虚拟服务和真实服务器。
工作原理详细步骤
下图清晰地展示了 IPVS 模式下的数据包流向与核心组件交互:
第 1 步:监听与配置 (控制平面)
- 监听 API Server:
kube-proxy
启动后,会通过 List-Watch 机制监听 Kubernetes API Server,获取所有 Service 和 Endpoint(或 EndpointSlice)的变更事件。 - 创建虚拟服务 (VS):当有新的 Service 创建时,
kube-proxy
会在本机内核的 IPVS 表中添加一条虚拟服务记录。- 地址:该记录的地址就是 Service 的
ClusterIP:Port
(或NodePort
)。 - 协议:TCP 或 UDP。
- 调度算法:可以是
rr
(轮询)、lc
(最小连接数)、sh
(源地址哈希) 等(通过 Service 的sessionAffinity
配置)。
- 地址:该记录的地址就是 Service 的
- 添加真实服务器 (RS):对于每个 Service 对应的后端 Pod,
kube-proxy
会将其作为真实服务器添加到上述虚拟服务的记录中。- 地址:真实服务器的地址就是 Pod 的 IP 地址和端口。
- 一个虚拟服务会对应多个真实服务器。
这个过程是通过 Linux 的 netlink
接口调用内核函数来完成的,效率非常高,远比维护大量的 iptables 规则要快。
第 2 步:流量转发 (数据平面)
当一个数据包到达节点,其目标地址是 Service 的 VIP 和端口时,会发生以下情况:
- 拦截:数据包进入本机的网络协议栈,在输入链(INPUT) 之前就被 IPVS 模块 拦截。这是因为
kube-proxy
已经通过ipset
巧妙地将 Service 的 VIP 集合配置到了本机的网络栈中,使得这些地址被视为本地地址,从而流量会进入 INPUT 链,进而被 IPVS 捕获。 - 匹配虚拟服务:IPVS 检查数据包的目标 IP 和端口,与它管理的虚拟服务列表进行匹配。
- 负载均衡:如果匹配到某个虚拟服务,IPVS 会根据为该服务配置的负载均衡算法(如
rr
,lc
),从后端的真实服务器列表中选择一个 Pod。 - 转发:IPVS 将数据包的目标地址修改(通过 NAT)为选中的 Pod 的 IP 和端口。
- 路由送出:修改后的数据包被重新送入网络协议栈,经过转发(FORWARD) 链,并根据本机的路由规则被路由到正确的 Pod 所在网络。Pod 可能在当前节点,也可能在其他节点。
第 3 步:连接跟踪
为了确保同一个连接的响应包能正确返回给客户端,IPVS 同样依赖 Linux 内核的 conntrack
(连接跟踪)模块来记录 NAT 转换的关系。当响应包返回时,conntrack
会将其源地址(Pod IP)反向修改回 Service 的 VIP,再返回给客户端。
IPVS 的三种转发模式
IPVS 支持多种数据包转发模式,kube-proxy
主要使用以下两种:
-
NAT 模式 (默认模式)
- 原理:IPVS 对请求包进行目的地址转换(DNAT),对响应包进行源地址转换(SNAT)。
- 优点:对后端 Pod 无特殊要求,Pod 可以在任何节点上。
- 缺点:请求和响应流量都必须经过
kube-proxy
所在节点,该节点容易成为瓶颈。
-
直接路由模式 (DR模式) - 性能最佳
- 原理:IPVS 只修改请求包的 MAC 地址,将其直接转发给后端的 Pod。响应包由 Pod 直接返回给客户端,不经过原节点。
- 要求:
- Pod 必须与
kube-proxy
节点在同一个二层网络(可直连MAC地址)。 - 需要在 Pod 所在的节点上配置,防止其响应针对 Service VIP 的 ARP 请求(通常通过
kube-ipvs0
接口和 ARP 抑制实现)。
- Pod 必须与
- 优点:性能极高,响应数据不绕回,减轻了负载均衡节点的压力。
- 缺点:配置更复杂,对网络环境有要求。
kube-proxy
IPVS 模式默认使用 NAT 模式。虽然它支持隧道模式,但 DR 和隧道模式在 Kubernetes 中需要额外的网络配置,不如 NAT 模式通用。
为什么需要 ipset?
虽然 IPVS 本身处理性能很高,但 kube-proxy
仍然巧妙地使用了 ipset
工具。
- 目的:高效管理需要被 IPVS 处理的地址集合。
- 功能:
ipset
可以存储大量的 IP 地址、端口、网络段等,并且可以作为一个整体被 iptables 规则引用。 - 工作方式:
kube-proxy
会创建多个ipset
集合,例如:- 存储所有 Service
ClusterIP
的集合。 - 存储所有 Service
ExternalIP
的集合。 - 存储所有 Service
NodePort
的端口集合。
- 存储所有 Service
- 好处:只需一条 iptables 规则就可以匹配到
ipset
中所有的 IP 地址,从而将数据包跳转(-j
) 给 IPVS 模块处理。这避免了为每个 Service VIP 创建一条 iptables 规则,极大地减少了 iptables 规则的数量,提升了效率和可维护性。
总结
kube-proxy
IPVS 模式的核心原理是:
- 控制平面:
kube-proxy
作为控制器,监听 API Server,通过netlink
接口配置内核中的 IPVS 规则(虚拟服务和真实服务器)。 - 数据平面:进入节点的流量被 IPVS 模块拦截,根据负载均衡算法进行 DNAT,直接转发到后端 Pod。
- 辅助工具:使用
ipset
来高效地管理需要被 IPVS 处理的 IP 地址集合,避免 iptables 规则爆炸。
这种架构使得 IPVS 模式能够以近乎恒定的时间复杂度(O(1))处理海量的服务和后端 Pod,提供了卓越的性能和可扩展性,非常适合大规模 Kubernetes 集群。