这一章要真正掌握的是:
- 为什么有了 Service 还需要 Ingress::cite[536]
- Ingress 资源与 Ingress Controller 到底谁负责“声明”,谁负责“实现”::cite[537]
- 域名、TLS、路径转发、路径重写这些入口能力在 Kubernetes 里怎么落地::cite[536]
- 为什么社区会从 Ingress 逐步走向 Gateway API,以及在 Kubernetes v1.32 视角下为什么要关注 Gateway API GA::cite[286]
如果说 Service 解决的是“集群内部如何稳定访问一组 Pod”,那么 Ingress 与 Gateway 要解决的,就是“外部世界如何优雅进入集群”。Service 只能提供四层入口,而实际生产里我们往往需要七层能力,比如按域名分流、按路径转发、做 TLS 终止、做重写、做灰度。Ingress 就是在这个背景下出现的。::cite[536]
1. 为什么需要 Ingress
1.1 Service 已经能暴露应用,为什么还不够
如果你只想把一个应用暴露出去,NodePort 或 LoadBalancer 就够了。但一旦你有多个 HTTP 服务,就会很快遇到问题:
- 每个服务都独立占一个端口,不够优雅;
- 很难按域名分流;
- HTTPS 证书管理分散;
- URL 路径治理能力弱。::cite[536]
Ingress 的目标,就是把这些“HTTP/HTTPS 入口管理”能力抽象出来,让你用一个统一入口处理多个 Service。::cite[536]
1.2 Ingress 更像“路由规则”,不是完整实现
Ingress 资源本身只是声明:
- 这个域名怎么匹配;
- 这个路径怎么转发;
- TLS 用哪个 Secret;
- 默认后端是谁。::cite[536]
真正把这些规则翻译成 NGINX、HAProxy、Envoy 或云负载均衡配置的,是 Ingress Controller。官方文档说得非常清楚:想让 Ingress 真正工作,集群里必须运行至少一个 ingress controller。::cite[537]
2. Ingress 资源与 Ingress Controller 的关系
2.1 一句话先讲清楚
- Ingress:你写的 YAML,对外流量规则的声明。
- Ingress Controller:真正监听 Ingress 资源并把规则下发到代理/负载均衡实现中的控制器。::cite[537]
这两者一定要分开理解。很多“为什么我写了 Ingress 却不生效”的问题,根因都不是 YAML 写错,而是控制器没装、没选对、没匹配到 ingressClassName。::cite[537]
2.2 Ingress Controller 会做什么
一个典型控制器会做下面几件事:
- watch Ingress、Service、Endpoints / EndpointSlice、Secret;
- 把规则转换成代理层配置;
- 监听 80/443 或者驱动外部 LB;
- 把流量按 host/path 转发到对应 Service。::cite[537]
所以排查 Ingress 时,永远不要只看 Ingress 对象本身,还要看 Controller 的日志、状态和 class 绑定。::cite[537]
3. Ingress 常见入口能力
3.1 域名路由
最常见的入口能力就是按域名转发,例如:
api.example.com-> API Serviceshop.example.com-> Shop Serviceadmin.example.com-> Admin Service
这类路由让多个服务共享一个统一入口地址或负载均衡器,而不必每个服务一个公网端口。::cite[536]
3.2 TLS 终止
Ingress 可以把 HTTPS 证书通过 Secret 绑定进来,由 Controller 在入口层终止 TLS。这样后端 Service 可以继续只处理 HTTP,证书管理集中在入口侧。::cite[536]
3.3 路径转发
另一个很常见的能力是按路径转发:
/api-> api-service/web-> web-service/static-> static-service
这对前后端拆分、BFF、统一网关入口都很实用。::cite[536]
3.4 路径重写
路径重写不是 Ingress API 的通用内建字段,很多时候依赖具体 Controller 的注解或扩展能力。比如 Ingress NGINX 常通过注解实现 rewrite。也正因为很多高级能力需要靠 annotation 扩展,社区才逐步推动更结构化的 Gateway API。::cite[286]
4. 先看 Ingress:声明式入口怎么写
4.1 准备一组可演示的后端服务
下面的示例用两个简单后端:
web-v1:处理/appapi-v1:处理/api
4.2 业务 YAML
apiVersion: v1
kind: Namespace
metadata:
name: unit4-ingress
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-v1
namespace: unit4-ingress
spec:
replicas: 2
selector:
matchLabels:
app: web-v1
template:
metadata:
labels:
app: web-v1
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-svc
namespace: unit4-ingress
spec:
selector:
app: web-v1
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-v1
namespace: unit4-ingress
spec:
replicas: 2
selector:
matchLabels:
app: api-v1
template:
metadata:
labels:
app: api-v1
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: api-svc
namespace: unit4-ingress
spec:
selector:
app: api-v1
ports:
- port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
---
apiVersion: v1
kind: Secret
metadata:
name: demo-tls
namespace: unit4-ingress
type: kubernetes.io/tls
stringData:
tls.crt: |
-----BEGIN CERTIFICATE-----
REPLACE_WITH_YOUR_CERT
-----END CERTIFICATE-----
tls.key: |
-----BEGIN PRIVATE KEY-----
REPLACE_WITH_YOUR_KEY
-----END PRIVATE KEY-----
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-ingress
namespace: unit4-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
tls:
- hosts:
- demo.example.com
secretName: demo-tls
rules:
- host: demo.example.com
http:
paths:
- path: /app(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: web-svc
port:
number: 80
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-svc
port:
number: 80
4.3 这份 Ingress YAML 到底表达了什么
- 入口域名是
demo.example.com。 - HTTPS 证书来自
demo-tlsSecret。 /app前缀请求转到web-svc。/api前缀请求转到api-svc。- 通过 NGINX 注解把前缀做 rewrite。::cite[536]
这里特别值得注意:rewrite 依赖 NGINX 注解,不是所有 Ingress Controller 都支持这一套写法。 这也是 Ingress API 的一个现实局限。::cite[536]
4.4 实操步骤
kubectl apply -f ingress-demo.yaml
kubectl get ingress -n unit4-ingress
kubectl describe ingress demo-ingress -n unit4-ingress
如果你已经安装了 Ingress NGINX Controller,还可以进一步验证:
kubectl -n ingress-nginx get pods
kubectl -n ingress-nginx get svc
如果本地或测试环境没有域名解析,你可以临时改 /etc/hosts 或通过 curl 指定 Host 头:
curl -k https://<INGRESS_IP>/app -H 'Host: demo.example.com'
curl -k https://<INGRESS_IP>/api -H 'Host: demo.example.com'
5. Ingress 的局限,为什么社区继续演进
官方 Ingress 文档已经明确给出一个非常重要的信号:Kubernetes 推荐使用 Gateway,而 Ingress API 已经冻结(frozen)。 这里的“冻结”不是废弃,而是说它已经不再作为主要新能力的承载对象。::cite[536]
为什么会这样?核心原因有 3 个:
- Ingress 主要面向 HTTP/HTTPS,用途偏窄。::cite[536]
- 很多高级能力只能靠注解实现,可移植性差。::cite[286]
- Ingress 把“基础设施提供者、集群管理员、应用开发者”的角色边界揉在了一起,不够清晰。::cite[286]
于是,Gateway API 开始成为新的演进方向。
6. 从 Ingress 到 Gateway API:设计思路变了什么
6.1 Gateway API 的定位
Kubernetes 官方文档把 Gateway API 描述为一组用于动态基础设施配置和高级流量路由的 API family。它是 role-oriented、protocol-aware、extensible 的。::cite[286]
这几个关键词非常重要:
- Role-oriented:把基础设施提供者、集群运维、应用开发者的职责拆开。::cite[286]
- Expressive:很多以前只能靠 annotation 表达的能力,可以直接结构化描述。::cite[286]
- Portable:不同实现都围绕同一套 CRD 规范。::cite[286]
6.2 Gateway API 的核心资源
官方文档给出的稳定资源包括:
GatewayClass:定义由哪个控制器实现这类 Gateway;Gateway:定义一个真实的流量入口实例;HTTPRoute:定义 HTTP 路由规则;GRPCRoute:定义 gRPC 路由规则。::cite[286]
这比 Ingress 的“一个对象尽量包办所有入口描述”要更分层,也更适合复杂组织协作。::cite[286]
6.3 v1.32 视角下,为什么说 Gateway API 已进入主线
从官方历史里看,Gateway API v1.0 在 2023 年已经 GA;到 2024 年末,Gateway API v1.2 继续进入 GA,并带来 WebSockets、超时、重试等能力演进。也就是说,在 Kubernetes v1.32 的学习语境里,Gateway API 已经不是“未来概念”,而是应该纳入主线学习的入口抽象。::cite[289]
如果你今天还只把 Ingress 当成唯一入口方案,那学习路径就已经落后半拍了。更准确的理解应该是:Ingress 仍然广泛存在,但 Gateway API 正在成为更标准化、更可扩展的下一代入口抽象。::cite[535]
7. 实操:Gateway API 最小可用示例
7.1 Gateway API YAML
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: demo-gateway-class
spec:
controllerName: example.com/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: demo-gateway
namespace: unit4-ingress
spec:
gatewayClassName: demo-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
hostname: demo.example.com
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demo-route
namespace: unit4-ingress
spec:
parentRefs:
- name: demo-gateway
hostnames:
- demo.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /app
backendRefs:
- name: web-svc
port: 80
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-svc
port: 80
7.2 这个模型与 Ingress 最大的不同
GatewayClass代表“由谁实现”。::cite[286]Gateway代表“入口实例本身”。::cite[286]HTTPRoute代表“业务路由规则”。::cite[286]
这意味着入口基础设施与业务路由真正做到了职责分离。对平台团队和应用团队协作来说,这是非常大的改进。::cite[286]
7.3 实操步骤
kubectl apply -f gateway-demo.yaml
kubectl get gatewayclass
kubectl get gateway -n unit4-ingress
kubectl get httproute -n unit4-ingress
kubectl describe gateway demo-gateway -n unit4-ingress
kubectl describe httproute demo-route -n unit4-ingress
请注意:和 Ingress 一样,只有在你的集群里安装了支持 Gateway API 的实现时,这些资源才会真正工作。 Gateway API 是 add-on API family,不是“只写 CRD 就自动有转发能力”。::cite[286]
8. Ingress 与 Gateway API 的学习建议
8.1 当前工程实践怎么学
最务实的学习路线是:
- 先学会 Ingress,因为它现在仍然大量存在;
- 再学 Gateway API,因为它代表新一代主线能力;
- 学任何入口对象时,都同时看“资源声明 + 控制器实现”。::cite[537]
8.2 做架构设计时怎么选
- 已有 Ingress NGINX 体系、诉求简单:继续用 Ingress 完全没问题。
- 要做平台化入口治理、跨团队分工清晰、能力更结构化:优先评估 Gateway API。
- 如果你写了很多 Controller 专属注解:说明你已经在碰 Ingress 的边界了,Gateway API 往往更值得投入。::cite[536]
9. 本章小结
这一章最关键的结论有 4 个:
- Ingress 解决的是七层统一入口,不是简单暴露端口。::cite[536]
- Ingress 资源只负责声明,Ingress Controller 才负责真正实现。::cite[537]
- 域名、TLS、路径转发、重写,是最常见也最实用的入口能力。::cite[536]
- Gateway API 已经进入主线,Ingress 仍要会用,但不能只会 Ingress。::cite[286]
学到这里,你应该已经能把“Service 是内部稳定入口”“Ingress / Gateway 是外部访问入口”这两层抽象彻底分开。下一章我们继续看 NetworkPolicy,理解 Kubernetes 网络为什么默认偏开放,以及怎样把它收紧成可控的微服务隔离网络。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!