① 背景与问题(解决了什么痛点)

在 Kubernetes 生态中,Ingress-NGINX 是最广泛使用的 Ingress 控制器之一。它为集群提供了基于 HTTP 的路由能力,使得外部流量能够被正确地转发到相应的服务上。然而,在 2025 年 11 月的公告中,Kubernetes 宣布将在 2026 年 3 月正式退役 Ingress-NGINX,这意味着开发者和运维人员需要尽快规划迁移方案。

尽管 Ingress-NGINX 已经非常成熟,但其背后仍存在一些容易被忽视的行为特征,这些行为可能在实际部署中导致性能瓶颈、配置错误或安全漏洞。如果你正在考虑迁移到其他 Ingress 控制器(如 NGINX Ingress Controller、Traefik 或 Envoy),那么了解这些行为将帮助你更顺利地完成迁移,并避免在新环境中重蹈覆辙。

本文将从实战角度出发,深入分析 Ingress-NGINX 的五个“令人意外”的行为,并结合真实案例展示如何应对这些问题,最终提供一套完整的迁移建议和替代方案。


② 核心概念/技术原理

Ingress-NGINX 简介

Ingress-NGINX 是一个基于 NGINX 的 Kubernetes Ingress 控制器,它通过监听 Kubernetes 的 Ingress API 来动态更新 NGINX 配置,从而实现对外部请求的路由控制。

其核心组件包括:

  • Controller Pod:运行 NGINX 的容器,负责根据 Ingress 资源生成配置。
  • ConfigMap:用于存储 NGINX 的全局配置。
  • Ingress Resource:定义了外部访问规则,如路径、主机名、后端服务等。
  • Service:指向后端 Pod 的负载均衡器。

基本工作流程

  1. 用户创建 Ingress 资源,定义路由规则。
  2. Ingress-NGINX Controller 监听该资源变化。
  3. Controller 生成对应的 NGINX 配置文件。
  4. NGINX 重新加载配置,使新的路由规则生效。

虽然这个流程看似简单,但在实际使用中,由于某些隐藏行为的存在,可能导致配置不一致、性能下降或安全风险。


③ 实战案例/代码示例

案例一:Ingress 路由冲突处理

场景描述

假设你有如下两个 Ingress 资源:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-a
spec:
  rules:
  - http:
      paths:
      - path: /app-a
        pathType: Prefix
        backend:
          service:
            name: app-a-service
            port:
              number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-b
spec:
  rules:
  - http:
      paths:
      - path: /app-b
        pathType: Prefix
        backend:
          service:
            name: app-b-service
            port:
              number: 80

此时,如果用户访问 /app-a/app-b,理论上应该分别路由到 app-a-serviceapp-b-service。但在某些情况下,可能会出现路径冲突,导致请求被错误地路由。

问题分析

Ingress-NGINX 在处理多个 Ingress 资源时,会按照某种顺序进行合并,这可能导致某些路径被覆盖或优先级错误。

解决方案

为了避免这种问题,可以使用 nginx.ingress.kubernetes.io/canonical-host 注解来指定域名,或者在每个 Ingress 中明确设置 host 字段,以确保路径不会被混淆。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-a
  annotations:
    nginx.ingress.kubernetes.io/canonical-host: "example.com"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /app-a
        pathType: Prefix
        backend:
          service:
            name: app-a-service
            port:
              number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-b
  annotations:
    nginx.ingress.kubernetes.io/canonical-host: "example.com"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /app-b
        pathType: Prefix
        backend:
          service:
            name: app-b-service
            port:
              number: 80

注意:canonical-host 可以用来强制统一域名,防止不同 Ingress 资源之间的路径冲突。


案例二:TLS 证书未正确加载

场景描述

你为某个 Ingress 资源配置了 TLS 证书,但访问 HTTPS 时仍然报错。

配置示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-app
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - example.com
    secretName: example-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-app
            port:
              number: 443
问题分析

在某些版本的 Ingress-NGINX 中,secretName 必须是 Kubernetes Secret 中的名称,且必须包含 tls.crttls.key 文件。如果 Secret 不完整或命名不正确,TLS 证书将无法被正确加载。

此外,如果 Ingress 的 backend 使用的是非 HTTPS 端口(例如 80),而 TLS 被启用,则可能会触发 301 重定向,导致客户端连接失败。

解决方案
  • 确保 Secret 名称正确,并包含完整的证书和私钥。
  • 如果使用 HTTPS 后端服务,确保 backend.port.number 是 443。
  • 可以通过 kubectl describe ingress secure-app 查看事件信息,确认证书是否被正确加载。

案例三:Ingress 控制器日志缺失

场景描述

