当集群里只有一个服务时,使用 NodePort 暴露端口似乎很直接;但服务数量增加后,端口管理、域名路由、TLS 证书和统一访问策略都会变得复杂。Ingress 的价值,就是把 HTTP 和 HTTPS 的入口规则声明成 Kubernetes 资源。
一、NodePort、Service 与 Ingress 的区别
NodePort 会在节点上开放一个端口,把流量转发到对应的 Service。它适合测试或某些基础设施场景,但大量服务各占一个端口,不便于使用标准的 80/443 端口,也不擅长按域名和 URL 路径分流。
Service 负责为一组 Pod 提供稳定的访问入口与服务发现,并由集群网络实现流量转发。原笔记中“Service 没有转发作用”的说法不准确;更准确地说,Service 主要解决四层的稳定寻址和负载分发,而 Ingress 解决 HTTP/HTTPS 七层路由。
Ingress 可以根据 Host、Path 等请求信息,将流量转发给不同 Service。它通常还可以配合控制器完成 TLS 终止、重定向和虚拟主机等功能。
二、Ingress 资源不等于 Ingress Controller
只创建 Ingress YAML 并不会自动产生流量入口。集群中必须运行一个 Ingress Controller,它持续观察 Ingress 资源,并把规则转换成实际的代理或负载均衡配置。
常见实现基于 NGINX、Traefik、HAProxy、Envoy、Cilium 或云厂商负载均衡服务。不同控制器支持的注解和扩展能力并不完全相同,因此安装和高级配置必须查看所选控制器的官方文档。
三、一个带域名和 TLS 的 Ingress 示例
假设集群中已经存在名为 blog-service 的 Service,并监听 80 端口:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: blog
namespace: default
spec:
ingressClassName: nginx
tls:
- hosts:
- blog.example.com
secretName: blog-tls
rules:
- host: blog.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: blog-service
port:
number: 80
这里有四个关键点:
1. apiVersion 使用 networking.k8s.io/v1。
2. ingressClassName 指定由哪个 Ingress Controller 处理。
3. backend 指向 Service,而不是直接指向 Pod。
4. TLS Secret 与 Ingress 必须位于同一个命名空间。
四、理解 pathType
Exact:请求路径必须精确匹配。
Prefix:按路径前缀匹配,并按路径段处理,最常用于 /api、/admin 等路由。
ImplementationSpecific:匹配行为由控制器决定,可移植性较差。除非明确依赖某个控制器的行为,否则优先使用 Exact 或 Prefix。
如果多个规则都能匹配,具体优先级还要结合 Kubernetes 规范和控制器实现验证。上线前应测试真实 URL,不能只看 YAML 是否创建成功。
五、从公网请求到 Pod 的链路
一次典型访问会经过:
用户请求 → DNS 解析 → 外部负载均衡或节点入口 → Ingress Controller → Service → Pod
因此,Ingress 显示正常不代表整条链路一定正常。DNS、云安全组、防火墙、负载均衡健康检查、Service 选择器和 Pod 就绪状态中的任何一环都可能导致访问失败。
六、TLS 的注意事项
Ingress 的 tls 配置只声明证书 Secret 和域名。证书可以手工创建,也可以使用证书自动化工具管理。
不要把私钥写进公开 YAML 或代码仓库。还应确认:
1. 证书包含正确的域名。
2. Secret 类型和证书内容正确。
3. Ingress Controller 能读取该命名空间的 Secret。
4. HTTP 到 HTTPS 的跳转通常属于控制器配置,不能假设所有实现行为一致。
七、常用排查步骤
先确认控制器和 IngressClass:
kubectl get ingressclass
kubectl get pods -A | grep -i ingress
再检查 Ingress、Service 和后端 Pod:
kubectl get ingress -A
kubectl describe ingress blog
kubectl get service blog-service
kubectl get endpointslice -l kubernetes.io/service-name=blog-service
kubectl get pod -o wide
如果 DNS 还没配置,可以临时指定 Host 头测试:
curl -H 'Host: blog.example.com' http://<INGRESS_ADDRESS>/
常见故障包括:控制器未安装、ingressClassName 不匹配、Service 名称或端口错误、Service 没有 EndpointSlice、Pod 探针失败、DNS 未指向入口地址,以及证书 Secret 不存在。
八、Ingress 与 Gateway API
Ingress API 已经稳定,但功能集合已经冻结;Kubernetes 项目目前建议新需求评估 Gateway API。Gateway API 将基础设施入口、监听器和应用路由拆分成更清晰的角色,适合多团队和更复杂的流量治理。
这不代表现有 Ingress 会被移除。已有系统可以继续使用 Ingress;新项目如果需要跨命名空间授权、更多协议或更细致的角色分工,可以比较控制器对 Gateway API 的支持情况后再选择。
总结
Ingress 不是一个独立代理,而是一套七层路由声明;真正处理流量的是 Ingress Controller。排查时不要只盯着 Ingress YAML,而要沿着 DNS、入口地址、控制器、Service、EndpointSlice 和 Pod 的完整链路逐层验证。
参考资料:
https://kubernetes.io/docs/concepts/services-networking/ingress/
https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/