返回首页

4.4 Ingress 与网关

这一章要真正掌握的是:

  • 为什么有了 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 已经能暴露应用,为什么还不够

如果你只想把一个应用暴露出去,NodePortLoadBalancer 就够了。但一旦你有多个 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 会做什么

一个典型控制器会做下面几件事:

  1. watch Ingress、Service、Endpoints / EndpointSlice、Secret;
  2. 把规则转换成代理层配置;
  3. 监听 80/443 或者驱动外部 LB;
  4. 把流量按 host/path 转发到对应 Service。::cite[537]

所以排查 Ingress 时,永远不要只看 Ingress 对象本身,还要看 Controller 的日志、状态和 class 绑定。::cite[537]

3. Ingress 常见入口能力

3.1 域名路由

最常见的入口能力就是按域名转发,例如:

  • api.example.com -> API Service
  • shop.example.com -> Shop Service
  • admin.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:处理 /app
  • api-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-tls Secret。
  • /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 个:

  1. Ingress 主要面向 HTTP/HTTPS,用途偏窄。::cite[536]
  2. 很多高级能力只能靠注解实现,可移植性差。::cite[286]
  3. 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 当前工程实践怎么学

最务实的学习路线是:

  1. 先学会 Ingress,因为它现在仍然大量存在;
  2. 再学 Gateway API,因为它代表新一代主线能力;
  3. 学任何入口对象时,都同时看“资源声明 + 控制器实现”。::cite[537]

8.2 做架构设计时怎么选

  • 已有 Ingress NGINX 体系、诉求简单:继续用 Ingress 完全没问题。
  • 要做平台化入口治理、跨团队分工清晰、能力更结构化:优先评估 Gateway API。
  • 如果你写了很多 Controller 专属注解:说明你已经在碰 Ingress 的边界了,Gateway API 往往更值得投入。::cite[536]

9. 本章小结

这一章最关键的结论有 4 个:

  1. Ingress 解决的是七层统一入口,不是简单暴露端口。::cite[536]
  2. Ingress 资源只负责声明,Ingress Controller 才负责真正实现。::cite[537]
  3. 域名、TLS、路径转发、重写,是最常见也最实用的入口能力。::cite[536]
  4. Gateway API 已经进入主线,Ingress 仍要会用,但不能只会 Ingress。::cite[286]

学到这里,你应该已经能把“Service 是内部稳定入口”“Ingress / Gateway 是外部访问入口”这两层抽象彻底分开。下一章我们继续看 NetworkPolicy,理解 Kubernetes 网络为什么默认偏开放,以及怎样把它收紧成可控的微服务隔离网络。


📝 版权声明:本文为原创技术博客,转载请注明出处。

如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!

上一篇

3.1 调度器原理:Pod 为什么会落到这台节点

下一篇

7.1 Metrics:Prometheus + Grafana