ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【Kubernetes从入门到精通】第17篇:Ingress——HTTP流量的“总管家“

2026/8/6 11:06:08 拓冰建站 浏览量
【Kubernetes从入门到精通】第17篇:Ingress——HTTP流量的“总管家“

上一篇【第16篇】Service的负载均衡原理——kube-proxy到底干了什么
下一篇【第18篇】Ingress Controller选型和实战——Nginx Ingress完全指南


摘要

Service不错——ClusterIP让你内部Pod互相找到,NodePort对外开了个后门,LoadBalancer更是直接挂上了云厂商的LB。但你有没有发现一个尴尬的问题:一个公网LB一个月几百块,你有3个服务就得买3个LB,10个服务就得买10个——这谁顶得住?而且Service只管四层(TCP/UDP),HTTP Header里那些花活(域名路由、路径匹配、Cookie粘滞、Header改写)它一概不关心。

这就是Ingress出场的原因——它是K8s原生的七层HTTP路由入口。一个Ingress Controller对应一个LB,通过域名和路径把流量分发给不同的后端Service。本文先把Ingress和Service的关系理清楚,再逐字段拆解Ingress YAML,最后演示TLS证书管理。


一、Ingress是什么——“HTTP反向代理入口”

1.1 Service解决不了的三个问题

