摘要:沿 ClusterIP 到后端 Pod 的路径理解 Service 数据面,比较 kube-proxy 的 iptables、IPVS、nftables 模式及 Cilium 的 eBPF 实现。
这一节继续沿着数据包的路径往下走,解决一个关键问题:
当客户端访问 ClusterIP:Port 时,Kubernetes 是如何把请求转发到某个后端 Pod 的?
例如:
flowchart TB
N0["前端 Pod"]
N1["Service ClusterIP"]
N2["后端 Pod 10.244.2.20:80"]
N0 -->|"请求 10.96.120.30:8080"| N1
N1 -->|"选择一个后端"| N2
这里需要先区分两个机制:
- CNI:主要解决 Pod 网络如何连接、如何跨节点通信。
- Service 数据面:解决 Service 虚拟 IP 的流量如何转发到后端端点。
在常见的 Kubernetes 部署中,kube-proxy 会负责配置 Service 转发规则;也有 Cilium 等方案能够在特定配置下替代 kube-proxy。
一、Service 为什么需要数据面?
Service 的 ClusterIP 通常是一个虚拟服务地址,并不对应一个独立的普通网络接口。
例如:
Service: backendClusterIP: 10.96.120.30Port: 8080
后端 Pod:10.244.1.10:8010.244.2.20:8010.244.3.15:80客户端发出请求:
curl http://10.96.120.30:8080内核必须有一套规则,决定如何将目标地址和端口转换、转发到实际后端。
这就是 Service 数据面的作用。
flowchart TB
N0["客户端<br/>目标地址:10.96.120.30:8080"]
N1["Service 数据面<br/>匹配服务规则,选择后端端点"]
N2["Pod A<br/>:80"]
N3["Pod B<br/>:80"]
N4["Pod C<br/>:80"]
N0 --> N1
N1 --> N2
N1 --> N3
N1 --> N4
需要注意:EndpointSlice 保存服务端点信息,控制平面和数据面组件据此维护转发状态。实际数据包一般不会经过 API Server。
二、kube-proxy 是什么?
kube-proxy 是 Kubernetes 中负责实现 Service 网络转发的传统组件。
在常见部署中,它运行在每个 Node 上,观察 Service 和 EndpointSlice 的变化,并配置相应的数据面规则。
它的工作过程可以理解为:
- 监听 Service 和 EndpointSlice 的变化。
- 获取 Service 的虚拟 IP、端口以及后端端点。
- 在节点上维护相应的转发规则。
- 客户端访问 ClusterIP 时,由节点网络数据面完成实际转发。
注意,kube-proxy 通常不在每个请求的转发路径上充当用户态代理。它主要负责配置规则,数据包随后由内核或其他数据面处理。
kube-proxy 的三种主要模式
| 模式 | 核心机制 | 特点 |
|---|---|---|
| iptables | Linux Netfilter 规则 | 通过匹配和 NAT 规则实现 Service 转发 |
| IPVS | Linux IPVS 虚拟服务器 | 使用内核四层负载均衡机制 |
| nftables | Linux nftables 规则 | 使用较新的 Netfilter 规则管理接口 |
另外,部分集群会使用 Cilium 等数据面替代 kube-proxy。此时 Service 转发可以由 eBPF 实现,未必存在传统 kube-proxy 规则。
三、iptables 模式:Service 转发的经典实现
先看最重要的机制:DNAT(目标地址转换)。
假设:
Service:10.96.120.30:8080
后端 Pod:10.244.1.10:8010.244.2.20:80客户端访问 Service:
curl http://10.96.120.30:8080在典型的 iptables 数据面中,数据包会匹配相关规则,并被转发到某个后端 Pod。
flowchart TB
N0["原始数据包<br/>目的 IP:10.96.120.30<br/>目的端口:8080"]
N1["iptables / Netfilter<br/>匹配 Service 规则<br/>选择后端并执行 DNAT"]
N2["转换后的数据包<br/>目的 IP:10.244.2.20<br/>目的端口:80"]
N3["路由与 CNI 网络<br/>将请求送往目标 Pod"]
N0 --> N1
N1 --> N2
N2 --> N3
这里的 DNAT 会改变数据包的目标地址和端口,使它指向真实的后端端点。
返回流量通常会通过连接跟踪(conntrack)关联原始连接,并执行相应的反向地址转换,使客户端看到的是与原始连接一致的 Service 通信。
iptables 规则大致如何组织?
传统 kube-proxy 的 iptables 模式会创建多层规则链,典型名称包括:
KUBE-SERVICES:匹配 Service。KUBE-SVC-*:处理特定 Service 的后端选择。KUBE-SEP-*:对应具体的服务端点。
可以把它理解为:
flowchart TB
N0["KUBE-SERVICES"]
N1["KUBE-SVC-*"]
N2["KUBE-SEP-*"]
N3["KUBE-SEP-*"]
N4["KUBE-SEP-*"]
N5["Pod A"]
N6["Pod B"]
N7["Pod C"]
N0 --> N1
N1 --> N2
N1 --> N3
N1 --> N4
N2 --> N5
N3 --> N6
N4 --> N7
这是传统规则结构的示意,实际链名、规则内容和实现细节会随 Kubernetes 版本及配置变化。
如何查看规则?
在有权限的 Linux Node 上执行:
sudo iptables-save -t nat筛选 Kubernetes 相关规则:
sudo iptables-save -t nat | grep KUBE-在某些环境中,iptables 命令可能使用 nftables 后端,因此输出与底层规则实现并不完全等同于旧式 iptables 内核机制。
建议只查看规则,不要直接修改或删除 KUBE-* 规则。 这些规则由控制组件管理,手工修改可能导致 Service 转发异常。
四、IPVS 模式:用虚拟服务器实现负载均衡
IPVS 是 Linux 内核提供的四层负载均衡机制。
在 kube-proxy 的 IPVS 模式中,Service 可以映射为虚拟服务器,后端 Pod 则对应真实服务器。
例如:
虚拟服务:10.96.120.30:8080
真实服务器:10.244.1.10:8010.244.2.20:8010.244.3.15:80flowchart TB
N0["Service 虚拟 IP<br/>10.96.120.30:8080"]
N1["IPVS<br/>虚拟服务器与真实服务器映射"]
N2["Real Server A"]
N3["Real Server B"]
N4["Real Server C"]
N0 --> N1
N1 --> N2
N1 --> N3
N1 --> N4
IPVS 支持多种调度算法,例如轮询、加权轮询等。不过,实际使用哪种算法取决于配置,不应认为所有 Service 都一定使用轮询。
在传统 kube-proxy IPVS 模式下,通常还会配合 iptables 规则完成部分流量处理,例如特定流量的标记、过滤和 SNAT。
如何查看 IPVS 状态?
在节点上执行:
sudo ipvsadm -Ln如果系统安装了 ipvsadm,可以看到虚拟服务器和后端目标。
但要注意,IPVS 模式并不是所有现代集群的默认选择。新版本 Kubernetes 对 IPVS 模式的支持状态和维护方向可能随版本变化,实际部署时应以目标版本官方文档为准。
五、iptables 与 IPVS 有什么区别?
| 对比 | iptables | IPVS |
|---|---|---|
| 主要机制 | Netfilter 规则匹配与 NAT | 内核虚拟服务器与真实服务器 |
| 后端选择 | 通过规则链选择 | 通过 IPVS 调度机制选择 |
| 规则组织 | 多层规则链 | 虚拟服务与目标服务器映射 |
| 查看工具 | iptables-save | ipvsadm |
| 依赖条件 | iptables / Netfilter 能力 | IPVS 内核支持及相关工具 |
| 学习重点 | 理解数据包匹配、DNAT、conntrack | 理解虚拟服务和四层负载均衡 |
不要简单地认为 IPVS 在所有场景下一定比 iptables 快。实际表现取决于规则规模、内核版本、工作负载和具体配置。
六、nftables 模式:现代 Linux 防火墙规则接口
除了 iptables 和 IPVS,Kubernetes 还支持基于 nftables 的 kube-proxy 模式。
nftables 是 Linux Netfilter 的规则管理框架,能够通过统一的规则集管理包过滤、NAT 等操作。
查看 nftables 规则:
sudo nft list ruleset但如果你的集群实际使用的是 iptables、IPVS 或 Cilium eBPF 数据面,就不能假设所有 Service 规则都会出现在 nftables 输出中。
学习时建议按照以下顺序:
- 先理解 iptables 中 Service 的匹配和 DNAT。
- 再理解 IPVS 的虚拟服务器模型。
- 最后学习 nftables 与 eBPF 数据面的实现差异。
七、实际请求的完整路径
现在把之前学习的知识串起来。
假设前端 Pod 调用:
curl http://backend.default.svc.cluster.local:8080一次请求通常涉及以下步骤:
flowchart TB
N0["1. DNS 解析<br/>CoreDNS 返回 Service ClusterIP"]
N1["2. Service 数据面<br/>kube-proxy 配置的规则或其他数据面选择后端"]
N2["3. 地址转换与路由<br/>根据具体数据面处理目标地址和数据包转发"]
N3["4. CNI 网络<br/>必要时跨节点传输至目标 Pod"]
N4["5. 后端应用<br/>目标进程接收请求并返回响应"]
N0 --> N1
N1 --> N2
N2 --> N3
N3 --> N4
这是便于理解的逻辑链路。真实数据包经过的钩子、路由点和转换顺序,会受网络插件、Service 实现、是否跨节点、是否需要 SNAT 等因素影响。
八、本节总结
你需要记住:
- kube-proxy:传统 Service 数据面规则管理组件。
- iptables:通过规则匹配和 NAT 完成转发。
- IPVS:通过虚拟服务器和真实服务器模型实现四层负载均衡。
- nftables:现代 Linux Netfilter 规则管理框架。
- CNI:负责 Pod 网络配置及相关网络能力,而不只是 Service 转发。
- Cilium:可以在特定配置下通过 eBPF 实现 Service 数据面。