第27章 Ingress 与南北流量:Ingress-nginx 与 Gateway API
学习目标
- 分清南北流量与东西流量,理解 Ingress 管的是"入口"
- 看清 Ingress = 规则(API 对象)+ Ingress Controller(真正干活的反向代理)
- 走通流量路径:client → LB/NodePort → Controller → 后端 Pod
- 理解 Ingress 的局限与 Gateway API 新标准
前置知识
原理
南北 vs 东西流量
南北流量(North-South):集群外 ←→ 集群内 ← Ingress 管这个
用户 → [Ingress] → 集群内服务
东西流量(East-West):服务 ←→ 服务(集群内部) ← Service Mesh 管这个(第26/29章)
服务A → 服务B
本章讲南北入口:外部请求如何进入集群。
Ingress = 规则 + Controller(关键认知)
很多人以为 Ingress 是个代理——不是。Ingress 是两部分:
① Ingress 资源(K8s API 对象)= 一份"路由规则声明"
host/path → Service,仅仅是声明,自己不转发任何流量
② Ingress Controller = 真正的反向代理(Nginx/Envoy/HAProxy/Traefik)
它 watch K8s API,把 Ingress 规则翻译成自己的配置,真正接流量、转发
Ingress 资源是"想要什么",Ingress Controller 是"怎么实现"。 只创建 Ingress 资源而没装 Controller,啥也不会发生——这是新手头号困惑。
Ingress Controller 的工作原理
以 ingress-nginx 为例(k8sLab 第14课):
ingress-nginx Pod 内:
[controller 进程] watch K8s API(Ingress/Service/Endpoints 变化)
│ 变化时
▼ 生成/更新 nginx.conf(host/path → upstream)
[nginx 反向代理] 按配置接流量、转发到后端 Pod
- 路由规则变 → 重新生成 nginx.conf → reload
- Endpoints 变(Pod 扩缩容) → ingress-nginx 用 Lua 动态更新 upstream,避免频繁 reload(呼应 第13章 OpenResty)
流量路径全景
外部 Client
│
▼ ① 经云 LB(type=LoadBalancer)或 NodePort 进集群
[ingress-nginx Service]
│
▼ ② 到 ingress-nginx Controller Pod(反向代理)
[Controller: 按 host/path 选后端]
│
▼ ③ 直接转发到后端 Pod IP(通常跳过 ClusterIP/kube-proxy,直连 Endpoints)
[业务 Pod]
注意③:ingress-nginx 通常从 Endpoints 拿到 Pod IP 直连,绕过 Service 的 ClusterIP(kube-proxy),减少一跳、负载更均(呼应 第09章连接级 LB)。
Ingress 资源示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # 高级功能靠 annotation(各家不通用!)
spec:
ingressClassName: nginx # 指定哪个 Controller 处理
tls:
- hosts: [app.example.com]
secretName: app-tls # TLS 终止用的证书(第05章)
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend: { service: { name: api-svc, port: { number: 80 } } }
- path: /
pathType: Prefix
backend: { service: { name: web-svc, port: { number: 80 } } }
Ingress 的局限 → Gateway API
Ingress 资源表达力很弱:只有 host/path,其它高级能力(重写、灰度、限流、mTLS)全靠 annotation,而 annotation 各家 Controller 不通用——换个 Controller 就得重写。
Gateway API 是 K8s 新的入口标准,解决这些痛点:
| Ingress | Gateway API | |
|---|---|---|
| 表达力 | 弱(host/path + annotation) | 强(原生支持流量切分、Header 匹配、跨命名空间等) |
| 可移植 | 差(annotation 各家不同) | 好(厂商中立的 CRD) |
| 角色分离 | 无 | 有(GatewayClass/Gateway/Route 分给不同角色) |
| 协议 | 主要 HTTP | HTTPRoute/TLSRoute/GRPCRoute/TCPRoute |
Gateway API 的三层对象:
GatewayClass(厂商实现,集群级,类似 IngressClass)
└─ Gateway(监听器:端口/协议/证书,平台运维管)
└─ HTTPRoute(路由规则:host/path/header→Service,应用开发管)
这种角色分离(基础设施 / 平台 / 应用各管一层)是 Gateway API 的核心理念,也是 Service Mesh 与 Ingress 走向统一的方向(第29章)。
️ 实现 / 命令
实验一:装 Controller + 创建 Ingress
# 装 ingress-nginx
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml
kubectl apply -f web-ingress.yaml
# 访问验证(Host 头要匹配 rule)
curl -H "Host: app.example.com" http://<node-ip>:<nodeport>/api
实验二:看 Controller 生成的 nginx.conf
# Ingress 规则被翻译成了真实的 nginx 配置
kubectl exec -n ingress-nginx <controller-pod> -- cat /etc/nginx/nginx.conf | grep -A5 "app.example.com"
# server { server_name app.example.com; location /api { ... proxy_pass ... } }
亲眼看到你的 Ingress YAML 变成了 第13章 的 nginx server/location——Ingress Controller 就是个被 K8s 驱动的 Nginx。
实验三:Gateway API(新标准)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata: { name: prod-gw }
spec:
gatewayClassName: nginx
listeners:
- { name: http, protocol: HTTP, port: 80 }
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: { name: web-route }
spec:
parentRefs: [{ name: prod-gw }]
hostnames: ["app.example.com"]
rules:
- matches: [{ path: { type: PathPrefix, value: /api } }]
backendRefs: [{ name: api-svc, port: 80 }]
排错
| 现象 | 根因 | 解决 |
|---|---|---|
| 创建 Ingress 没反应 | 没装 Controller | 装 ingress-nginx 等 |
| 404 default backend | host/path 不匹配 | 核对 Host 头、pathType |
| 多个 Controller 抢 | 没指定 ingressClassName | 显式设 ingressClassName |
| TLS 不生效 | secretName 证书缺失/错 | 检查 secret(第05章) |
| annotation 不生效 | 换了 Controller,annotation 不通用 | 用对应 Controller 的 annotation,或迁 Gateway API |
| 外部访问不到 | LB/NodePort 没暴露 | 检查 ingress-nginx Service 类型 |
本章小结
- 南北流量靠 Ingress(入口),东西流量靠 Mesh(第26/29章)。
- Ingress = 规则(API 对象)+ Controller(真正的反向代理);只建规则不装 Controller 无效。
- ingress-nginx 把 Ingress 规则翻译成 nginx.conf,Endpoints 变化用 Lua 动态更新;通常直连 Pod IP。
- Ingress 表达力弱、annotation 不通用 → Gateway API(角色分离、厂商中立、多协议)是新方向。
下一章 第28章 Egress 出网治理,把方向反过来:集群内的 Pod 如何安全、可控、可审计地访问外部世界——这是企业 K8s 落地的安全刚需。