Skip to content

ipvs 模式详解

ipvs(IP Virtual Server)模式是 Kubernetes 自 v1.11 版本起稳定提供的第三种 Service 代理模式,也是目前性能最高、功能最丰富的代理模式。它基于 Linux 内核内置的四层负载均衡器 LVS(Linux Virtual Server),专为大规模服务发现和负载均衡设计,能够支撑上万 Service 的高并发场景。

ipvs 与 LVS 基础

  • ipvs:Linux 内核 netfilter 框架之上的一个模块,实现了传输层(L4)负载均衡,支持 TCP、UDP、SCTP 等协议。它通过 IPVS 虚拟服务器(virtual server)将流量分发到后端的真实服务器(real server)。
  • ipset:Linux 内核中的集合框架,ipvs 模式利用它高效地管理大量 IP 地址(如所有 Service IP 和 Pod IP),避免 iptables 规则爆炸。
  • 调度算法:ipvs 原生支持多种负载均衡算法(rr、wrr、lc、wlc、sh、dh、sed、nq 等)。

工作原理

kube-proxy 以 ipvs 模式运行时,不再依赖 iptables 进行数据包转发(仅保留少量 iptables 规则用于 SNAT、伪装等辅助功能)。其核心工作流程如下:

  1. 创建虚拟网卡:kube-proxy 创建一个名为 kube-ipvs0 的虚拟网卡,并将所有 Service 的 ClusterIP 绑定到这个网卡上(作为辅助 IP)。这样,发往 ClusterIP 的数据包就会被内核中的 ipvs 模块捕获。
  2. 创建 ipvs 虚拟服务器:对于每个 Service(类型为 ClusterIP、NodePort、LoadBalancer),kube-proxy 会创建一个 ipvs virtual server(VS),VS 的地址为 Service IP,端口为 Service Port,协议为 Service 协议。
  3. 绑定真实服务器:根据 Service 关联的 Endpoints(Pod IP 列表),kube-proxy 为每个 VS 添加对应的真实服务器(RS),RS 的地址为 Pod IP,端口为 targetPort。
  4. 设置调度算法:根据 Service 是否配置 sessionAffinity 以及 kube-proxy 启动参数,为每个 VS 分配调度算法(默认为 rr 轮询)。
  5. 辅助 iptables 规则:ipvs 模式仍会创建少量 iptables 规则,主要用于:
    • 处理 NodePort 类型 Service(将外部访问节点端口的数据包重定向到 ipvs)。
    • 处理 LoadBalancer 类型 Service(源地址转换,即 SNAT)。
    • 处理伪造的、非 ipvs 管理的流量(如 kube-proxy 自身的健康检查)。

当一个客户端 Pod 访问 Service 时,数据包路径如下:

  • 数据包离开客户端 Pod 的网络命名空间,进入主节点的内核协议栈。
  • 因为 Service ClusterIP 配置在 kube-ipvs0 网卡上,内核识别出这是一个本地 IP,流量被 ipvs 截获。
  • ipvs 根据 VS 配置的负载均衡算法,选择一个后端 RS(即 Pod IP)。
  • ipvs 执行 DNAT(目标地址转换),将数据包的目标 IP 修改为 Pod IP,并重新发出。
  • 数据包经过路由和网络驱动到达目标 Pod;响应数据包经过连接跟踪(conntrack)自动还原源地址为 Service IP,返回客户端。

整个过程完全在内核态完成,不涉及用户态代理。

负载均衡算法

ipvs 模式支持多种调度算法,可以通过 kube-proxy 启动参数 --ipvs-scheduler 设置全局默认算法,也可以通过 Service 注解 kubectl.kubernetes.io/ipvs-scheduler 为特定 Service 指定算法。

常用算法:

算法说明适用场景
rr(Round Robin)轮询,将请求依次分配给后端 RS,是默认算法。通用,各后端能力相近。
wrr(Weighted RR)加权轮询,根据权重分配。Kubernetes 中通过端点权重(Endpoint 的 weight)实现比例分配。后端能力不均时使用(需配合 EndpointSlice)。
lc(Least Connection)最少连接,将新请求分配给活动连接数最少的 RS。长连接场景(如数据库、WebSocket)。
wlc(Weighted LC)加权最少连接,结合权重和连接数。后端能力不同且连接跨度大。
sh(Source Hashing)源地址哈希,相同源 IP 的请求总是被分配到同一 RS。需要会话保持,可作为 sessionAffinity: ClientIP 的实现方式。
dh(Destination Hashing)目标地址哈希,相同目标 IP 的请求分配到同一 RS。用于缓存、负载均衡中的定向分发。
sed(Shortest Expected Delay)最短期望延迟,基于连接数和权重计算预测延迟。延迟敏感场景。
nq(Never Queue)不排队,有空闲 RS 立即分配,否则随机选一个。避免请求排队堆积。

当 Service 设置了 sessionAffinity: ClientIP 时,kube-proxy 会为该 VS 采用 sh 算法(源地址哈希),从而实现同一客户端 IP 的请求固定到同一个后端 Pod。

