Ingress 入口
HTTP 路由、TLS、与 Nginx 对比。
Ingress 入口
这一课你将能做到
- 对比 NodePort、LoadBalancer、Ingress 三种对外暴露方式并说清适用场景
- 在 minikube 启用 Ingress Controller,写出按 host/path 转发到多个 Service 的 Ingress 规则并验证
- 把本站现网「Nginx 反代 platform 与 backend」完整映射到 Ingress 模型
为什么要学
ClusterIP 只在集群内可用;NodePort 是逃生门不是正解。生产把 HTTP 服务暴露给用户的标准姿势是 Ingress:一条按域名/路径分流的路由规则 + 一个真正处理流量的 Ingress Controller(如 ingress-nginx)。
对照本站现网:你在服务器上配过 Nginx 443 反代——location /api 转给 backend:8080、其余转给 platform:3000、再挂 TLS 证书。上 K8s 后这份职责由 Ingress 承担,好处是:路由规则版本化进 Git、证书有 cert-manager 自动续期、多服务共享一个入口 IP 而不是一人开一个 NodePort。面试常问「Ingress 和 Service 什么关系」「为什么要有 Controller」。
先建立图像
现网(你熟悉的):
浏览器 → Nginx:443 ─┬─ location /api → backend:8080
└─ location / → platform:3000
K8s(本课目标):
浏览器 → Ingress Controller(也是 nginx)
│ 按 host/path 匹配 Ingress 规则
├─ /api → Service/backend → Pod × N
└─ / → Service/platform → Pod × N
角色分工(易混点):
| 组件 | 本质 | 管什么 |
|---|
| Ingress | API 对象(规则) | 声明「哪个域名/路径给哪个 Service」 |
| Ingress Controller | 真实运行的程序 | 读规则、生成 nginx 配置、处理流量 |
| Service | 稳定后端抽象 | Ingress 的下游,仍必需 |
一句话:Ingress 是「导航图」,Controller 是「司机」——只建 Ingress 不装 Controller,流量原地不动。
跟着做
步骤 1:启用 Ingress Controller(minikube 插件)
minikube addons enable ingress
kubectl get pods -n ingress-nginx
等 controller Pod 变为 Running(首次要拉镜像)。验证方式:
kubectl get svc -n ingress-nginx
kind 用户需自行 Helm 安装 ingress-nginx(官方文档有命令),本课以 minikube 为主线。
步骤 2:准备两个后端 Service
沿用第 5/6 课的 backend(nginx 占位)即可;再快速补一个 platform:
# deploy-platform.yaml + svc-platform.yaml(合并演示)
apiVersion: apps/v1
kind: Deployment
metadata:
name: platform
spec:
replicas: 1
selector:
matchLabels:
app: platform
template:
metadata:
labels:
app: platform
spec:
containers:
- name: web
image: nginx:1.27-alpine
---
apiVersion: v1
kind: Service
metadata:
name: platform
spec:
selector:
app: platform
ports:
- port: 80
targetPort: 80
kubectl apply -f deploy-platform.yaml
kubectl get svc backend platform
两个 Service 就位(backend 用前几课的 ClusterIP)。真实场景 platform 是你的前端镜像、backend 是 Spring Boot,路由结构完全相同。
步骤 3:写 Ingress 规则
ingress-coderoadmap.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: coderoadmap
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: app.local
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: platform
port:
number: 80
语义:访问 app.local/api/... 转给 Service backend;其余路径转给 platform。pathType: Prefix 按前缀匹配;更具体的路径放前面书写更清晰。
步骤 4:apply 并拿到入口地址
kubectl apply -f ingress-coderoadmap.yaml
kubectl get ingress coderoadmap
minikube ip
记下 ADDRESS 列的 IP(minikube 里即 minikube ip 的值)。
步骤 5:配置 hosts 并验证分流
Windows 用管理员身份编辑 C:\Windows\System32\drivers\etc\hosts,加一行(IP 换成你的):
curl -sS -o NUL -w "%{http_code}\n" http://app.local/ # platform(nginx 欢迎页 → 200)
curl -sS -o NUL -w "%{http_code}\n" http://app.local/api/ # backend
curl -sS -H "Host: app.local" http://192.168.49.2/api/
应看到两条路径分别命中不同后端(内容或状态码有区分)。生产环境这一步对应「域名 DNS 解析到 LB IP」。
步骤 6:TLS 与现网 Nginx 对照
Ingress 的 TLS 写法(证书存进 Secret,类型必须为 kubernetes.io/tls):
apiVersion: v1
kind: Secret
metadata:
name: app-local-tls
type: kubernetes.io/tls
data:
tls.crt: <base64 的证书>
tls.key: <base64 的私钥>
---
# Ingress spec 追加
spec:
tls:
- hosts:
- app.local
secretName: app-local-tls
生产不会手工管证书,用 cert-manager 自动申请续期(Let's Encrypt 等)。打开现网 Nginx 配置对照:server_name ↔ host、location /api ↔ paths、proxy_pass ↔ backend.service、ssl_certificate ↔ tls.secretName——概念一一对应,你其实早就会 Ingress 了。新标准 Gateway API 正在演进,了解即可,本 track 以 Ingress 对齐现网心智。
讲清楚要点
- Ingress 是规则,Controller 是数据面:先装 Controller 再写规则,缺一不可;
kubectl get ingress 的 ADDRESS 一直为空就是没 Controller 或没就绪。
- Ingress 不替代 Service:它的后端永远是 Service,Service 再到 Pod——三层叠加(Ingress → Service → Pod)各司其职。
- TLS 在入口终结:证书挂在 Ingress(实为 Controller)层,集群内部仍走 HTTP;证书续期用 cert-manager 自动化,过期中断是常见生产事故。
- 注解(annotations)因 Controller 而异:rewrite、超时、限流、白名单都靠注解,nginx/traefik 的注解名不同,换实现要重查文档。
- 入口通了不代表后端通了:Ingress 返回 502/503 时,先查后端 Pod 与 Endpoints(第 6 课三板斧),再查 Controller 日志。
- 本地 hosts ≠ 生产 DNS:本地用 hosts 模拟域名只是演示技巧;上线要真实域名、真实证书与 LB。
你可能会懵的地方
-
Ingress 和 Service 谁必须有?
Service 必须有,Ingress 是其上的 HTTP 路由层。只暴露一个服务时 NodePort/LB 也能凑合,但多服务按域名分流时 Ingress 是标准答案。
-
pathType 三个值什么区别?
Prefix 前缀匹配(最常用);Exact 精确匹配整条路径;ImplementationSpecific 交给 Controller 自行解释(不同实现行为可能不同,慎用)。写错或漏写会导致规则匹配不到。
-
为什么访问得到的是 default backend 的 404?
Controller 收到请求但没有任何规则匹配(Host 头不对、路径没写、Ingress 未生效)。先 get ingress 看 ADDRESS 与 HOSTS 列,再核对自己的 curl 目标。
-
Gateway API 要不要现在学?
知道它存在、定位是「Ingress 的下一代、角色模型更清晰」即可。Ingress 生态仍是当前主流,先掌握它。
-
ingress-nginx 和我服务器上的 Nginx 什么关系?
ingress-nginx 就是跑在 Pod 里的 Nginx + 一段自动生成配置的控制器。你手写过 location,它只是把这件事变成了「读 Ingress 对象自动生成」。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 只 apply Ingress 不装 Controller | 永远不通,ADDRESS 为空 | 先启用/安装 Controller |
| host 与 curl 的域名不一致 | 落到 default backend 404 | hosts 或 -H "Host: ..." 对齐 |
| path 与应用上下文不匹配 | 后端 404/静态资源丢失 | 对齐 /api 前缀或配 rewrite 注解 |
| 用 NodePort 当生产唯一入口 | 难管 TLS、端口暴露混乱 | Ingress/LB 收口 |
| 证书手动管、无人盯续期 | 到期 HTTPS 全站中断 | cert-manager 自动化 + 过期监控 |
卡点急救
get ingress 的 ADDRESS 一直空:Controller 没装好或没就绪——kubectl get pods -n ingress-nginx 看状态、kubectl logs -n ingress-nginx deploy/ingress-nginx-controller 找报错。
- 502/503(Bad Gateway):规则命中了但后端不可用——
get endpoints <svc> 是否为空、Pod 是否 Ready、Service 端口是否对齐(number 写的是 Service 的 port)。
- 本地域名访问不通:hosts 是否加对 IP(
minikube ip)、是否用了管理员保存;或直接 curl -H "Host: app.local" http://<ip>/ 绕过 DNS 验证 Controller 本身是否正常。
面试常问
-
Ingress 是什么?为什么需要 Ingress Controller?
Ingress 是定义 HTTP/HTTPS 路由规则(域名、路径 → Service)的 API 对象,本身不做任何转发;Ingress Controller 是依据这些规则实际处理流量的组件(常见 ingress-nginx、Traefik)。没有 Controller,规则只是 etcd 里的死数据。这样设计的意义:路由规则声明式、可版本化,数据面实现可替换。
-
Ingress、NodePort、LoadBalancer 怎么选?
NodePort:每个服务在所有节点开一个 30000-32767 高位端口,适合测试与内网临时访问;LoadBalancer:云厂商为 Service 创建外部负载均衡器,是流量进集群的底座,但每个服务一个 LB 成本高;Ingress:七层路由,一个入口 IP 按域名/路径分发到多个 Service,并集中做 TLS 终结。典型生产组合:一个 LoadBalancer 承载 Ingress Controller,Ingress 分发全部 HTTP 服务。
-
TLS 证书在 K8s 里怎么管理?
证书与私钥存于 kubernetes.io/tls 类型的 Secret,Ingress 的 tls 段引用后由 Controller 在入口终结 HTTPS。手工签发维护易过期出事故,生产用 cert-manager 配合 ACME(Let's Encrypt)自动申请与续期,并配过期监控兜底。
自测三问
- 为什么说「Ingress 不是 Service 的替代品」?
- 本站的
/api 与前端静态资源应如何在 paths 里拆分?
- Controller 挂了和 backend Pod 挂了,对外表现可能有什么不同?怎么区分?
小结一句话
Ingress 把「Nginx 反代多服务」翻译成声明式规则对象,Controller 负责执行——装好 Controller、写清 host/path/TLS,本站的对外入口模型就齐了;下一课给副本划资源边界并接入自动扩缩。
延伸