Kubernetes 将服务暴露给外部访问时,NodePort 方式需要为每个 Service 分配独立端口,LoadBalancer 又依赖云厂商且成本较高,而 Ingress 提供了统一的七层入口和基于域名、路径的流量分发能力。不过,Ingress 资源本身只是一组路由规则,真正解析并执行这些规则的是 Ingress 控制器。在众多实现中,基于 Nginx 的 ingress-nginx 控制器使用广泛、配置灵活,适合作为集群入口的首选方案。本文围绕它的部署与配置展开,帮助读者快速构建一个可用的 Kubernetes Ingress。

一、Ingress 与 Nginx 控制器的协作原理
Kubernetes 中的 Ingress 资源定义了从集群外部访问内部 Service 的一组 HTTP 或 HTTPS 路由规则,例如将访问 api.ippipp.com 的请求转发到后端 api 服务,将 shop.ippipp.com 的请求转发到 shop 服务。这些规则不会直接被 kube-proxy 或 kubelet 处理,而是由 Ingress 控制器读取。控制器通常以 Pod 形式部署在集群中,通过 watch 机制监听 Ingress、Service、Endpoints 等资源的变化。
ingress-nginx 控制器内部运行着一个定制化的 Nginx 进程。当用户创建或修改 Ingress 对象时,控制器会从 API Server 获取最新的规则,生成对应的 nginx.conf 配置文件,然后执行 Nginx 的平滑重载,使新配置生效。这个过程的延迟通常很短,但对频繁变更的大规模集群来说,重载频率是需要关注的性能点。控制器还会根据 Service 对应的 Endpoints 动态更新 upstream 服务器列表,从而避免请求被转发到已经终止的 Pod。
从数据流角度看,外部请求首先到达控制器所在的节点或负载均衡器,Nginx 根据请求的 Host 头和 URL 路径匹配 Ingress 规则,选择对应的后端 Service,再通过 Service 的 ClusterIP 或直接通过 Pod IP 进行转发。默认情况下,ingress-nginx 会使用 Service 的 ClusterIP 作为代理目标,但部分配置下也会直接连接 Pod,以绕过 kube-proxy 的额外转发。
二、安装与部署 ingress-nginx 控制器
部署 ingress-nginx 有多种方式,最直接的是使用官方维护的 YAML 清单,一条命令即可完成安装。对于需要自定义镜像仓库、副本数、资源限制或启用监控等场景,推荐使用 Helm Chart。以下示例采用 Helm 方式,因为它便于后续升级和参数管理。
首先添加 ingress-nginx 的 Helm 仓库并更新索引,然后创建一个独立的命名空间,最后安装控制器。执行命令如下:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update kubectl create namespace ingress-nginx helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx
安装完成后,可以查看控制器 Pod 是否正常运行:
kubectl get pods -n ingress-nginx kubectl get svc -n ingress-nginx
在云环境中,Service 通常会自动获得一个 LoadBalancer 类型的公网或内网地址。在裸金属或本地集群中,可以使用 NodePort 方式或通过 MetalLB 提供负载均衡地址。对于 NodePort 方式,控制器 Service 会暴露一个高位端口,访问时需要使用该端口,生产环境一般会在前面再挂一层硬件或软件负载均衡器。如果使用 kubectl apply 方式安装,可以执行官方仓库中的 deploy.yaml 文件,但需要留意版本与 Kubernetes 集群的兼容性。
三、编写 Ingress 资源实现路由转发
部署好控制器后,就可以创建 Ingress 资源来定义转发规则。假设集群中已经有两个服务:一个名为 web-service,负责前端页面;另一个名为 api-service,负责 REST 接口。我们希望将 ippipp.com 的根路径 / 转发到 web-service,将 /api 路径转发到 api-service。对应的 YAML 如下:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: default
spec:
ingressClassName: nginx
rules:
- host: ippipp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
这里的 ingressClassName 字段很重要,它指定由哪个 Ingress 控制器处理该资源。在较新的 Kubernetes 版本中,如果集群中存在多个控制器,必须通过该字段显式声明。pathType 控制路径匹配方式,Prefix 表示前缀匹配,例如 /api 会匹配 /api、/api/v1、/api/v1/users 等路径;Exact 表示精确匹配;ImplementationSpecific 则由具体控制器决定匹配逻辑,通常不推荐在跨控制器场景中使用。
创建该 Ingress 后,可以通过 kubectl describe ingress 查看规则是否被正确解析,也可以通过访问 ippipp.com/api/v1/health 验证请求是否到达 api-service。如果后端 Service 的端口是命名端口,在 YAML 中也可以使用 port.name 字段替代数字端口,但需要确保 Service 定义中存在对应名称。
四、进阶配置:TLS、路径重写与常用注解
生产环境通常需要启用 HTTPS,Kubernetes 通过 Secret 保存 TLS 证书和私钥,然后在 Ingress 的 tls 字段中引用。先使用 kubectl create secret tls 命令创建 Secret,再修改 Ingress 配置。示例:
kubectl create secret tls example-tls --cert=server.crt --key=server.key -n default
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: default
spec:
ingressClassName: nginx
tls:
- hosts:
- ippipp.com
secretName: example-tls
rules:
- host: ippipp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
路径重写是另一个常见需求。例如后端服务期望的路径不包含 /api 前缀,而我们对外暴露为 /api。可以通过注解 nginx.ingress.kubernetes.io/rewrite-target 实现。以下配置会把 /api/users 重写为 /users 后再转发给后端:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: ippipp.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 8080
这里使用了正则捕获组,/api(/|$)(.*) 会匹配以 /api 开头的路径,并将 /api 之后的部分作为第二个捕获组,重写目标 /$2 表示只保留后面的路径。需要注意 pathType 必须设为 ImplementationSpecific,因为正则匹配不属于 Prefix 或 Exact。除了重写,ingress-nginx 还支持大量注解,例如 nginx.ingress.kubernetes.io/ssl-redirect 控制 HTTP 跳转 HTTPS,nginx.ingress.kubernetes.io/proxy-body-size 设置上传文件大小限制,nginx.ingress.kubernetes.io/cors-enable 开启跨域支持等。使用注解时,建议查阅对应版本的 ingress-nginx 文档,避免因版本差异导致注解无效。
五、常见问题与排障思路
Ingress 配置不生效时,首先应确认控制器是否正常运行。使用 kubectl get pods -n ingress-nginx 查看 Pod 状态,如果 Pod 未就绪或反复重启,可以通过 kubectl logs -n ingress-nginx deployment/ingress-nginx-controller 查看日志。常见原因包括镜像拉取失败、资源不足或与 API Server 的连接异常。
其次,检查 Ingress 对象是否被控制器正确加载。执行 kubectl describe ingress app-ingress,如果 Address 字段为空,可能说明控制器没有成功分配入口地址,或者 Service 类型不支持 LoadBalancer。此时应查看 Service 的状态,确认 external-ip 或 NodePort 是否正常分配。同时确认 Ingress 中指定的 ingressClassName 与实际部署的控制器名称一致,否则规则会被忽略。
请求返回 503 或 502 通常表示后端服务不可达。需要检查后端 Service 是否存在、端口是否正确,以及对应的 Endpoints 是否有就绪的 Pod。使用 kubectl get endpoints 查看地址列表,如果为空,说明 Service 的选择器没有匹配到任何 Pod,或者 Pod 就绪探针未通过。TLS 相关错误则要检查 Secret 是否存在于同一命名空间,证书和私钥是否匹配,以及域名是否与证书的 CN 或 SAN 一致。通过以上步骤,大多数 Ingress 问题都能定位到具体原因并进行修复。
Kubernetes IngressNginx 控制器Ingress 配置修改时间:2026-08-26 14:44:25