优点

  • 性能极高:ipvs 模块在内核层面实现,使用哈希表存储规则,查找时间复杂度 O(1)。即使 Service 数量达到上万,转发性能也几乎没有衰减。
  • 丰富的调度算法:原生支持多种负载均衡算法,适应不同业务需求。
  • 扩展性强:ipvs 本身支持高并发连接(百万级),且连接跟踪(conntrack)开销较小。
  • 规则刷新快: Service 或 Endpoints 变更时,kube-proxy 只需修改 ipvs 相关的 RS,无需像 iptables 那样整体刷新规则集。
  • 支持更大的集群规模:经实测,ipvs 模式可支撑 5000+ Service 和数万个 Pod 的集群,依然保持较低延迟和高吞吐量。
  • 更好的连接处理:ipvs 针对大规模 NAT 场景做了优化,如连接复用、优雅断开等。

缺点与注意事项

  • 依赖内核模块和工具:需要节点内核加载 ip_vs 模块及其相关调度算法模块(ip_vs_rrip_vs_wrrip_vs_sh 等),还需要安装 ipsetiptables(部分依赖)。在定制内核或某些容器化环境下需确保已加载。
  • 配置相对复杂:相比 iptables 模式,初始设置需要额外检查内核模块和工具。
  • 调试难度增加:查看 ipvs 规则需要使用 ipvsadm 工具,不如 iptables 命令为人熟知。
  • 兼容性:早期 Kubernetes 版本(< v1.11)中 ipvs 为 beta,可能存在少量 bug;但自 v1.11 起已稳定。部分网络插件(如 Calico)需要额外配置。

iptables 与 ipvs 模式对比

特性ipvs 模式iptables 模式
规则存储结构哈希表线性链表(规则顺序遍历)
规则刷新方式增删改查 O(1),实时生效整体刷新生效,延迟随规则数线性增长
负载均衡算法多种高级算法(rr、wrr、lc、sh等)仅随机概率(近似轮询)
大 Service 数量(>5000)性能几乎无衰减规则膨胀,刷新延迟增加,CPU 使用飙升
源 IP 保留支持,通过 externalTrafficPolicy: Local支持,同样需配置
会话亲和性支持,基于 sh 算法支持,基于 recent 模块
对节点内核要求需要 ip_vs 模块及 ipset仅需 iptables(所有 Linux 都有)
部署的通用性较高(需预装工具,但现代发行版默认支持)极高(无需额外工具)
推荐使用场景大规模、高性能集群中小规模、通用集群

环境要求与启用步骤

确保节点满足以下条件:

  • Linux 内核版本 >= 4.0(推荐 4.19+)
  • 加载 ip_vs 模块:
bash
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
# 可选其他调度算法模块
  • 安装 ipsetipvsadm(用于查看规则):
bash
# CentOS/RHEL
yum install -y ipset ipvsadm

# Ubuntu/Debian
apt-get install -y ipset ipvsadm

修改 kube-proxy 配置以启用 ipvs 模式:

  • 对于使用 ConfigMap 管理的 kube-proxy:
bash
kubectl edit configmap kube-proxy -n kube-system

修改 mode 字段:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
data:
  config.conf: |
    ...
    mode: "ipvs"
    ipvs:
      scheduler: "rr"   # 全局默认算法
      ...

删除 kube-proxy Pod 以使其重新加载配置(DaemonSet 会自动重建):

bash
kubectl delete pod -l k8s-app=kube-proxy -n kube-system

验证 ipvs 模式是否生效:

bash
# 查看节点内的 ipvs 规则
ipvsadm -L -n

如果能看到对应 Service IP 的 Virtual Server 以及后端的 Real Server,则表示已成功切换到 ipvs 模式。

验证与调试常用命令

  • 查看所有 ipvs 虚拟服务器:
bash
ipvsadm -l -n
  • 查看指定 IP 的虚拟服务器及其后端:
bash
ipvsadm -l -n | grep <service-ip>
  • 统计连接数:
bash
ipvsadm -l -n --stats
  • 实时监控连接分布(需安装 ipvsadm 并开启内核事件):
bash
ipvsadm -l -n --rate

与网络插件的兼容性

ipvs 模式与大多数 CNI 插件兼容,包括:

  • Calico:支持(需使用 kube-proxy 管理 ipvs,Calico 不干扰 ipvs 规则)。
  • Flannel:支持(host-gw 和 VXLAN 均工作正常)。
  • Cilium:支持(Cilium 可替换 kube-proxy,但 ipvs 模式也同时可用)。
  • Weave:支持。

需要注意:如果集群同时使用某些网络策略或服务网格(如 Istio 的 sidecar),需要确保 ipvs 规则不会被意外覆盖。

总结

ipvs 模式是 Kubernetes 为应对大规模、高性能服务发现而设计的终极解决方案。它利用 Linux 内核成熟的 LVS 技术,提供了接近硬件负载均衡器的性能、丰富的调度能力和卓越的可扩展性。对于大型生产集群(Service 数千、Pod 数万),ipvs 模式是首选。虽然需要额外的内核模块和工具检查,但对于现代 Linux 发行版来说,这些要求通常已经满足。从中小规模集群起始,可以平稳地从 iptables 模式迁移到 ipvs 模式,以满足未来的增长需求。