Kubernetes Ingress 是什么?它如何实现外部访问集群内服务?
Kubernetes Ingress 是什么
当你把一个 Web 应用部署到 Kubernetes 集群后,集群外部的用户怎么访问它?最直接的方式是用 Service 的 NodePort 或 LoadBalancer 类型暴露端口,但前者端口范围有限且不安全,后者每个 Service 都要占用一个云厂商的负载均衡器,成本很高。
Ingress 就是解决这个问题的方案。它是一种 API 对象,在集群入口处统一管理 HTTP 和 HTTPS 路由规则,根据域名和路径把流量分发到不同的 Service。你可以把它理解成集群的"前台接待"——所有外部请求先到 Ingress,再由它根据规则转给对应的后端服务。
Ingress 能做的事情包括:
- 基于域名的路由:
api.example.com走 A 服务,web.example.com走 B 服务,共享同一个入口 IP - 基于路径的路由:
example.com/api走后端 API 服务,example.com/app走前端服务 - TLS 终止:在 Ingress 层处理 HTTPS 握手,后端 Service 只需跑 HTTP,证书管理集中化
- 路径重写:把
/v2/api重写为/api再转发给后端 - 负载均衡:在多个 Pod 副本之间分发请求
一个请求从到达到转发的完整链路
理解 Ingress 工作方式的关键是搞清楚请求的完整路径:
- 外部客户端发送请求到
https://api.example.com/users - DNS 将域名解析到 Ingress Controller 暴露的 IP(通常是一个 LoadBalancer Service)
- 请求到达 Ingress Controller,Controller 检查 TLS 证书完成 HTTPS 握手
- Controller 根据 Host 头和路径匹配 Ingress 规则,找到对应的 Service
- Controller 将请求转发给 Service 关联的某个 Pod(通过 Endpoints 列表)
- Pod 处理请求并返回响应
注意:Ingress 资源本身只是规则定义,真正干活的是 Ingress Controller。没有 Controller,Ingress 规则就是一纸空文。
Ingress Controller 选型
Ingress Controller 是 Ingress 功能的实际执行者,它监听集群中 Ingress 资源的变化,动态更新自己的配置(比如 NGINX 的 upstream 配置),然后按照规则转发流量。
NGINX Ingress Controller
社区使用最广泛的方案,基于 NGINX/OpenResty 实现。功能成熟、社区活跃、文档齐全,支持限流、认证、CORS、自定义错误页、灰度发布等高级特性。如果你没有特殊需求,选它基本不会出错。
Traefik
云原生设计,原生支持自动服务发现和 Let's Encrypt 自动证书申请,配置方式比 NGINX 更直观(支持文件和 CRD 两种 provider)。适合追求配置简洁和自动化的团队。
HAProxy Ingress
基于 HAProxy 实现,强项是高性能和丰富的负载均衡算法(加权轮询、最少连接、一致性哈希等)。对性能有极致要求时可以考虑。
Istio Gateway
服务网格方案中的入口网关,除了基本路由还支持 mTLS、流量镜像、故障注入、熔断等服务网格能力。如果集群已经用了 Istio,直接用它就够了,不需要再额外部署 Ingress Controller。
AWS ALB Ingress Controller
专为 AWS 设计,直接创建 ALB 资源作为入口,和 AWS 的 WAF、ACM 证书、CloudWatch 等服务深度集成。纯 AWS 环境下的首选。
Ingress 资源配置实战
最基本的路由规则
下面这个示例把 example.com/app1 和 example.com/app2 分别路由到两个不同的 Service:
yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: simple-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: example.com http: paths: - path: /app1 pathType: Prefix backend: service: name: app1-service port: number: 80 - path: /app2 pathType: Prefix backend: service: name: app2-service port: number: 80
pathType 是 v1 版本必须指定的字段,有三个可选值:
- Exact:精确匹配,只有路径完全一致才命中。
/app只匹配/app,不匹配/app/或/app1 - Prefix:前缀匹配,按
/分段进行前缀判断。/app能匹配/app、/app/、/app/user,但不匹配/app1 - ImplementationSpecific:由 Controller 自行决定匹配逻辑
配置 HTTPS(TLS 终止)
要启用 HTTPS,需要先在集群中创建 TLS 证书的 Secret,然后在 Ingress 中引用:
yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tls-ingress spec: tls: - hosts: - secure.example.com secretName: tls-secret rules: - host: secure.example.com http: paths: - path: / pathType: Prefix backend: service: name: secure-service port: number: 80
Ingress Controller 会在 443 端口处理 TLS 握手,解密后以 HTTP 转发给后端 Service,后端无需关心证书。
默认后端(Default Backend)
当请求没有匹配到任何规则时,Ingress Controller 会把流量发给默认后端。通常是一个返回 404 的简单服务:
yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: default-backend-ingress spec: defaultBackend: service: name: default-service port: number: 80 rules: - host: example.com http: paths: - path: /api pathType: Prefix backend: service: name: api-service port: number: 80
IngressClass:多 Controller 共存的关键
一个集群中可能部署了多个 Ingress Controller(比如 NGINX 处理外部流量,Traefik 处理内部流量)。IngressClass 用来指定一个 Ingress 资源由哪个 Controller 处理:
yamlapiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx-external annotations: ingressclass.kubernetes.io/is-default-class: "true" spec: controller: k8s.io/ingress-nginx --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: ingressClassName: nginx-external rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: my-service port: number: 80
标注 is-default-class: "true" 的 IngressClass 会被自动分配给没有指定 ingressClassName 的 Ingress 资源。
常用 Annotations 配置
Annotations 是 Ingress 的核心扩展机制,不同 Controller 支持不同的注解。以下是 NGINX Ingress Controller 最常用的几个:
路径重写:把匹配到的路径部分替换后再转发
yamlnginx.ingress.kubernetes.io/rewrite-target: /$2
强制 HTTPS 重定向:HTTP 请求自动跳转到 HTTPS
yamlnginx.ingress.kubernetes.io/ssl-redirect: "true"
限流配置:限制每个客户端的请求频率和并发连接数
yamlnginx.ingress.kubernetes.io/limit-rps: "10" nginx.ingress.kubernetes.io/limit-connections: "5"
CORS 跨域:前后端分离场景经常需要
yamlnginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
Basic 认证:简单的访问控制
yamlnginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-auth
自定义错误页面:统一展示 404、503 等错误页
yamlnginx.ingress.kubernetes.io/custom-http-errors: "404,503"
Ingress 和 Service、LoadBalancer 的区别
很多初学者容易混淆这三者的关系,这里做个明确对比。
Ingress vs Service:Service 是四层(L4)负载均衡,基于端口和 IP 转发 TCP/UDP 流量,不关心请求内容。Ingress 是七层(L7)负载均衡,能识别 HTTP 的 Host 头和 URL 路径,做更精细的路由。Service 是必须的(Ingress 最终还是把流量转给 Service),Ingress 是可选的增强。
Ingress vs LoadBalancer:LoadBalancer 类型的 Service 每个都占用一个云厂商负载均衡器,成本高且没有域名路由能力。Ingress 只需要一个 LoadBalancer(给 Ingress Controller 用),然后通过规则复用这个入口给多个 Service 使用。
| 维度 | Ingress | Service (ClusterIP/NodePort) | Service (LoadBalancer) |
|---|---|---|---|
| 层级 | L7 | L4 | L4 |
| 路由能力 | 域名 + 路径 | 端口 | 端口 |
| TLS 终止 | 支持 | 不支持 | 部分支持 |
| 成本 | 低(共享入口) | 低 | 高(每 Service 一个 LB) |
| 协议 | HTTP/HTTPS | TCP/UDP | TCP/UDP |
部署 NGINX Ingress Controller
用 Helm 安装是最快的方式:
bash# 添加 Helm 仓库 helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update # 安装到独立命名空间 helm install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx \ --create-namespace
安装完成后验证:
bashkubectl get pods -n ingress-nginx kubectl get svc -n ingress-nginx
如果看到 Service 有一个 EXTERNAL-IP(云环境)或 NodePort(本地环境),说明 Controller 已经就绪。
生产环境的最佳实践
命名空间隔离:把 Ingress Controller 部署在独立命名空间(如 ingress-nginx),和业务负载分开管理。
资源限制:Ingress Controller 是集群流量的咽喉,必须设置合理的 CPU 和内存 requests/limits,避免被其他 Pod 抢占资源。
监控告警:重点监控连接数、请求延迟、4xx/5xx 错误率、证书过期时间。Prometheus + Grafana 是主流方案。
证书管理:生产环境推荐用 cert-manager 自动签发和续期 Let's Encrypt 证书,避免手动管理证书过期。
健康检查:确保后端 Service 配置了正确的 readinessProbe,Ingress Controller 只会把流量发给就绪的 Pod。
配置备份与版本管理:Ingress 规则属于基础设施即代码的一部分,应该用 Git 管理 YAML 文件,而不是直接 kubectl edit。
灰度发布:利用 nginx.ingress.kubernetes.io/canary 系列注解实现金丝雀发布,按权重或 Header 把部分流量导向新版本。
常见故障排查
排查 Ingress 问题有一个清晰的思路:从外到内,逐层验证。
第一层:Ingress 规则是否正确
bashkubectl get ingress kubectl describe ingress <ingress-name>
检查 Rules 中的 Host、Path、Backend 是否符合预期,特别注意 pathType 是否匹配。
第二层:Controller 是否正常工作
bashkubectl logs -n ingress-nginx <pod-name> --tail=100
看日志中是否有配置加载错误或后端连接失败的记录。
第三层:DNS 是否解析正确
bashnslookup example.com dig example.com
确认域名指向 Ingress Controller 的外部 IP。
第四层:后端 Service 和 Pod 是否健康
bashkubectl get svc kubectl get endpoints <service-name> kubectl get pods -l app=<your-app>
Endpoints 列表为空说明没有 Pod 通过了 readinessProbe,流量无处可去。
第五层:TLS 证书是否有效
bashkubectl get secret tls-secret -o yaml openssl x509 -in <cert-file> -text -noout
检查证书是否过期、域名是否匹配、Secret 是否在正确的命名空间。
按照这个顺序逐层排查,绝大多数 Ingress 问题都能定位到原因。