Tip
云负载均衡(Cloud Load Balancer,简称 云LB)的核心工作原理是将客户端的并发访问流量,通过预设的转发策略和调度算法,均匀、合理地分发到后端的多个云服务器(ECS/实例)上,以此消除单点瓶颈,提升系统的整体并发处理能力与高可用性
核心组件
- 虚拟IP(VIP):云LB对外暴露的统一访问入口。公网LB使用弹性公网IP,私网LB使用内网虚拟IP。
- 监听器(Listener):负责监听特定端口上的网络请求(如 HTTP 80、HTTPS 443、TCP 8080),并根据规则分发流量。
- 转发策略/路由规则:决定流量的去向。例如在七层负载均衡中,可以根据不同的域名(Host)或URL路径(Path)将请求发往不同的服务器组。
- 后端服务器组(Backend Server Group):接收并处理请求的真实云服务器集群。
工作流程
[客户端请求] ──> [统一入口: VIP] ──> [监听器过滤] ──> [算法/策略筛选] ──> [健康的后端服务器]- 接收请求
客户端通过域名解析(DNS)访问云LB绑定的虚拟IP(VIP)。 - 监听与匹配
云LB的监听器截获该请求,检查其使用的协议和端口是否与配置匹配。如果不匹配则直接拒绝;如果匹配,则准备将请求投递给后端。 - 策略评估与隔离
监听器会结合健康检查机制,实时剔除那些已经发生故障的后端服务器,确保流量只会被分发到“健康”的资源上。 - 算法调度与转发
监听器根据预设的调度算法(如轮询、加权轮询、最小连接数、源IP Hash),选出一台最合适的后端服务器,并将请求包转发过去。服务器处理完后,再将结果返回给客户端。
四层/七层
| 特性 | 四层负载均衡(例如:NLB / CLB) | 七层负载均衡(例如:ALB) |
|---|---|---|
| 工作层级 | 传输层(TCP/UDP 协议) | 应用层(HTTP/HTTPS/QUIC 协议) |
| 工作原理 | 不拆包。只分析IP和端口,通过修改数据包的源/目的IP和端口(NAT技术),直接将请求快速转发给后端服务器。 | 拆包代理。LB先与客户端建立TCP连接,解析应用层内容后,再与后端服务器建立新的TCP连接(反向代理模式)。 |
| 转发依据 | 源IP、目的IP、端口、协议 | URL路径、域名、Cookie、HTTP请求头等 |
| 适用场景 | 适合超大流量、对延迟极度敏感、不需要识别业务内容的场景(如视频流媒体、游戏连接)。 | 适合需要精细化路由的复杂 Web 应用、微服务架构、动静分离、灰度发布等场景。 |
常用调度算法
- 轮询/加权轮询(Round Robin):按顺序挨个分发请求。如果性能不同的服务器混用,可设置“权重”,性能好的服务器接收更多流量。
- 最少连接数(Least Connections):优先把新请求发送给当前并发连接数最少的服务器,适合处理请求耗时差异较大的业务(如长连接服务)。
- 源IP哈希(Source IP Hash):根据客户端的 IP 地址计算哈希值,使来自同一个 IP 的请求始终分发到同一台后端服务器。常用于保持用户的登录状态(会话保持)。
架构流派
四层云 LB + 集群内 Ingress Controller(最经典、最通用)
- 组合方式:购买云厂商的 四层 LB 挂在最前面,后端对准集群内的 Nginx Ingress Pod。
- 流量走法:
- 外部流量打到云四层 LB。
- 四层 LB 像个纯粹的搬运工,只看 TCP 端口,闭着眼睛把流量甩给节点的 NodePort。
- 流量进入集群后,由集群内的 Nginx Ingress 承担七层路由的重任,拆开 HTTP 包,根据 URL(如
/order)分流给不同的业务 Pod。
- 优点:省钱且极其灵活。只需要买一个便宜的四层云 LB 守大门,集群内部的七层路由规则(如灰度、限流)全部用 Yaml 写在 K8s 里,不需要每次都去调云厂商的 API。
七层云 LB 直接当 Ingress(云原生直通模式)
- 组合方式:在 K8s 里写一个标准的 Ingress Yaml,云厂商的控制器在外面自动为创建一个云七层 LB。
- 流量走法:
- 外部流量直接打到云七层 LB。
- 云七层 LB 在云端直接解密 HTTPS 证书,直接读取 HTTP 的 Path(如
/api/v2)。 - 云七层 LB 绕过集群内所有的 Nginx 组件,直接把流量弹射到业务 Pod 的 IP 上。
- 优点:链路最短,性能调优省心。集群内少了一层 Nginx Pod 的维护成本,证书管理、DDoS 防御全部托管给云厂商的硬件级七层 LB。
- 缺点:贵。并且云七层 LB 的高级路由功能往往受限于云厂商的控制台功能,不如自建的 Nginx/Envoy 插件生态那么丰富。
优化
流量策略
背景
云LB会自动把集群里的每一个工作节点(Worker Node)都挂载到自己的后端服务器列表里。
外部流量打进来时,云 LB 会根据轮询(Round Robin)或最小连接数等算法,把流量均匀地甩给集群中的任意一个节点
问题产生
当流量落到一个节点上时,会面临两种命运(直连/转发)。假设 Ingress Pod(后端应用)只运行在 Node A 上,但云 LB 把流量甩给了 Node B:
- 流量落地:外部流量到达 Node B 的
NodePort端口。 - 内核检查:Node B 的内核网络栈(
kube-proxy的 iptables/IPVS 规则)一看:“哦,这个包是来找 Ingress Pod 的。” - 发现扑空:Node B 检查了一下自己本地,发现自己身上并没有运行 Ingress Pod。
- 内部倒手(跨节点转发):Node B 只能通过内部的 Calico 网络(BGP 或 IPIP 隧道),把这个数据包跨网络再次转发给 Node A。
- 到达终点:Node A 收到 Node B 倒手过来的包,最终送进 Ingress Pod。
问题
- 多跳损耗(Extra Hop):流量在集群内部无谓地多跨了一次网络,导致网络延迟(Latency)增加。
- 丢失真实客户端 IP:当 Node B 把包倒手给 Node A 时,为了让响应包能原路返回,Node B 会对数据包做一次 SNAT(源地址转换)。这导致 Ingress Pod 拿到的“客户端 IP”全都变成了 Node B 的内网 IP,你在应用日志里根本看不见真正用户的公网 IP。
解决
spec: externalTrafficPolicy: Local # 默认为 Cluster
参数修改影响
1. 云 LB 的健康检查联动
当改为 Local 后,K8s 上的云厂商组件(CCM)会通知云 LB:“请开启特殊的端口健康检查!”
- 云 LB 会去主动探测所有节点的特殊端口。
- Node A 身上有 Ingress Pod,它回应:“我这里有货,健康!” -> 云 LB 保留 Node A。
- Node B 身上没有 Ingress Pod,它回应:“我这里没货,不健康!” -> 云 LB 立刻把 Node B 从后端列表中剔除(隔离)。
2. 完美的流量路径
此时,云厂商的公网 LB 只会把流量甩给真正运行了 Ingress Pod 的节点(Node A)。
- 流量到达 Node A 后,内核直接直通本地的 Pod。
- 零跨节点转发(没有多跳,延迟极低)。
- 保留真实客户端 IP:因为不需要 Node 之间倒手,Node A 不会做 SNAT。你的 Ingress(Nginx)日志里可以清清楚楚地看到每一个外部用户的真实公网 IP。
策略对比
流量策略 (externalTrafficPolicy) | Cluster(默认行为) | Local(生产推荐优化) |
|---|---|---|
| 云 LB 后端挂载哪些节点 | 集群内的所有 Worker 节点 | 只有当前运行了该 Pod 的节点 |
| 集群内部是否二次转发 | 是(如果流量砸中了没有 Pod 的节点) | 否(直达目标节点,本地直接消费) |
| 客户端真实 IP 保持 | 丢失(变成宿主机内网 IP) | 完美保留(看到用户真实公网 IP) |
| 负载均衡均衡度 | 云 LB 级别绝对均衡,但由于内部转发,Pod 负载可能略有倾斜 | 流量直接精准按 Pod 数量平摊,完全由云 LB 调度 |