摘要:Ingress 提供 HTTP/HTTPS 层的路由能力,支持基于域名和路径的流量转发,是将集群内服务暴露到外部的标准方式。本文详解 Ingress Controller 选型、路由规则、pathType、TLS 配置、Annotations、Ingress Class、Gateway API 及常见问题排查。
一、为什么需要 Ingress?
使用 NodePort 或 LoadBalancer 时,每个 Service 需要独立的负载均衡器和公网 IP,导致成本高、无法基于路径路由、TLS 需分别配置。Ingress 通过统一入口解决上述问题。
有 Ingress
app-a.com
Ingress
app-b.com
Service-A
Service-B
无 Ingress
app-a.com
LB-1
app-b.com
LB-2
Service-A
Service-B
上图为无 Ingress 与有 Ingress 的架构对比。无 Ingress 时每个域名对应一个 LoadBalancer;有 Ingress 后多个域名共享同一入口,由 Ingress 根据规则分发。
1.1 无 Ingress 的局限
- 每个 Service 一个 LoadBalancer,对应一个公网 IP,云资源成本高
- 无法基于 URL 路径路由(如
/api、/admin) - TLS 证书需在每个 Service 分别配置
1.2 Ingress 的优势
- 统一入口,节省 LoadBalancer 成本
- 支持基于域名和路径的灵活路由
- 支持在入口层统一进行 TLS 终结
二、Ingress 架构
Ingress 定义 HTTP 路由规则,实际执行路由的是 Ingress Controller。流量经负载均衡器到达 Ingress Controller,由 Controller 按 Ingress 规则将请求转发到对应 Service 和 Pod。
互联网用户
Load Balancer
Ingress Controller
shop-svc
api-svc
admin-svc
Pod
Pod
Pod
Load Balancer 将流量转发到 Ingress Controller,Controller 根据 Ingress 规则(如 shop.example.com → shop-svc、api.example.com → api-svc)将请求路由到对应 Service。
重要概念 :Ingress 本身只是路由规则的定义 ,实际执行路由的是 Ingress Controller。使用 Ingress 前必须先安装并配置 Ingress Controller。
三、Ingress Controller 选型对比
| Controller | 特点 | 适用场景 |
|---|---|---|
| Nginx Ingress Controller | 使用广泛,功能全,Annotations 丰富 | 通用场景,需细粒度控制 |
| Traefik | 云原生设计,自动服务发现,配置简单 | 动态环境,快速部署 |
| HAProxy Ingress | 高性能,适合高流量 | 高并发、低延迟 |
| 云厂商 ALB / ELB | 与云平台集成,自动创建 LB | 云上生产环境 |
| Istio Gateway | 服务网格入口,功能多 | 已有服务网格 |
Ingress Controller 选型
Nginx Ingress
Traefik
HAProxy
云厂商 ALB
Nginx 和 Traefik 常用于通用场景;HAProxy 适合对性能要求高的场景;云上环境可考虑云厂商 ALB。
四、Ingress 规则配置
4.1 基于域名路由(host-based)
通过 host 字段将不同域名路由到不同 Service。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: shop-svc
port:
number: 80
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 8080
| 字段 | 说明 |
|---|---|
| spec.ingressClassName | 指定 Ingress Controller,K8s 1.18+ |
| spec.rules[].host | 匹配的域名 |
| spec.rules[].http.paths[].path | URL 路径 |
| spec.rules[].http.paths[].pathType | Prefix / Exact / ImplementationSpecific |
| backend.service | 转发的 Service 及端口 |
4.2 基于路径路由(path-based)
同一域名下,通过 path 将不同路径转发到不同 Service。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-based-ingress
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 8080
- path: /admin
pathType: Prefix
backend:
service:
name: admin-svc
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
/api 前缀到 api-svc,/admin 前缀到 admin-svc,根路径 / 到 frontend-svc。路径匹配顺序通常由 Ingress Controller 决定(多为最长前缀优先)。
4.3 pathType 区别
| pathType | 说明 |
|---|---|
| Prefix | 前缀匹配。/api 匹配 /api、/api/、/api/users |
| Exact | 精确匹配。/api 只匹配 /api,不匹配 /api/ |
| ImplementationSpecific | 由 Ingress Controller 自行实现 |
4.4 TLS 终止配置完整示例
在 Ingress 层配置 TLS 终结,可将 HTTPS 在入口处解密,内部使用 HTTP 访问后端。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-svc
port:
number: 80
| 字段 | 说明 |
|---|---|
| spec.tls[].hosts | 使用该证书的域名 |
| spec.tls[].secretName | 存放证书和私钥的 Secret 名称 |
创建 TLS Secret:
bash
kubectl create secret tls app-tls-secret \
--cert=tls.crt \
--key=tls.key
HTTPS
TLS 终结
用户
Ingress Controller
HTTP
Pod
五、Annotations 常用配置
Nginx Ingress Controller 支持通过 Annotations 扩展行为:
yaml
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/limit-rps: "10"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/enable-cors: "true"
六、Ingress Class 机制
K8s 1.18+ 通过 IngressClass 资源区分不同 Ingress Controller,替代已废弃的 kubernetes.io/ingress.class Annotation。
yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
Ingress 通过 spec.ingressClassName: nginx 指定使用该 IngressClass。集群可存在多个 Ingress Controller,通过 IngressClass 路由到不同 Controller。
七、Gateway API 简介
Gateway API 是 Kubernetes 社区推荐的下一代 Ingress 规范,提供更丰富的路由与角色分离能力。
| 对比项 | Ingress | Gateway API |
|---|---|---|
| 角色分离 | 无 | 支持集群管理员 / 应用开发者分离 |
| 高级路由 | 依赖 Annotations | 标准化 Header 匹配、流量分割 |
| 协议支持 | 主要为 HTTP/HTTPS | HTTP、gRPC、TCP、UDP |
Gateway API
标准化路由
角色分离
跨协议支持
Ingress
规则定义
高级功能依赖 Annotations
八、实践与部署
8.1 安装 Nginx Ingress Controller
bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
# 或使用 Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx
8.2 验证 Ingress 状态
bash
kubectl get ingress
kubectl describe ingress <ingress-name>
kubectl get pods -n ingress-nginx
8.3 完整部署示例
yaml
# 1. 部署后端应用
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deploy
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:alpine
ports:
- containerPort: 80
---
# 2. 创建 Service
apiVersion: v1
kind: Service
metadata:
name: app-svc
spec:
selector:
app: web
ports:
- port: 80
---
# 3. 创建 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-svc
port:
number: 80
8.4 常见问题排查表
| 问题 | 排查方向 |
|---|---|
| 404 或路由不到后端 | 确认 Ingress Controller 已安装;检查 ingressClassName;核对 Service 名称与端口 |
| TLS 证书错误 | 确认 Secret 类型为 kubernetes.io/tls;检查证书有效期 |
| 超时 | 调整 proxy-read-timeout、proxy-send-timeout |
| 502 Bad Gateway | 检查后端 Pod 是否就绪;检查 Service 的 endpoints |
九、生产环境建议
- Ingress Controller 高可用:多副本部署,配合 PodDisruptionBudget
- TLS 证书:使用 cert-manager 自动签发 Let's Encrypt 证书
- 限流与防护:通过 Annotations 或 WAF 配置限流、防 DDoS
- 监控:监控 Ingress Controller 的请求量、延迟、错误率
- 资源限制:为 Ingress Controller 设置合理的 resources requests/limits
十、FAQ
Q1:Ingress 404 排查思路?
确认 Ingress Controller 已安装;检查 ingressClassName 是否与集群 IngressClass 一致;核对 Service 名称、端口与 selector;确认后端 Pod 就绪;查看 Ingress Controller 日志。
Q2:多 Ingress Controller 共存如何配置?
为每个 Controller 创建 IngressClass;创建 Ingress 时指定对应的 ingressClassName;不同 Controller 可监听不同端口或通过 LB 区分。
Q3:如何配置 HTTPS 重定向?
Nginx Ingress 设置 nginx.ingress.kubernetes.io/ssl-redirect: "true";同时配置 TLS 的 hosts 与 secretName。
Q4:502 Bad Gateway 如何排查?
检查后端 Pod 是否就绪;检查 Service 的 endpoints;确认 Pod 端口与 Service 端口一致;查看 Ingress Controller 日志。
十一、总结
Ingress 负责定义 HTTP 层路由规则,Ingress Controller 负责实际执行路由。核心能力包括:基于域名的路由、基于路径的路由、TLS 终结。使用前需先安装并配置 Ingress Controller,高级功能可通过 Annotations 或 Gateway API 实现。
| 能力 | 说明 |
|---|---|
| 域名路由 | host 字段匹配 |
| 路径路由 | path + pathType |
| TLS | spec.tls 配置 |
| 扩展 | Annotations / Gateway API |
11.1 路由匹配优先级
多数 Ingress Controller 按以下优先级匹配:精确 host + 最长 path 优先。配置时注意将更具体的路径放在更通用的路径之前。
11.2 rewrite-target 使用示例
当后端应用期望的路径与外部路径不同时,可使用 rewrite-target:
yaml
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: app.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-svc
port:
number: 8080
/api/users 会被重写为 /users 转发到后端。
11.3 多 Ingress Controller 共存
同一集群可部署多个 Ingress Controller,通过 IngressClass 区分。创建 Ingress 时指定 ingressClassName 即可路由到对应 Controller。不同 Controller 可监听不同 NodePort 或通过不同 LoadBalancer 暴露。