返回首页

4.3 Service 实现原理:iptables 与 IPVS

这一章要解决的不是“Service 怎么写 YAML”,而是“Service 为什么能工作”:

  • kube-proxy 到底负责什么::cite[218]
  • iptables 模式是怎么把 ClusterIP 转发到 Pod 的::cite[216]
  • IPVS 模式为什么曾经被认为更适合大规模集群::cite[216]
  • 两种模式在性能、维护、排障上有什么明显差异::cite[216]

学 Kubernetes 网络时,Service 常常最容易让人产生错觉:你能 curl 一个根本不存在的虚拟 IP,但流量却总能打到后端 Pod。这背后真正的主角不是 Service 对象本身,而是运行在每个节点上的 kube-proxy。官方文档写得很清楚:kube-proxy 负责把 Service 的虚拟 IP 机制落到节点上,它会监听 Service 和 EndpointSlice 的变化,然后在节点里配置转发规则,把访问 ClusterIP 的流量导到某个后端。::cite[216]

1. kube-proxy 的职责与工作方式

1.1 kube-proxy 不是四层代理进程那种“逐包中转”

很多同学第一次看到 kube-proxy 这个名字,会以为它像 Nginx 一样接收请求、再转发请求。其实在 Linux 场景里,kube-proxy 更常做的是:根据 Service 和 EndpointSlice 的状态,在节点内核网络栈里下发规则。::cite[216]

也就是说,真正转发流量的是节点内核中的 netfilter / IPVS / nftables 规则,kube-proxy 更像是“规则控制器”。::cite[216]

1.2 kube-proxy 在每个节点都要运行

官方 kube-proxy 参考文档说明,它运行在每个节点上,把 Kubernetes API 中定义的 Service 反映到本节点的网络转发规则里。这样无论客户端 Pod 落在哪个节点,只要它访问 Service 的 ClusterIP,所在节点都知道怎么把流量送到正确的后端。::cite[218]

1.3 kube-proxy 具体干了什么

你可以把 kube-proxy 的工作理解成下面这个循环:

  1. watch Service 与 EndpointSlice;
  2. 发现某个 Service 新增、删除或后端变化;
  3. 按当前代理模式(iptables / IPVS / nftables)重算转发规则;
  4. 同步到节点网络栈。::cite[216]

所以 Service 之所以“稳定”,并不是因为 ClusterIP 后面真有一台机器,而是因为每个节点都被教会了“这个虚拟 IP 该转给谁”。::cite[216]

2. iptables 模式的转发原理

2.1 核心思路

在 iptables 模式下,kube-proxy 会调用内核 netfilter 的 iptables API,为每个 Service 和每个 Endpoint 创建一组规则。访问 Service ClusterIP 的流量会先命中 Service 规则,再跳到某个 endpoint 规则,最终通过 DNAT 转发到真实 Pod。::cite[216]

换句话说,ClusterIP 不是被“监听”了,而是被内核规则“截获”了。::cite[216]

2.2 一条典型请求链路

假设有一个 Service:

  • ClusterIP:10.96.100.10
  • Port:80
  • 后端 Pod:10.244.1.12:808010.244.2.18:8080

当客户端访问 10.96.100.10:80 时,大致会发生:

  1. 包到达节点网络栈;
  2. iptables 规则发现目标是某个 Service ClusterIP;
  3. 规则随机或按会话亲和性选中一个后端;
  4. 目标地址被改写为 Pod IP + TargetPort;
  5. 数据包继续被路由到目标 Pod。::cite[216]

官方文档明确说明,在 iptables 模式下,默认会随机选择一个后端 Pod,并把流量重定向到这个后端;在 ClusterIP 场景中,客户端源地址通常不会被改写。::cite[216]

2.3 iptables 模式的优点

  • 逻辑直观,很多 Linux 工具都能直接观察;
  • 历史最久,兼容性和使用面都很广;
  • 对中小规模集群来说,理解和排障成本相对低。::cite[216]

2.4 iptables 模式的局限

官方文档指出,iptables 模式下,Service 和 Endpoint 越多,规则数量就越大;在大规模集群里,规则同步可能会更慢。虽然自 Kubernetes 1.28 起,iptables 模式已经采用更增量化的同步方式,性能明显改善,但它本质上仍然是规则表规模随对象数增长的方案。::cite[216]

