Kube Proxy 工作模式对比分析

本文深入解析KubeProxy的四种运行模式:userspace、iptables、ipvs及kernelspace,探讨其工作原理、性能特点及适用场景,为Kubernetes集群网络流量管理和优化提供全面指导。
引言

Kube Proxy 是 Kubernetes 生态的核心组件之一,主要负责处理访问 Service 的流量(包括通过 Cluster IP 以及 Node Port),自动将 Client 对 Kubernetes Service 的请求代理到正确的 Pod 或 Node 后端。截止 1.18 版本,Kube Proxy 能够支持的运行模式有 4 种,其平台支持情况如下表:

ModeLinuxWindows
userspaceYY
iptablesYN
ipvsYN
kernelspaceNY

注意:userspace 模式在实现上其实细分为 Linux 的 userspace 和 Windows 平台的 winuserspace,工作原理基本一致。之所以分两套实现,笔者以为主要是 Linux 的 userspace 实现仍部分依赖了 Linux 内核的 iptables 功能,而 Windows 平台由于没有 iptables 支持,所以使用了另外的机制(将 ClusterIP 绑定到网卡) 单独实现了一番。

userspace 模式

在 userspace 模式下,kube-proxy 通过监听 K8s apiserver 获取关于 Service 和 Endpoint 的变化信息,在内存中维护一份从ClusterIP:Port 到后端 Endpoints 的映射关系,通过反向代理的形式,将收到的数据包转发给后端,并将后端返回的应答报文转发给客户端。该模式下,kube-proxy 会为每个 Service (每种协议,每个 Service IP,每个 Service Port)在宿主机上创建一个 Socket 套接字(监听端口随机)用于接收和转发 client 的请求。默认条件下,kube-proxy 采用 round-robin 算法从后端 Endpoint 列表中选择一个响应请求。

[root@machine ~]# kubectl get svc --all-namespaces
NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  8d
kube-system   kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   8d
[root@machine ~]# netstat -apn | grep kube-proxy
tcp6       0      0 :::39748                :::*                    LISTEN      21092/kube-proxy    
tcp6       0      0 :::46122                :::*                    LISTEN      21092/kube-proxy    
tcp6       0      0 :::10256                :::*                    LISTEN      21092/kube-proxy    
tcp6       0      0 :::43892                :::*                    LISTEN      21092/kube-proxy

正如我们看到的,kube-proxy 会根据 Service IP(包括 CLUSTER-IP 和 EXTERNAL-IP)、协议以及端口号确定一个 Socket,在宿主机上打开一个监听端口。客户端访问 Service 的流量会被分别路由到对应的 Socket 监听端口得到处理。Service 到 Socket 的重定向路由,在 Linux 平台采用 iptables 实现(在 Windows 平台通过将 Service ClusterIP 绑定到网卡实现)。

Linux iptables 根据目的 Service 定向到指定的 Socket 监听端口的规则示意:

[root@machine ~]# iptables -t nat -S
-A KUBE-PORTALS-CONTAINER -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https" -m tcp --dport 443 -j REDIRECT --to-ports 46122
-A KUBE-PORTALS-HOST -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https" -m tcp --dport 443 -j DNAT --to-destination 192.168.137.139:46122

userspace 模式工作原理示意:

在这里插入图片描述

iptables 模式

在 iptables 模式下,kube-proxy 依然需要通过监听 K8s apiserver 获取关于 Service 和 Endpoint 的变化信息。不过与 userspace 模式不同的是,kube-proxy 不再为每个 Service 创建反向代理(也就是无需创建 Socket 监听),而是通过安装 iptables 规则,捕获访问 Service ClusterIP:Port 的流量,直接重定向到指定的 Endpoints 后端。默认条件下,kube-proxy 会 随机 从后端 Endpoint 列表中选择一个响应请求。ipatbles 模式与 userspace 模式的不同之处在于,数据包的转发不再通过 kube-proxy 在用户空间通过反向代理来做,而是基于 iptables/netfilter 在内核空间直接转发,避免了数据的来回拷贝,因此在性能上具有很大优势,而且也避免了大量宿主机端口被占用的问题。

