4. Ingress流量入口高可用
Ingress Controller 本身只是集群内的一组 Pod,它要真正对外提供七层入口能力,必须先解决“流量如何从集群外到达这些 Pod”的问题。这一层通常由 Service 或主机网络承担,而 Service 的不同类型决定了入口的可用性边界、故障域和运维方式。理解 LoadBalancer、NodePort、HostNetwork 以及外部负载均衡器集成这四种路径,是设计高可用入口的前提。
四种入口暴露方式的本质差异
从数据面看,四者的区别集中在三个问题:外部流量首先落到哪里、由谁做第一层转发、以及故障时流量能否自动切换。
- LoadBalancer Service:由云厂商或 MetalLB 等控制器分配一个虚拟 IP(VIP),外部流量先到 VIP,再由负载均衡器转发到各节点的 NodePort,最后经 kube-proxy 或 IPVS 到达 Ingress Controller Pod。VIP 本身通常具备健康检查与多节点后端,天然具备一定高可用能力。
- NodePort:在每个节点上开放同一端口(默认 30000–32767),外部流量直接打到任意节点的该端口。它不提供 VIP,也不做节点级健康检查,客户端需要自己选择节点或依赖前置负载均衡器。
- HostNetwork:Ingress Controller Pod 直接使用宿主机网络命名空间,监听节点 IP 的 80/443。没有 Service 转发环节,路径最短、延迟最低,但端口被独占,且 Pod 调度到哪些节点,入口就只存在于哪些节点。
- 外部负载均衡器集成:在集群外已有 F5、Nginx、LVS 或云 SLB 时,把节点或 NodePort 作为后端池,由外部设备统一做 VIP、健康检查和流量分发。它把高可用责任交给外部设备,集群侧只提供稳定的后端端点。
下面的图展示了四种方式从客户端到 Ingress Controller Pod 的流量路径与关键差异点。
LoadBalancer Service:云上与裸金属的两种实现
在公有云中,type: LoadBalancer 的 Service 会触发云控制器向云平台申请一个 SLB/CLB 实例,并自动把集群节点注册为后端。以阿里云 ACK 为例,一个典型的 Service 定义如下:
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
annotations:
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-flag: "on"
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-type: "tcp"
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
这里有两个关键参数。第一是 externalTrafficPolicy:设为 Local 时,流量只转发到本节点上运行的 Ingress Pod,能保留客户端真实源 IP,但要求每个节点都有 Pod;设为 Cluster 时,流量可能被二次转发到其他节点,源 IP 会丢失,但后端覆盖更均匀。第二是健康检查类型,TCP 检查只能判断端口是否监听,HTTP 检查才能识别 Ingress Controller 是否真正可服务。
在裸金属环境中没有云控制器,需要用 MetalLB 等方案提供 VIP。MetalLB 的 L2 模式通过 ARP 宣告 VIP,同一时刻只有一个节点响应,故障时切换到其他节点,切换时间通常在秒级;BGP 模式则与上游路由器建立邻居,把 VIP 作为路由发布,收敛更快,但需要网络设备配合。
NodePort 与 HostNetwork 的取舍
NodePort 的最大问题是客户端必须知道节点 IP,且节点故障后客户端不会自动切换。因此它很少单独暴露给最终用户,更多是作为 LoadBalancer 或外部负载均衡器的后端。它的优势是简单、不依赖任何外部组件,适合测试环境或作为兜底入口。
HostNetwork 则把 Ingress Controller 直接绑到节点 80/443 端口。它的性能最好,因为没有 kube-proxy 的 DNAT 环节,也没有 Service 的额外一跳。但代价是:端口冲突风险高,Pod 必须调度到指定节点,节点故障时入口直接不可用。实践中通常配合 DaemonSet 让每个节点都运行一个 Ingress Pod,再在前端挂一个外部负载均衡器做健康检查和流量分发。
外部负载均衡器集成:把高可用交给专业设备
当企业已有 F5、Nginx Plus、LVS 或云 SLB 时,最稳妥的做法是让外部设备承担 VIP 和健康检查,集群侧只提供稳定的后端端点。后端可以是 NodePort,也可以是 HostNetwork 下的节点 IP:80/443。
以 Nginx 作为外部负载均衡器为例,后端池配置如下:
upstream ingress_backend {
least_conn;
server 10.0.1.11:30080 max_fails=3 fail_timeout=10s;
server 10.0.1.12:30080 max_fails=3 fail_timeout=10s;
server 10.0.1.13:30080 max_fails=3 fail_timeout=10s;
keepalive 32;
}
server {
listen 80;
location / {
proxy_pass http://ingress_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout http_502 http_503;
}
}
这里 max_fails=3 fail_timeout=10s 表示 10 秒内失败 3 次就把该后端摘除,10 秒后再尝试恢复。proxy_next_upstream 让请求在遇到 502/503 时自动重试下一个后端,这是外部负载均衡器提供高可用的核心机制。健康检查建议使用 HTTP 探针指向 Ingress Controller 的 /healthz 端点,而不是简单 TCP 检查,因为 TCP 端口监听不代表七层转发正常。
高可用设计检查清单
| 检查项 | LoadBalancer | NodePort | HostNetwork | 外部 LB |
|---|---|---|---|---|
| 是否有 VIP | 有 | 无 | 无 | 有 |
| 节点故障自动切换 | 支持 | 不支持 | 不支持 | 支持 |
| 保留客户端源 IP | Local 模式支持 | 需 Local 模式 | 天然支持 | 需配置 X-Forwarded-For |
| 额外网络跳数 | 2–3 跳 | 2 跳 | 0 跳 | 1–2 跳 |
| 依赖外部组件 | 云控制器 / MetalLB | 无 | 无 | 外部 LB 设备 |
无论选择哪种方式,Ingress Controller 自身的高可用都是前提:至少 2 个副本、通过 podAntiAffinity 分散到不同节点、配置 readinessProbe 指向真实健康端点、并设置合理的 terminationGracePeriodSeconds 让旧 Pod 在摘除后仍能处理完存量连接。入口层的高可用不是单一组件的能力,而是“外部 VIP + 节点冗余 + Controller 多副本 + 健康检查”共同构成的链路。