【Service的局限——为什么要Ingress】 问题1:每个公网服务要一个LB = 穷死 用 LoadBalancer Service: 用 Ingress: ┌──────┐ ┌──────┐ ┌──────┐ ┌─────────────────────────┐ │ LB-1 │ │ LB-2 │ │ LB-3 │ │ 一个 LB (省钱!) │ │$100/月│ │$100/月│ │$100/月│ │ │ └──┬───┘ └──┬───┘ └──┬───┘ │ api.example.com → API │ │ │ │ │ web.example.com → Front │ ▼ ▼ ▼ │ admin.example.com→Admin │ ┌──────┐┌──────┐┌──────┐ └─────────────────────────┘ │API ││Front ││Admin │ └──────┘└──────┘└──────┘ 10个服务 = 10个LB = ¥1000/月 😱 10个服务 = 1个LB = ¥100/月 😎 问题2:域名路由 Service不行 问题3:URL路径路由 Service不行 /api/* → API Service, /web/* → Frontend Service

要点:Service工作在OSI第四层(传输层),只管IP和端口。Ingress工作在第七层(应用层),能看HTTP的Host头、URL路径、Cookie等。打个比方:Service是邮局的"按地址送信",Ingress是公司的"前台接待员"——看你是来面试的、送快递的还是谈合作的,把你引到不同的办公室

1.2 Ingress ≠ Ingress Controller

这是很多人学Ingress时踩的第一个坑——Ingress只是"规则",Ingress Controller才是真正转发流量的"发动机"

【Ingress 和 Ingress Controller 的关系】 你写的 Ingress 资源: 实际干活的是 Ingress Controller: ┌─────────────────────────┐ ┌─────────────────────────┐ │ apiVersion: networking │ │ Nginx Ingress Controller│ │ .k8s.io/v1 │ │ (一个运行的Pod) │ │ kind: Ingress │ ──监听──▶ │ │ │ │ │ 监听Ingress资源变化 │ │ spec: │ │ → 生成 nginx.conf │ │ rules: │ │ → reload nginx │ │ - host: api.ex.com │ │ → 按规则转发HTTP流量 │ │ paths: │ │ │ │ - path: /users │ │ 类比: │ │ backend: ... │ │ Ingress = nginx.conf │ └─────────────────────────┘ │ Ingress Controller │ │ = nginx 进程 │ └─────────────────────────┘ Ingress 只是配置文件——自己不干活! 跟Service类似:Service也是"配置",真正转发的是kube-proxy

要点:K8s默认不安装任何Ingress Controller——你装了Nginx Ingress、Traefik、Contour等任一款Controller后,Ingress资源才能生效。这个设计很像Java的接口和实现:Ingress是接口标准,各家Controller是具体实现。


二、Ingress YAML——完整拆解

一个完整的Ingress资源长这样:

apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:myapp-ingressnamespace:defaultannotations:# 各种功能开关(不同Controller不同)nginx.ingress.kubernetes.io/rewrite-target:/nginx.ingress.kubernetes.io/ssl-redirect:"true"spec:ingressClassName:nginx# ★ 指定用哪个 Ingress Controllertls:# ★ TLS配置-hosts:-api.example.com-web.example.comsecretName:example-tls# TLS证书存在这个Secret里rules:# ★ 路由规则——核心!-host:api.example.com# 域名匹配http:paths:-path:/users# 路径前缀匹配pathType:Prefix# Prefix(前缀)或 Exact(精确)backend:service:name:users-service# 转发到哪个Serviceport:number:8080-path:/orderspathType:Prefixbackend:service:name:orders-serviceport:number:8080-host:web.example.com# 另一个域名http:paths:-path:/pathType:Prefixbackend:service:name:frontend-serviceport:number:80defaultBackend:# ★ 默认后端——匹配不到任何规则时用resource:apiGroup:k8s.example.comkind:StorageBucketname:static-assets

2.1 ingressClassName——“谁来执行这些规则?”

spec:ingressClassName:nginx# 告诉K8s:"这个Ingress交给Nginx Ingress Controller处理"

如果你集群里装了多个Ingress Controller(比如同时有Nginx和Traefik),这个字段确保Ingress只被指定的Controller处理。K8s 1.18+版本强烈推荐设置这个字段。

2.2 host和path——“根据什么路由?”

【Ingress路由决策流程】 HTTP请求: GET http://api.example.com/users/123 │ ▼ ┌─────────────────────────────────────────────┐ │ Ingress Controller │ │ │ │ Step 1: 匹配 host │ │ "Host头是 api.example.com 吗?" │ │ 遍历所有rules,找到 host 匹配的 │ │ │ │ │ ▼ │ │ Step 2: 匹配 path │ │ "URL路径是 /users/123" │ │ pathType是Prefix:/users能匹配 /users/123 │ │ │ │ │ ▼ │ │ Step 3: 转发到 backend │ │ 转发到 users-service:8080 │ └─────────────────────────────────────────────┘

2.3 pathType——前缀还是精确?

pathType含义示例/users能匹配的请求
Prefix路径前缀匹配path: /users/users/users//users/123/users/123/orders
Exact精确匹配path: /users/users
ImplementationSpecific由Controller决定取决于具体Controller的实现
# Prefix vs Exact 的区别paths:-path:/apipathType:Prefix# /api、/api/、/api/users 都能匹配backend:...-path:/healthpathType:Exact# 只有 /health 能匹配,/health/check 不行backend:...

2.4 defaultBackend——“如果都没匹配到…”

# 所有规则都没匹配上时的兜底处理spec:defaultBackend:service:name:404-handler# 返回404页面port:number:80rules:-host:api.example.com# ...

要点defaultBackend不是必选项,但我建议都配上——至少指向一个返回404的服务。否则没匹配到的请求可能会被路由到随机后端,或者返回Ingress Controller自己的默认页面,用户体验极差。


三、基于域名的路由——“一个入口,多个服务”

【域名路由示意】 user1: api.example.com/users ─┐ user2: api.example.com/orders ──┤ │ ▼ ┌─────────────────┐ │ Ingress Controller│ │ (Nginx/Traefik) │ │ :80/:443 │ └──┬──────┬──────┬──┘ │ │ │ host匹配 │ │ │ ┌──────────────┘ │ └──────────────┐ ▼ ▼ ▼ api.example.com web.example.com admin.example.com │ │ │ ┌────────┴────────┐ ┌──────┴──────┐ ┌──────┴──────┐ │ /users │ /orders│ │ / │ │ / │ ▼ ▼ │ ▼ │ ▼ │ ┌──────┐ ┌────────┐ │ ┌──────────┐ │ ┌──────────┐ │ │users │ │orders │ │ │frontend │ │ │admin │ │ │svc │ │svc │ │ │svc │ │ │panel svc │ │ └──────┘ └────────┘ │ └──────────┘ │ └──────────┘ │ └────────────────┘ └────────────────┘
# 域名+路径双层路由apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:multi-domain-ingressspec:ingressClassName:nginxrules:# 第一个域名:api.example.com-host:api.example.comhttp:paths:-path:/userspathType:Prefixbackend:service:name:users-serviceport:number:8080-path:/orderspathType:Prefixbackend:service:name:orders-serviceport:number:8080-path:/productspathType:Prefixbackend:service:name:products-serviceport:number:8080# 第二个域名:web.example.com-host:web.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:frontend-serviceport:number:80# 第三个域名:admin.example.com-host:admin.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:admin-serviceport:number:8080

四、TLS配置——让Ingress终结HTTPS

Ingress Controller是TLS终结的最佳位置——客户端到Ingress是HTTPS,Ingress到后端Pod是HTTP。这样后端Pod不用管证书的事,省心又安全。

【TLS 终结——Ingress处理HTTPS,后端Pod只管HTTP】 客户端 Ingress Controller 后端Pod ────── ────────────────── ────── https://api.example.com/users ┌────────────────┐ ┌────┐ ──────────────────────────────► │ 解密TLS │ http://10.244 │ │ 加密传输 │ 检查Host/Path │ ─────────────► │ │ │ 路由到后端 │ 明文传输 │ │ │ (K8s内部网络安全) │ └────┘ └────────────────┘

4.1 手动配置TLS证书

# Step 1: 用OpenSSL生成自签名证书(仅限测试!)openssl req-x509-nodes-days365-newkeyrsa:2048\-keyouttls.key-outtls.crt\-subj"/CN=api.example.com/O=MyOrg"# Step 2: 创建TLS Secretkubectl create secret tls example-tls\--cert=tls.crt\--key=tls.key\-ndefault# Step 3: 在Ingress中引用
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:api-ingress-tlsspec:ingressClassName:nginxtls:-hosts:-api.example.com-web.example.com# 一个Secret可以服务多个域名secretName:example-tls# 刚才创建的Secretrules:-host:api.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:api-serviceport:number:8080

4.2 用cert-manager自动管理证书——“再也不用记续期时间”

cert-manager是K8s生态中管理TLS证书的事实标准。它自动从Let’s Encrypt(免费)等CA申请证书、自动续期。

# 安装cert-manager(Helm方式)helm repoaddjetstack https://charts.jetstack.io helminstallcert-manager jetstack/cert-manager\--namespacecert-manager\--create-namespace\--setinstallCRDs=true
# 创建Issuer(证书颁发者配置)apiVersion:cert-manager.io/v1kind:Issuermetadata:name:letsencrypt-prodnamespace:defaultspec:acme:server:https://acme-v02.api.letsencrypt.org/directoryemail:admin@example.comprivateKeySecretRef:name:letsencrypt-prod-keysolvers:-http01:ingress:class:nginx---# Ingress——只需加一个Annotation,cert-manager自动帮你拿证书apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:api-ingress-tls-autoannotations:cert-manager.io/issuer:"letsencrypt-prod"# ← 就这一行!spec:ingressClassName:nginxtls:-hosts:-api.example.comsecretName:api-tls-secret# cert-manager自动创建这个Secretrules:-host:api.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:api-serviceport:number:8080

要点:cert-manager注册免费TLS证书需要域名有真实DNS解析(Let’s Encrypt会验证域名所有权)。本地测试用自签名证书就够了,但生产环境强烈建议用cert-manager + Let’s Encrypt——免费、自动续期、不用半夜爬起来更新过期证书。


五、rewrite-target——URL路径改写

这是Ingress最常见的玩法——外部路径和内部路径不一样:

apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:rewrite-ingressannotations:# 关键:重写目标路径nginx.ingress.kubernetes.io/rewrite-target:/$2spec:ingressClassName:nginxrules:-host:api.example.comhttp:paths:# 外部: /api/users → 内部: /users# 正则 (.*) 捕获组,$2 代表第二个捕获组-path:/api(/|$)(.*)pathType:ImplementationSpecificbackend:service:name:api-serviceport:number:8080
【URL 重写示意】 外部请求 内部转发 ───────── ──────── /api/users ──rewrite──► /users /api/users/123 ──rewrite──► /users/123 /api/orders ──rewrite──► /orders /health ──不匹配──► /health(走其他规则或defaultBackend) 注解说明: nginx.ingress.kubernetes.io/rewrite-target: /$2 path: /api(/|$)(.*) 正则解释: /api — 匹配 "/api" (/|$) — $1: 匹配 "/" 或 结尾 (.*) — $2: 匹配剩余所有字符 rewrite到: /$2 = 去掉 /api 前缀

六、同一个Ingress管理多个服务——完整示例

apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:main-ingressannotations:cert-manager.io/issuer:"letsencrypt-prod"nginx.ingress.kubernetes.io/ssl-redirect:"true"spec:ingressClassName:nginxtls:-hosts:-"*.example.com"secretName:wildcard-tlsdefaultBackend:service:name:default-backendport:number:80rules:# 用户API-host:api.example.comhttp:paths:-path:/v1/userspathType:Prefixbackend:service:name:users-v1-serviceport:number:8080-path:/v2/userspathType:Prefixbackend:service:name:users-v2-service# v2灰度版port:number:8080# PC Web前端-host:www.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:web-frontend-serviceport:number:80# 移动端API(不同的域名)-host:m.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:mobile-api-serviceport:number:8080# 管理后台-host:admin.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:admin-serviceport:number:8080
# 部署并验证kubectl apply-fmain-ingress.yaml kubectl get ingress# NAME CLASS HOSTS ADDRESS PORTS# main-ingress nginx api.example.com,www.example.com 10.0.1.100 80, 443# m.example.com,admin.example.com# 测试路由curl-H"Host: api.example.com"http://10.0.1.100/v1/userscurl-H"Host: www.example.com"http://10.0.1.100/curl-H"Host: admin.example.com"http://10.0.1.100/

本篇小结

Ingress是K8s七层路由的标准入口——它让你用一个LB管理N个服务,通过域名和路径精准分发HTTP流量:

  1. Ingress是规则,Controller是引擎:Ingress资源只是"配置文件",真正干活的是Nginx Ingress/Traefik等Controller
  2. 域名+路径双层路由hostpath组合决定流量去向,Prefix/Exact两种匹配模式各有用处
  3. TLS终结:Ingress处理HTTPS→HTTP转换,cert-manager免费自动管理证书,告别手动续期
  4. pathType和rewrite:控制路径匹配粒度和改写规则,是Ingress日常使用率最高的功能

下一篇,咱们深入Ingress Controller的世界——Nginx Ingress怎么工作、常用Annotations大全、金丝雀发布怎么配、Traefik有什么不一样的玩法。


上一篇【第16篇】Service的负载均衡原理——kube-proxy到底干了什么
下一篇【第18篇】Ingress Controller选型和实战——Nginx Ingress完全指南