但是将数据转发完全交给 iptables 来做也有个缺点,就是一旦选择的后端没有响应,连接就会直接失败了,而不会像 userspace 模式那样,反向代理可以支持自动重新选择后端重试,算是失去了一定的重试灵活性。不过,官方建议使用 Readiness 探针来解决这个问题,一旦检测到后端故障,就自动将其移出 Endpoint 列表,避免请求被代理到存在问题的后端。

[root@machine ~]# iptables -t nat -S
-A KUBE-SEP-XVJ25MO2MX75T34R -s 192.168.137.139/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-XVJ25MO2MX75T34R -p tcp -m tcp -j DNAT --to-destination 192.168.137.139:6443
-A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
-A KUBE-SVC-NPX46M4PTMTKRN6Y -j KUBE-SEP-XVJ25MO2MX75T34R

正如上面 iptables 规则列出的,访问 10.96.0.1 443 端口的流量会被交由 KUBE-SVC-NPX46M4PTMTKRN6Y 处理,KUBE-SVC-NPX46M4PTMTKRN6Y 继而跳转到 KUBE-SEP-XVJ25MO2MX75T34R,最终 DNAT 到目的 Node 的 6443 端口,这正是 kubernetes apiserver 的监听地址。因此,iptables 模式下,完全通过 iptables 自身就实现了流量转发,不需要为每个 Service 打开 Socket 监听端口了。注意,这里最上边那条是 DNAT 的配对策略,DNAT 的回包需要做 UN-DNAT(即 SNAT/MASQ)。

iptables 模式工作原理示意:

在这里插入图片描述

ipvs 模式

在 ipvs 模式下,kube-proxy 通过监听 K8s apiserver 获取关于 Service 和 Endpoint 的变化信息,然后调用 netlink 接口创建 ipvs 规则,并周期性地同步 Kubernetes Service/Endpoint 与 ipvs 规则,保证状态匹配。当客户端请求 Service 时,ipvs 会将流量重定向到指定的后端。

ipvs 相比 iptables 的优势在于通过 hash table 实现了 O(1) 时间复杂度的规则匹配。当 Service 和 Endpoint 的数量急剧增加时,iptables 的匹配表项会变得十分庞大,而其采用的顺序匹配模式会严重影响其性能。相反,ipvs 无论在小规模集群还是大规模集群,都拥有几乎相同的性能表现,因此相比其他代理模式,能提供更高的网络吞吐量,更能满足大规模集群扩展性和高性能的需要。同时,ipvs 支持对后端的健康检查和连接重试,可靠性相比 iptables 更佳。此外,ipvs 模式还为用户提供了多种负载均衡策略以供选择,例如:

  • rr: round-robin (轮询,默认采用)
  • lc: least connection (最少连接数)
  • dh: destination hashing (根据目的哈希)
  • sh: source hashing (根据源哈希)
  • sed: shortest expected delay (最小延迟)
  • nq: never queue (不排队等待,有空闲 Server 直接分配给空闲 Server 处理,否则通过 sed 策略处理)

ipvs 仍然使用 iptables 实现对数据包的过滤、SNAT 或 MASQ,但使用 ipset 来存储需要执行 MASQ 或 DROP 的源地址和目的地址,从而保证在大量 Service 存在的情况下,iptables 表项数量仍能维持在常数级。

通过 ipvsadm、ipset 工具可以查看 Service ClisterIP:Port 到后端 Pod/Node 映射关系。

[root@machine ~]# iptables -t nat -S
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A KUBE-SERVICES -m set --match-set KUBE-CLUSTER-IP dst,dst -j ACCEPT
[root@machine ~]# ip addr show dev kube-ipvs0
68: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default 
    link/ether fe:04:6f:5a:01:3e brd ff:ff:ff:ff:ff:ff
    inet 10.96.0.10/32 brd 10.96.0.10 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.96.0.1/32 brd 10.96.0.1 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