这也是为什么历史上很多人会考虑 IPVS:因为它在大规模规则同步时更有优势。::cite[216]

3. IPVS 模式的转发原理

3.1 核心思路

IPVS 模式也是把 Service IP 转到后端 Pod,但实现方式从“大量 iptables 规则”换成了“内核中的 IPVS 虚拟服务表”。官方文档说明:IPVS 基于类似 netfilter hook 的机制,但底层数据结构是哈希表,并且工作在内核空间。::cite[216]

这句话特别关键。它意味着 IPVS 不再主要靠一长串规则链顺序匹配,而是用更适合负载均衡场景的数据结构维护 Service 与后端之间的关系。::cite[216]

3.2 IPVS 模式为什么曾经很受欢迎

官方文档给出的总结很直接:IPVS 当初是为了给 kube-proxy 提供比 iptables 更好的规则同步性能和更高网络吞吐而引入的实验性后端。::cite[216]

所以它在历史上的吸引力主要来自两点:

  • 后端数量很多时,同步与查找更高效;
  • 更像传统四层负载均衡器的数据结构。::cite[216]

3.3 IPVS 支持多种调度算法

IPVS 还支持多种调度方式,比如 rr(轮询)、wrr(加权轮询)、lc(最少连接)等。这比 iptables 默认的随机后端选择更“像一个负载均衡器”。::cite[216]

3.4 为什么现在学 IPVS 仍然有意义

虽然我们这一章以 Kubernetes v1.32 的学习视角来写,但需要补充一个重要背景:官方后续文档已经在 v1.35 将 IPVS 模式标记为 deprecated。 原因不是它不快,而是它与 Kubernetes Service API 的某些边界场景并不完全契合,长期维护成本较高,官方更推荐把 nftables 作为后续方向。::cite[216]

这并不影响你学习 IPVS。因为很多现网老集群、历史排障文档、云厂商旧版本环境里,仍然可能遇到 IPVS。把它学懂,排障时会非常有用。::cite[216]

4. iptables 与 IPVS:到底差在哪

4.1 性能视角

  • iptables:规则越多,维护和同步成本越明显,但从 1.28 以后增量同步已经改进很多。::cite[216]
  • IPVS:依赖哈希表与内核态虚拟服务表,在大量 Service / Endpoint 场景里同步效率和吞吐历史上更占优。::cite[216]

4.2 维护视角

  • iptables:系统工具更通用,iptables-saveiptables -t nat -L -n 都能直接看。排障路径很 Linux 原生。::cite[216]
  • IPVS:需要理解 ipvsadm 输出、虚拟服务表、后端 real server 概念。对纯 Kubernetes 使用者来说心智负担更高。::cite[216]

4.3 排障视角

  • iptables 更适合“顺着规则链查”,适合排查 DNAT、MASQUERADE、NodePort 行为。
  • IPVS 更适合观察“虚拟服务 -> real server”映射是否存在,但遇到边界兼容问题时,排查思路往往不如 iptables 直观。::cite[216]

4.4 现实建议

如果你是学习 Kubernetes v1.32,两种模式都要懂;如果你要理解今天的官方趋势,最好再知道一点:未来方向更偏向 nftables 或 eBPF 数据面,而不是继续扩大 IPVS 的使用面。::cite[216]

5. 实操:观察 Service 在节点上的转发行为

5.1 准备业务示例 YAML

apiVersion: v1
kind: Namespace
metadata:
  name: unit4-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-demo
  namespace: unit4-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: echo-demo
  template:
    metadata:
      labels:
        app: echo-demo
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: echo-svc
  namespace: unit4-service
spec:
  selector:
    app: echo-demo
  ports:
    - name: http
      port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: client
  namespace: unit4-service
spec:
  containers:
    - name: busybox
      image: busybox:1.36
      command:
        - sh
        - -c
        - sleep 360000

5.2 应用并验证 Service 可用

kubectl apply -f service-demo.yaml
kubectl get pod -n unit4-service -o wide
kubectl get svc -n unit4-service
kubectl exec -n unit4-service client -- wget -qO- http://echo-svc

