深色模式
南北向流量与负载均衡
摘要:本文梳理从集群外部进入的“南北向流量”路径,对比 NodePort / 云 LoadBalancer / MetalLB 的适用边界,并解释
externalTrafficPolicy对客户端源 IP 与负载分布的权衡。覆盖版本:Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+。
- 工具:
kubectl。 - 前提:理解 Service 三种类型(见
service.md)、Ingress(见ingress.md)。
背景与问题:什么是南北向
在 K8s 网络语境里:
- 南北向(North-South):集群外部 ↔ 集群内部的流量(用户访问服务)。
- 东西向(East-West):集群内部 Pod ↔ Pod 的流量。
本文聚焦南北向:外部客户端如何可靠、高效、可观测地访问集群内服务,以及负载均衡器的选型。HTTP 类流量通常经 Ingress 收敛到一个 LB(见 ingress.md、ingress-nginx.md),非 HTTP 或简单暴露则直接用 Service。
三种入口方式
方式 A:NodePort
每个节点开 30000–32767 的固定端口,外部通过 <任意节点IP>:<NodePort> 访问。优点是无额外依赖;缺点是端口有限、客户端要感知节点 IP、节点挂了对应入口就断。一般只用于开发或作为其他方案的底层(LB 实际也走 NodePort)。
方式 B:LoadBalancer(云 / MetalLB)
云环境由 cloud-controller 创建外部 LB,转发到 NodePort;裸金属由 MetalLB 接管 IP 分配与通告(Layer2 用 ARP/NDP,BGP 与路由器对等)。生产对外首选方式。
生产危险
裸金属集群若没装 MetalLB / 云控制器,直接建 LoadBalancer 会永久 Pending(EXTERNAL-IP 为 <pending>)。不要把每个服务都建一个 LB——每个 LB 都有成本,HTTP 场景应集中到一个 Ingress LB。
方式 C:Ingress(HTTP 收敛)
单个 LB + Ingress Controller,按 host/path 把 HTTP 流量分到多个后端 Service,最省成本、最灵活(详见 ingress.md)。
externalTrafficPolicy:源 IP 与分布的权衡
这是南北向最关键的旋钮。externalTrafficPolicy 决定外部流量能否在节点间跳转:
| 策略 | 源 IP | 负载分布 | 额外跳数 |
|---|---|---|---|
Cluster(默认) | 被 SNAT 改写(Pod 看到节点 IP) | 均匀(跨所有节点 Pod) | 可能多一跳 |
Local | 保留真实客户端 IP | 仅接收节点上有本地 Pod 的才收流量,可能不均 | 无额外跳 |
yaml
apiVersion: v1
kind: Service
metadata:
name: web-lb
spec:
type: LoadBalancer
externalTrafficPolicy: Local # 保留客户端源 IP
selector:
app: web
ports:
- port: 80
targetPort: 80801
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
何时用 Local
需要真实客户端 IP 做审计/限流/风控时(如 WAF、日志),用 Local。但要保证每个节点都有该服务的 Pod(或用拓扑/反亲和 + 充足副本),否则部分节点收不到流量、健康检查失败。Cloud LB 对 Local 模式只对“运行了匹配 Pod 的节点”做健康探测。
注意
Local 模式下,若某些节点没有后端 Pod,这些节点上的 LB 健康探测失败,流量不会分到它们,可能造成容量利用不均。务必配合充足的副本数与调度策略。
MetalLB 实战
MetalLB 安装后,只需把 Service 设为 type: LoadBalancer,它会分配 IP 并通告。可通过 IPAddressPool 与 L2Advertisement 控制地址池:
yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: production-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.240-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: production-l2
namespace: metallb-system
spec:
ipAddressPools:
- production-pool1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
yaml
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
annotations:
metallb.io/address-pool: production-pool
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 4431
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[厂商特定] MetalLB 为社区项目,Layer2 模式在某个时刻只有一个节点吸引某 Service IP(leader),故障切换有短暂收敛;BGP 模式依赖网络设备支持。[未实测] 具体收敛时间与网络拓扑相关,建议预发演练。
限制来源 IP
云 LB 支持 loadBalancerSourceRanges 把访问限制到特定 CIDR(实现为 LB 防火墙规则):
yaml
spec:
type: LoadBalancer
loadBalancerSourceRanges:
- 203.0.113.0/241
2
3
4
2
3
4
厂商差异
各云通过不同注解请求内部/外部 LB、配健康检查等(如 AWS service.beta.kubernetes.io/aws-load-balancer-internal: 'true')。这些注解不通用 [厂商特定],迁移云厂商需重写。
生产实践
- HTTP 服务统一走 Ingress + 单 LB,不要每个服务建 LB。
- 需要客户端 IP 且无 Ingress 层时,对 Service 用
externalTrafficPolicy: Local并保障副本分布。 - 裸金属必装 MetalLB(或等价方案)才能用 LoadBalancer。
- 监控 LB:云 LB 配额、健康检查状态、连接数;MetalLB 看 speaker/controller 日志与事件(
kubectl describe svc)。
验证
bash
kubectl get svc -A -o custom-columns=\
NS:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,\
EXT:.status.loadBalancer.ingress[0].ip
# 测试源 IP 是否保留(后端打印 RemoteAddr)
kubectl logs <backend-pod> | grep RemoteAddr1
2
3
4
5
2
3
4
5
回滚与清理
bash
kubectl delete svc web-lb
# 云 LB 会被云控制器异步回收;MetalLB 释放 IP 回池1
2
2
故障排查
- LB 一直 Pending:缺 MetalLB/云控制器。
- 客户端 IP 全变成节点 IP:默认
Cluster策略的 SNAT 所致,改用Local。 - 部分节点不收流量:
Local策略下这些节点无后端 Pod。 - 外部访问超时:检查 LB 健康检查、节点防火墙、kube-proxy 模式(见
service.md)。
安全与合规
- 外部入口是主要攻击面,结合 Ingress 的 TLS、限流与 NetworkPolicy(见
networkpolicy.md)。 loadBalancerSourceRanges做网络层白名单,但不可替代应用层鉴权。
常见坑
- 每个服务都建 LB 导致成本与配额爆炸。
- 以为
Cluster模式能拿到真实客户端 IP。 - 裸金属忘了装 MetalLB 导致 Pending。
替代方案与权衡
- Ingress / Gateway API:HTTP 七层更优,集中 LB(见
ingress.md)。 - NodePort + 外部 HAProxy/LB:自建可控,但要自己维护外部负载均衡。
- 服务网格入口(Istio Gateway):统一南北+东西治理,复杂度高。