Ingress 七层路由
本教程共 65 篇 · 第 28 篇 · 更新于 2026-08-14 · 约 15 分钟阅读
本节目标:掌握用 Ingress 做 HTTP/HTTPS 七层路由。看懂路径匹配、基于名称的虚拟主机、TLS 终止,以及 IngressClass 和 Ingress 控制器的关系。所有示例对齐
networking.k8s.io/v1。
Service 解决了集群内部的访问。可流量从哪进集群?NodePort 和 LoadBalancer 只能做四层(IP+端口)转发,看不到 URL 路径和域名。想按 /api、/web 把请求分给不同服务,得靠七层路由——这就是 Ingress(入口)。
Warning全程用
networking.k8s.io/v1。老的extensions/v1beta1早已废弃,别在新配置里出现。当前 Ingress API 已被冻结,但仍是 GA、稳定可用,官方建议新项目优先考虑 Gateway API。
28-1 Ingress 是什么
Ingress 把集群外的 HTTP 和 HTTPS 流量,按你定义的规则映射到集群内的 Service。它理解 URI、主机名、路径这些 Web 概念,能做:
- 给服务分配外部可访问的 URL。
- 对流量做负载均衡。
- 终止 TLS(也就是 HTTPS 卸载)。
- 基于名称的虚拟主机(一个 IP 托管多个域名)。
要注意:Ingress 只管 HTTP/HTTPS。想暴露别的协议,还是得回到 NodePort 或 LoadBalancer。
28-2 光写 Ingress 没用,得有控制器
这是新手最常见的误解:我创建了 Ingress,为什么没生效?
因为 Ingress 只是”规则声明”,真正干活的是 Ingress 控制器。常见的实现有 NGINX Ingress Controller、Traefik、HAProxy 等。它们读取 Ingress 规则,然后去配置背后的负载均衡器或代理。
Note只创建 Ingress 资源,集群里没有对应的 Ingress 控制器,等于写了张纸条却没人执行。部署集群时得先把控制器装上。
28-3 一个最小的 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
spec:
ingressClassName: nginx
defaultBackend:
service:
name: my-service
port:
number: 80
它把什么都没收到的流量,兜底转给 my-service。这里 ingressClassName: nginx 指明用哪个控制器实现。
如果省略 ingressClassName,集群里得有一个被标记为”默认”的 IngressClass,否则新建会出问题。
28-4 规则由 host、path、backend 组成
每条 HTTP 规则包含三样东西:
- 可选的
host:不写就匹配所有域名;写了就只对该主机名生效。 - 路径列表
paths:每个路径指向一个后端 Service(通过service.name和service.port)。 backend:即”Service + 端口”的组合,流量最终转去哪。
路径必须声明 pathType,有三种:
Exact:精确匹配,区分大小写。Prefix:按/分段的前缀匹配,区分大小写。ImplementationSpecific:匹配逻辑交给具体的 IngressClass 决定。
TipPrefix 匹配是按路径元素逐段匹配的。比如
/foo/bar能匹配/foo/bar/baz,但匹配不了/foo/barbaz。写路径时这个斜杠陷阱要留心。
28-5 扇出:一个 IP 分流到多个服务
扇出(fanout)是 Ingress 的经典用法:同一个 IP 进来,按路径分给不同 Service,省下一堆负载均衡器。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
访问 foo.bar.com/foo 进 service1,访问 foo.bar.com/bar 进 service2。一条规则,两个后端,清晰。
28-6 基于名称的虚拟主机
一个 IP 想同时托管 first.bar.com 和 second.bar.com?靠 host 字段区分即可:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host
spec:
ingressClassName: nginx
rules:
- host: first.bar.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service2
port:
number: 80
主机名还支持通配符,比如 *.foo.com 能匹配 bar.foo.com,但只覆盖一个 DNS 标签,匹配不了 baz.bar.foo.com。
28-7 配置 TLS 终止
想让 Ingress 支持 HTTPS,先准备一个包含证书和私钥的 Secret:
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64编码的证书
tls.key: base64编码的私钥
type: kubernetes.io/tls
然后在 Ingress 里引用它:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example
spec:
ingressClassName: nginx
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
Ingress 只支持 443 这一个 TLS 端口,且 TLS 在入口处终止——到后端 Service 和 Pod 的流量是明文的。证书里的 CN(全限定域名)得和 hosts 对上。
Warning
tls里的hosts必须和rules里的host精确匹配。默认规则(不写 host)配不了 TLS,因为那得给所有可能的子域名都发证。
28-8 IngressClass 是什么
Ingress 可以由不同控制器实现,配置各异。IngressClass 就是用来描述”这一套规则交给哪个控制器、用啥参数”的资源。
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
把它标成 is-default-class: "true",以后 Ingress 不写 ingressClassName 就自动归它管。
Warning一个集群里最多只能有一个默认 IngressClass。要是标了两个,准入控制器会拒绝创建任何没显式写
ingressClassName的 Ingress。
28-9 多个路径都匹配怎么办
当多条路径同时匹配一个请求,优先级规则是:路径最长的赢;如果长度还一样,则 Exact 类型优先于 Prefix 类型。这套规则让你可以放心地写细粒度路由而不必担心被粗粒度抢走。
28-10 Ingress 与 Service 的分工
记住一张图:Service 负责把一组 Pod 收敛成一个稳定地址;Ingress 负责在集群边缘,按域名和路径把外部 HTTP 流量引入正确的 Service。
两者配合,才构成完整的对外服务能力。Ingress 本身不直接连 Pod,它始终是”指到 Service,再由 Service 指到 Pod”。
下章退一步看更底层的东西:Kubernetes 的网络模型长什么样,CNI 插件在其中扮演什么角色。