[root@machine ~]# ipset list
Name: KUBE-CLUSTER-IP
Type: hash:ip,port
Revision: 2
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 16656
References: 2
Members:
10.96.0.10,tcp:53
10.96.0.10,tcp:9153
10.96.0.10,udp:53
10.96.0.1,tcp:443
[root@machine ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.0.1:443 rr
  -> 192.168.137.139:6443         Masq    1      1          0         
TCP  10.96.0.10:53 rr
  -> 10.80.1.233:53               Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.80.1.233:9153             Masq    1      0          0         
UDP  10.96.0.10:53 rr
  -> 10.80.1.233:53               Masq    1      0          0   

如上所示的,首先系统通过 iptables 允许访问 KUBE-CLUSTER-IP ipset 的流量进入,并通过在虚拟网卡 kube-ipvs0 上配置 VIP 的方式,告诉内核识别 VIP 为本机 IP,从而走 iptables 的 INPUT 链,继而通过 IP Virtual Server 找到 Real Server 提供服务。

注意:由于 KUBE-CLUSTER-IP 的类型为 hash:ip,port,在 --match-set KUBE-CLUSTER-IP dst,dst 匹配规则中,第一个 dst 表示将 set 中的 IP 作为目的地址,第二个 dst 表示将 set 中的 Port 作为目的端口。

ipvs 模式工作原理示意:

在这里插入图片描述

kernelspace 模式

kernelspace 也可以说是 winkernel 模式,因为它只应用于 Windows 平台。在 winkernel 模式下,kube-proxy 通过监听 K8s apiserver 获取关于 Service 和 Endpoint 的变化信息,然后通过 HNS (Host Network Service) 接口直接配置 Windows 内核的 LoadBalancer 以及 Endpoint ,实现基于 winkernel 的 Kubernetes Service 代理服务。

winkernel 模式相对 winuserspace 模式的改进与 iptables 模式相对 userspace 模式的改进类似,即避免了主动创建大量的 Socket 监听,也免去了频繁且低效的用户态-内核态数据拷贝,直接通过配置系统的 LoadBalancer 和 Endpoint 实现代理,性能上具有明显优势。

winkernel 模式工作原理示意:

在这里插入图片描述

附加:设置会话保持

在以上几种模式中,客户端对 Service ClusterIP:Port 的访问都被透明代理到合适的后端,客户端不会感知到 Kubernetes、Service 或是 Pod。默认条件下,代理后端认为每次请求都是独立的,会分别按照策略选择后端进行响应。如果你希望来自同一个客户端的请求每次都被同一个后端响应(即会话保持),可以通过设置 Kubernetes Service 的 service.spec.sessionAffinity 字段为 “ClientIP”,保证同一 Client 对 Service 的请求被定向转发到同一 Endpoint(其内部其实是通过一个 Map 结构记录了 Client 与 Endpoint 的对应关系)。同时,你还可以通过设置 service.spec.sessionAffinityConfig.clientIP.timeoutSeconds 字段定义会话保持的最长时间,默认是 3 小时。

<think>好的,我需要回答用户关于kube-proxy在LoadBalancer模式下Service的iptables工作机制的问题。首先,我得回忆一下kube-proxy的基本知识。用户提供的引用提到,kube-proxy有两种主要模式:userspace和iptables,现在还有ipvs模式。但用户的问题集中在LoadBalancer模式下的iptables机制,所以需要重点考虑iptables模式下的实现。 首先,LoadBalancer类型的Service其实是NodePort的一个扩展,通常会由云提供商提供负载均衡器,将外部流量导向各个节点的NodePort。然后kube-proxy负责将NodePort的流量通过iptables规则转发到后端Pod。我需要解释这个过程中kube-proxy如何生成iptables规则。 根据引用[2],kube-proxy作为控制器,负责更新iptables规则,而实际的流量处理由netfilter(即iptables)完成。在LoadBalancer模式下,当Service创建时,kube-proxy会监听API Server的变化,并生成相应的规则。这些规则包括目标地址转换(DNAT),将到达Service的ClusterIP或NodePort的流量转发到后端Pod的IP和端口。 接下来要详细说明iptables的处理链。例如,引用[4]提到PREROUTING链跳转到KUBE-SERVICES链,这里所有的服务流量都会先经过这个链。当数据包到达时,iptables会根据匹配的Service IP和端口,选择对应的后端Pod,并进行DNAT转换。同时,可能还需要处理负载均衡的策略,比如随机选择Pod或者轮询。 需要注意的是,LoadBalancer模式通常依赖于云平台的负载均衡器,但kube-proxy的iptables规则仍然在节点内部处理流量路由。因此,外部流量通过负载均衡器到达节点的NodePort,然后由iptables规则进一步转发到Pod。 还需要确认用户提到的引用内容是否涉及具体的iptables链和规则。比如引用[4]中的KUBE-SERVICES链,以及可能的其他链如KUBE-NODEPORTS,这些链会在处理不同流量时被调用。例如,当流量来自外部负载均衡器时,进入NodePort的端口,会被KUBE-NODEPORTS链处理,进而跳转到对应Service的规则,再DNAT到具体的Pod。 另外,需要说明每个Service对应的iptables规则如何生成。例如,当有多个后端Pod时,kube-proxy会为每个Pod创建相应的规则,并使用概率(--probability)参数来实现流量的随机分发,从而实现负载均衡。这部分需要结合具体的iptables规则示例来解释。 最后,总结整个过程,强调kube-proxy的作用是动态维护这些iptables规则,确保流量正确转发,而实际的数据包处理由Linux内核的netfilter完成。这符合引用[2]和[3]提到的内容,即kube-proxy作为控制器配置规则,而不是直接处理流量。 现在需要将这些思路组织成结构化的回答,确保使用正确的中文术语和LaTeX格式,同时生成相关问题。</think>### kube-proxy在LoadBalancer模式下的Service实现原理及iptables工作机制 #### 1. LoadBalancer模式Service的架构 LoadBalancer类型的Service是NodePort的扩展,通过云服务商的负载均衡器将外部流量分发到集群节点的NodePort端口[^1]。kube-proxy在此模式下的核心作用是通过iptables规则,将到达NodePort或ClusterIP的流量转发到后端Pod。 #### 2. iptables规则生成逻辑 kube-proxy通过监听Kubernetes API Server的Service和Endpoint变化,动态生成iptables规则: 1. **目标地址转换(DNAT)**:将目标地址从Service的IP:Port或NodePort转换为后端Pod的IP:Port。 2. **负载均衡规则**:使用`statistic`模块(如`random`或`nth`)实现流量随机分发到多个Pod[^2]。 #### 3. iptables关键处理链 以下是流量从负载均衡器到Pod的路径示例: ```plaintext 外部流量 → 云负载均衡器 → 节点NodePort → iptables PREROUTING链 → KUBE-SERVICES链 → KUBE-NODEPORTS链 → DNAT到Pod ``` 具体链的作用: - **PREROUTING链**:所有流量首先进入此链,跳转到`KUBE-SERVICES`链[^4]。 - **KUBE-SERVICES链**:匹配Service的ClusterIP和端口。 - **KUBE-NODEPORTS链**:处理NodePort类型的流量,进一步匹配端口并跳转到Service规则[^4]。 #### 4. 规则示例及负载均衡实现 假设Service有两个后端Pod(IP1:Port、IP2:Port),kube-proxy生成的规则可能如下: ```bash -A KUBE-SVC-XXXXX -m statistic --mode random --probability 0.5 -j KUBE-SEP-YYYYY -A KUBE-SVC-XXXXX -j KUBE-SEP-ZZZZZ ``` - **`--probability 0.5`**:第一条规则有50%概率命中,剩余流量走第二条规则,实现均匀分发。 #### 5. 与内核协作机制 kube-proxy仅负责规则配置,实际转发由Linux内核的netfilter模块完成[^2]。这种设计避免了用户态代理的性能瓶颈(对比早期的userspace模式[^3])。 $$ \begin{aligned} &\text{性能对比(包转发速率)} \\ &\text{userspace模式} & &< 10^4 \text{ pps} \\ &\text{iptables模式} & &\approx 10^5 \text{ pps} \\ &\text{ipvs模式} & &> 10^6 \text{ pps} \end{aligned} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值