这一步确认的是:业务层访问 Service 已经正常,接下来我们看节点层规则。

5.3 查看 kube-proxy 当前模式

kubectl -n kube-system get configmap kube-proxy -o yaml

一般可以在配置中看到 mode: iptablesmode: ipvs

5.4 如果是 iptables 模式,观察规则

iptables-save | grep KUBE-SVC
iptables-save | grep echo-svc

你通常会看到若干 KUBE-SVC-*KUBE-SEP-* 规则链。学习时不用死记每条链名,重点是理解:Service 有一组规则,后端 Endpoint 又有各自规则,流量是在这些规则间被一步步导走的。::cite[216]

5.5 如果是 IPVS 模式,观察虚拟服务表

ipvsadm -Ln

你会看到类似这样的概念:

  • 一个 Virtual Server 对应一个 Service IP:Port;
  • 多个 Real Server 对应后端 Pod IP:Port。

这时 Service 不再主要表现为一串 iptables 链,而更像一个内核里的四层负载均衡条目。::cite[216]

6. YAML 示例:切换 kube-proxy 模式时你会看到什么配置

下面是学习用途的最小示例。生产环境切换前,必须结合发行版、云厂商、系统内核模块与现有连接中断风险一起评估。

6.1 iptables 模式配置示例

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "iptables"
clusterCIDR: 10.244.0.0/16
iptables:
  minSyncPeriod: 1s
  syncPeriod: 30s

这个配置重点体现 2 件事:

  • 代理模式是 iptables
  • 可以通过 minSyncPeriodsyncPeriod 调整规则同步节奏。::cite[216]

6.2 IPVS 模式配置示例

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
clusterCIDR: 10.244.0.0/16
ipvs:
  scheduler: rr

这里的 scheduler: rr 表示采用轮询调度,这也是 IPVS 最典型的负载均衡能力体现。::cite[216]

6.3 切换配置后常见动作

kubectl -n kube-system edit configmap kube-proxy
kubectl -n kube-system rollout restart daemonset kube-proxy

请注意:切换模式可能导致已有连接中断,尤其是在生产集群上。Cilium 官方文档在讨论 kube-proxy replacement 共存与切换时,也特别提醒了服务连接中断风险;这类切换一律要按变更来做。::cite[471]

7. 排障笔记:遇到 Service 不通时怎么想

7.1 先别急着怀疑 DNS

先确认:

kubectl get svc -n unit4-service
kubectl get endpointslice -n unit4-service
kubectl get pod -n unit4-service -o wide

如果 Service 有 ClusterIP,但没有 EndpointSlice 或后端 Pod 不 Ready,那么 kube-proxy 也没法把流量导出去。::cite[216]

7.2 再看 kube-proxy 是否同步成功

kubectl -n kube-system get pod -l k8s-app=kube-proxy
kubectl -n kube-system logs ds/kube-proxy --tail=200

重点关注:

  • 是否 watch 到 Service / EndpointSlice 变化;
  • 是否存在 iptables / ipvs 初始化失败;
  • 是否缺少相关内核模块。::cite[218]

7.3 最后看节点规则层

  • iptables 模式:看 iptables-save
  • IPVS 模式:看 ipvsadm -Ln
  • 两种模式都要结合路由、CNI、NodePort/ExternalTrafficPolicy 等因素综合判断。::cite[216]

8. 本章小结

这一章最值得记住的结论是:

  1. Service 不是一台真实机器,而是一套节点级转发规则的抽象入口。::cite[216]
  2. kube-proxy 的核心职责不是“代理进程转发”,而是“在节点上维护 Service 转发规则”。::cite[218]
  3. iptables 模式更直观,IPVS 模式历史上更偏性能,但官方趋势已经在往 nftables / eBPF 方向演进。::cite[216]

只要你把这三点记住,后面学 Ingress、Gateway、Service Mesh 时,很多“为什么请求能打通”的问题就都会顺了。


📝 版权声明:本文为原创技术博客,转载请注明出处。

如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!

上一篇

3.4 PriorityClass 与 ResourceQuota

下一篇

1.4 第一个 Pod:从 YAML 到运行