你发现 Ingress-NGINX 控制器的日志没有输出任何错误信息,但流量无法正常到达后端服务。

日志检查
kubectl logs -n ingress-nginx ingress-nginx-controller-xxxxx
问题分析

Ingress-NGINX 默认的日志级别较低,只有当发生错误时才会输出详细信息。对于调试目的,需要手动调整日志级别。

解决方案

修改 ConfigMap 中的 log-level 设置为 debug

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration
data:
  log-level: "debug"

然后重启控制器 Pod:

kubectl delete pod -n ingress-nginx -l app=ingress-nginx

重启后,你可以看到更详细的日志,包括请求路径、代理状态、证书加载情况等。


案例四:Ingress 路由延迟高

场景描述

你在测试环境中发现,通过 Ingress 访问服务的响应时间比直接访问 Service 高很多。

性能对比
方法 响应时间
直接访问 Service 50ms
通过 Ingress 访问 200ms
问题分析

Ingress-NGINX 在处理请求时,会增加额外的网络跳转和配置解析开销。如果 Ingress 资源过多或配置复杂,可能会显著影响性能。

解决方案
  • 减少不必要的 Ingress 资源,合并相同 Host 的路由规则。
  • 使用 nginx.ingress.kubernetes.io/proxy-read-timeoutproxy-send-timeout 调整超时参数,优化请求处理效率。
  • 考虑使用更轻量级的 Ingress 控制器(如 Traefik)进行性能测试。

案例五:Ingress 配置未及时生效

场景描述

你更新了 Ingress 资源,但访问仍然返回旧内容。

问题分析

Ingress-NGINX 的配置更新不是立即生效的,而是需要等待一段时间(通常几秒)才能重新加载 NGINX 配置。如果在这段时间内有请求进入,可能会使用旧配置。

解决方案
  • 在更新 Ingress 后,可以手动触发 NGINX 重新加载:

    kubectl exec -n ingress-nginx -it ingress-nginx-controller-xxxxx -- nginx -s reload
    
  • 也可以在 ConfigMap 中设置 reload-timeout 参数,调整重新加载的时间限制。

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration
data:
  reload-timeout: "60"

④ 架构设计/方案对比

Ingress-NGINX 的架构图

Client Request

Ingress-NGINX Controller

NGINX Configuration

NGINX Process

Backend Services

Response

其他 Ingress 控制器对比

控制器 优点 缺点 适用场景
NGINX Ingress Controller 功能强大,支持高级特性(如 WebSocket、SSL、Rewrite) 配置较复杂,资源占用较高 复杂企业级应用
Traefik 自动发现服务,配置简洁 社区支持不如 NGINX 微服务架构、DevOps 环境
Envoy 高性能,支持 gRPC、mTLS 配置复杂,学习曲线陡峭 高性能、高安全性需求
HAProxy 稳定、成熟 功能有限,社区活跃度低 简单场景、传统架构

⑤ 优劣势评估/选型建议

Ingress-NGINX 的优势

  • 功能丰富:支持多种高级特性,如重写、限流、SSL 终止等。
  • 社区活跃:拥有庞大的用户群和丰富的文档资源。
  • 兼容性好:与 Kubernetes API 无缝集成,易于管理。

Ingress-NGINX 的劣势

  • 配置复杂:需要较多注解和 ConfigMap 配置,对新手不够友好。
  • 性能瓶颈:在大规模并发场景下,可能存在性能瓶颈。
  • 维护成本高:随着 Kubernetes 版本升级,需持续关注兼容性问题。

迁移建议

  1. 评估现有配置:梳理所有 Ingress 资源,识别依赖的注解和配置。
  2. 选择替代控制器:根据业务需求选择合适的 Ingress 控制器(如 Traefik、Envoy)。
  3. 逐步迁移:先在测试环境中验证新控制器的功能和性能。
  4. 监控与回滚:在生产环境中实施前,确保有完善的监控和回滚机制。

⑥ 总结与延伸

Ingress-NGINX 虽然即将被官方淘汰,但它在过去几年中为 Kubernetes 生态做出了巨大贡献。然而,它的某些行为可能在实际部署中带来意想不到的问题,如路由冲突、TLS 加载失败、配置延迟等。了解这些行为并提前做好准备,是成功迁移的关键。

在未来的 Kubernetes 生态中,更多的 Ingress 控制器将被引入,开发者可以根据自身需求选择更适合的方案。无论是继续使用 NGINX Ingress Controller,还是转向 Traefik 或 Envoy,都需要对它们的特性和行为有深入的理解。

推荐阅读

如果你正在计划迁移,不妨现在就开始探索新的 Ingress 控制器,为未来做好准备。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