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、伪装等辅助功能)。其核心工作流程如下:
- 创建虚拟网卡:kube-proxy 创建一个名为
kube-ipvs0的虚拟网卡,并将所有 Service 的 ClusterIP 绑定到这个网卡上(作为辅助 IP)。这样,发往 ClusterIP 的数据包就会被内核中的 ipvs 模块捕获。 - 创建 ipvs 虚拟服务器:对于每个 Service(类型为 ClusterIP、NodePort、LoadBalancer),kube-proxy 会创建一个 ipvs virtual server(VS),VS 的地址为 Service IP,端口为 Service Port,协议为 Service 协议。
- 绑定真实服务器:根据 Service 关联的 Endpoints(Pod IP 列表),kube-proxy 为每个 VS 添加对应的真实服务器(RS),RS 的地址为 Pod IP,端口为 targetPort。
- 设置调度算法:根据 Service 是否配置
sessionAffinity以及 kube-proxy 启动参数,为每个 VS 分配调度算法(默认为rr轮询)。 - 辅助 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_rr、ip_vs_wrr、ip_vs_sh等),还需要安装ipset和iptables(部分依赖)。在定制内核或某些容器化环境下需确保已加载。 - 配置相对复杂:相比 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 模块:
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
# 可选其他调度算法模块- 安装
ipset和ipvsadm(用于查看规则):
# CentOS/RHEL
yum install -y ipset ipvsadm
# Ubuntu/Debian
apt-get install -y ipset ipvsadm修改 kube-proxy 配置以启用 ipvs 模式:
- 对于使用 ConfigMap 管理的 kube-proxy:
kubectl edit configmap kube-proxy -n kube-system修改 mode 字段:
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-proxy
namespace: kube-system
data:
config.conf: |
...
mode: "ipvs"
ipvs:
scheduler: "rr" # 全局默认算法
...删除 kube-proxy Pod 以使其重新加载配置(DaemonSet 会自动重建):
kubectl delete pod -l k8s-app=kube-proxy -n kube-system验证 ipvs 模式是否生效:
# 查看节点内的 ipvs 规则
ipvsadm -L -n如果能看到对应 Service IP 的 Virtual Server 以及后端的 Real Server,则表示已成功切换到 ipvs 模式。
验证与调试常用命令
- 查看所有 ipvs 虚拟服务器:
ipvsadm -l -n- 查看指定 IP 的虚拟服务器及其后端:
ipvsadm -l -n | grep <service-ip>- 统计连接数:
ipvsadm -l -n --stats- 实时监控连接分布(需安装
ipvsadm并开启内核事件):
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 模式,以满足未来的增长需求。
