1. Ingress 控制器与 Ingress 资源的关系解析
在 Kubernetes 集群中,Ingress 控制器和 Ingress 资源是两个紧密关联但又职责分明的概念。简单来说,Ingress 资源定义了路由规则,而 Ingress 控制器则是这些规则的实际执行者。这种设计实现了关注点分离 - 开发人员只需关心如何声明路由规则,而不必了解底层实现细节。
1.1 Ingress 资源的核心作用
Ingress 资源是一个 API 对象,它通过 YAML 文件定义了一组规则,用于管理外部访问集群内部服务的 HTTP/HTTPS 路由。这些规则主要包括:
- 主机名匹配规则(如 foo.example.com)
- 路径匹配规则(如 /api/v1)
- 后端服务关联(将特定流量路由到哪个 Service)
- TLS 证书配置
一个典型的 Ingress 资源示例如下:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
ingressClassName: nginx
rules:
- host: "foo.example.com"
http:
paths:
- pathType: Prefix
path: "/api"
backend:
service:
name: api-service
port:
number: 80
1.2 Ingress 控制器的核心职责
Ingress 控制器是实际处理 Ingress 规则的程序,它通常以 Pod 形式运行在集群中。主要职责包括:
- 监听 Ingress 资源变更:当创建或修改 Ingress 资源时,控制器会实时获取这些变更
- 配置负载均衡器:根据规则配置底层负载均衡器(如 Nginx、AWS ALB 等)
- 处理 TLS 终止:管理证书并在负载均衡器层面处理 HTTPS 解密
- 流量路由:将请求按照规则路由到对应的后端服务
常见的 Ingress 控制器实现包括:
- Nginx Ingress Controller
- AWS ALB Ingress Controller
- Traefik
- HAProxy Ingress Controller
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. IngressClass:连接控制器与资源的桥梁
Kubernetes 1.18 引入了 IngressClass 资源,它明确建立了 Ingress 控制器与 Ingress 资源之间的关联关系。这种设计解决了早期版本中通过注解(如 kubernetes.io/ingress.class)指定控制器的模糊性问题。
2.1 IngressClass 的核心配置
一个典型的 IngressClass 定义如下:
yaml复制apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
关键字段说明:
controller:标识负责此类的控制器,格式通常为域名/控制器名称parameters:可选的额外配置,可以引用集群范围或命名空间范围的资源
2.2 默认 IngressClass 的实践意义
将某个 IngressClass 标记为默认(通过注解 ingressclass.kubernetes.io/is-default-class: "true")可以带来以下好处:
- 简化部署:开发人员创建 Ingress 时无需显式指定
ingressClassName - 统一标准:确保集群中使用统一的默认 Ingress 控制器
- 向后兼容:平滑过渡旧版未指定控制器的 Ingress 资源
重要提示:一个集群中应该只有一个默认 IngressClass。如果存在多个,Kubernetes 将阻止创建未指定 ingressClassName 的新 Ingress 资源。
3. 控制器与资源的最佳对应实践
3.1 多控制器场景下的明确关联
在生产环境中,我们可能会部署多个 Ingress 控制器来处理不同类型的流量。例如:
- 外部流量控制器:处理来自互联网的流量,可能使用 Nginx 或云厂商提供的解决方案
- 内部流量控制器:处理集群内部服务间的通信,可能使用 Traefik
在这种情况下,明确的关联关系尤为重要。最佳实践包括:
-
为每个控制器创建独立的 IngressClass:
yaml复制# 外部流量控制器 apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: external-nginx spec: controller: k8s.io/ingress-nginx # 内部流量控制器 apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: internal-traefik spec: controller: traefik.io/ingress-controller -
在 Ingress 资源中明确指定 ingressClassName:
yaml复制apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: external-api-ingress spec: ingressClassName: external-nginx rules: - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: api-service port: number: 80
3.2 控制器特定注解的合理使用
虽然 IngressClass 提供了标准化的关联方式,但许多控制器仍然支持使用注解进行特定配置。例如,Nginx Ingress 控制器支持以下常见注解:
yaml复制metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
经验分享:注解虽然方便,但会导致 Ingress 资源与特定控制器耦合。建议优先使用 IngressClass 的 parameters 字段进行配置,仅在必要时使用控制器特定注解。
4. 典型问题排查与解决方案
4.1 控制器未正确处理 Ingress 资源
症状:创建了 Ingress 资源,但访问时未按预期路由。
排查步骤:
-
确认 Ingress 控制器的 Pod 正在运行:
bash复制
kubectl get pods -n ingress-nginx -
检查控制器日志是否有错误:
bash复制
kubectl logs -n ingress-nginx <ingress-controller-pod> -
验证 Ingress 资源是否被控制器正确识别:
bash复制
kubectl describe ingress <ingress-name>查看
Events部分是否有警告或错误信息 -
检查 IngressClass 是否正确指定:
bash复制
kubectl get ingressclass kubectl describe ingress <ingress-name> | grep Class
常见原因:
- 未指定 ingressClassName 且集群中没有默认 IngressClass
- IngressClass 的 controller 字段与运行的控制器不匹配
- 控制器没有足够的权限读取 Ingress 资源(检查 RBAC 配置)
4.2 TLS 证书配置问题
症状:HTTPS 访问失败或浏览器提示证书不安全。
排查步骤:
-
确认 Secret 包含有效的 TLS 证书和私钥:
bash复制
kubectl get secret <tls-secret-name> -o yaml检查
tls.crt和tls.key是否存在且有效 -
验证 Ingress 中是否正确引用了 Secret:
yaml复制tls: - hosts: - example.com secretName: example-tls -
检查控制器是否支持 SNI(如果配置了多个 TLS 主机)
最佳实践:
- 使用 cert-manager 自动管理证书
- 确保证书的 CN 或 SAN 包含所有需要的主机名
- 定期检查证书有效期并设置自动续期
5. 高级配置与优化建议
5.1 多路径路由配置
Ingress 支持基于路径的复杂路由规则,以下是一个多路径配置示例:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: complex-ingress
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /static
pathType: Exact
backend:
service:
name: static-service
port:
number: 8000
路径匹配类型说明:
Prefix:匹配以指定路径开头的请求(如/api匹配/api/v1/users)Exact:精确匹配路径(只匹配完全相同的路径)ImplementationSpecific:匹配方式由控制器决定
5.2 跨可用区高可用部署
对于生产环境,Ingress 控制器的高可用性至关重要。以下是常见的高可用方案:
-
多副本部署:
yaml复制# 在控制器 Deployment 中配置 replicas: 3 strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 -
Pod 反亲和性:
yaml复制affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - ingress-nginx topologyKey: kubernetes.io/hostname -
多可用区支持(云环境):
- 使用
topologySpreadConstraints确保 Pod 均匀分布在多个可用区 - 配置云厂商的负载均衡器为跨区部署
- 使用
5.3 性能优化技巧
-
启用 HTTP/2:
yaml复制metadata: annotations: nginx.ingress.kubernetes.io/http2: "true" -
调整缓冲区大小:
yaml复制metadata: annotations: nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" nginx.ingress.kubernetes.io/proxy-buffers-number: "4" -
连接保持优化:
yaml复制metadata: annotations: nginx.ingress.kubernetes.io/upstream-keepalive-connections: "100" nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "60" nginx.ingress.kubernetes.io/upstream-keepalive-requests: "1000" -
启用 Brotli 压缩:
yaml复制metadata: annotations: nginx.ingress.kubernetes.io/brotli: "on" nginx.ingress.kubernetes.io/brotli-level: "6" nginx.ingress.kubernetes.io/brotli-types: "text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript"
6. 未来演进与替代方案
虽然 Ingress 是目前 Kubernetes 中管理外部访问的标准方式,但社区正在开发更强大的替代方案 - Gateway API。Gateway API 提供了更丰富的功能,包括:
- 更细粒度的路由控制
- 跨命名空间的路由支持
- 更好的策略分离(基础设施与业务规则)
- 更丰富的匹配条件(如 header、query 参数等)
对于新项目,建议评估 Gateway API 的适用性。现有项目可以继续使用 Ingress,因为 Kubernetes 已承诺长期维护 Ingress API 的稳定性。
