简介:本文系统梳理Kubernetes环境下的负载均衡方案体系,从Service四层转发到Ingress七层路由,再到外部负载均衡器与服务网格,逐一剖析其工作原理、适用场景与优缺点。同时结合conntrack表溢出导致间歇性503的真实案例,揭示负载均衡配置中的隐性陷阱,帮助读者建立完整的选型思路与排障能力。
在Kubernetes集群中,”负载均衡”是一个被频繁提及却又容易被简化的概念。很多开发者第一反应是”Service不就是负载均衡吗”,但在实际生产环境中,流量从集群外部进入、在Pod之间分发、再到服务间调用,每一层的负载均衡机制都不相同,各自解决的问题和引入的约束也截然不同。如果不理解这些方案的边界,就容易在排障时陷入”日志一切正常但用户就是偶发失败”的困境。
本文将从流量路径出发,系统梳理K8s中主流的负载均衡方案,分析各自的优缺点与适用场景,并结合一个典型的隐性故障案例,说明负载均衡配置中容易被忽视的细节。
在讨论具体方案之前,有必要先建立一个分层视角。K8s的负载均衡大致可以划分为四个层次:
这四层并非互斥,生产环境往往是组合使用。理解每一层的职责,才能判断某个问题应该在哪一层解决。
Service是K8s最基础的负载均衡抽象。它为后端Pod提供稳定的虚拟IP(ClusterIP)和DNS名称,并通过kube-proxy将访问VIP的流量转发到选中的Pod。常见的实现模式包括iptables模式和IPVS模式。
集群内部服务间调用、对七层路由无要求的简单暴露场景,是绝大多数服务的默认选择。
Ingress通过声明式规则定义外部流量如何到达集群内服务,规则可以基于Host和Path匹配,并支持TLS终止。Ingress本身只是一个抽象规范,实际生效需要部署Ingress Controller(如基于Nginx、Envoy等数据面的控制器)。Gateway API则是对Ingress的演进,将资源职责拆分得更细(GatewayClass、Gateway、HTTPRoute等),支持更强的表达能力和多租户场景。
需要统一南北向入口、按域名或路径分发、集中做TLS与入口治理的场景。
当Service以LoadBalancer类型暴露时,云环境通常会自动创建或关联一个外部负载均衡实例,将流量转发到各节点的NodePort或直接到Pod。自建环境则常用Keepalived+VIP、或部署边缘代理的方式实现类似能力。
对外暴露服务、需要公网入口或跨VPC访问的生产业务。
服务网格通过数据面代理(Sidecar或节点级代理)接管服务间流量,实现七层负载均衡、重试、熔断、流量切分等能力。控制面负责下发路由与策略配置。
大规模微服务、需要精细化流量治理和多环境灰度发布的组织。
理解了分层之后,再看一个真实场景:服务间歇性返回503,应用日志却完全正常,没有任何error记录,重启Pod后短暂恢复,几小时后又复发。
这类问题的迷惑性在于,它把排查方向引向了应用层,而真实原因往往在数据面。一个典型根因是conntrack表溢出。
Linux的netfilter使用conntrack(连接跟踪)表记录连接状态,NAT、iptables转发都依赖它。当表项数量达到上限(由nf_conntrack_max控制)时,新连接无法被跟踪,内核会丢弃数据包,表现为连接建立失败。对于客户端而言,就是间歇性的503或超时;而请求根本没到达应用进程,自然在应用日志里看不到任何异常。
排查思路可以按以下步骤展开:
# 查看当前conntrack使用量与上限sysctl net.netfilter.nf_conntrack_countsysctl net.netfilter.nf_conntrack_max# 观察是否接近上限cat /proc/sys/net/netfilter/nf_conntrack_count
同时可以在节点上观察内核日志中是否有类似”nf_conntrack: table full, dropping packet”的记录。如果确认是表溢出,通常的处理方向包括:
nf_conntrack_max,并同步调整nf_conntrack_buckets;nf_conntrack_tcp_timeout_established等超时时间,加速表项回收;这个案例的启示是:负载均衡链路上的每一跳都可能成为瓶颈,应用层日志正常不代表请求链路正常。 在四层转发路径上,内核参数、连接跟踪、iptables规则规模都是需要纳入容量规划的因素。
综合来看,负载均衡方案的选择应遵循以下原则:
K8s的负载均衡不是单一方案的选择题,而是分层组合的设计题。理解每一层的能力边界,既能在架构设计时做出合理取舍,也能在出现”日志正常但服务异常”这类问题时,快速把排查范围从应用层收敛到数据面,少走弯路。