概述
一个典型的 Web 应用:
- 前端:React/Vue 构建的静态页面,部署在 Nginx
- 后端:Spring Boot/Node.js 提供的 API 服务
当想用 同一个域名 访问它们:
https://myapp.com/→ 前端首页https://myapp.com/api/users→ 后端接口
但直接部署会遇到问题:
- 前端和后端是两个独立服务
- 如果分别暴露,就得用不同端口或子域名
- 用户体验差,运维复杂
Kubernetes 的 Ingress 可以轻松解决这个问题。
为什么需要路径路由
在微服务架构中,常见需求:
| 路径 | 目标服务 |
|---|---|
/ 或 /static/* |
前端静态资源(Nginx) |
/api/* |
后端 API 服务 |
/admin/* |
管理后台 |
如果不用 Ingress,你可能:
- 前端用
http://myapp.com - 后端用
http://api.myapp.com - 或者前端代码里写死
http://localhost:8080/api(开发环境 OK,生产不行)
面临的问题:
- 跨域(CORS)配置麻烦
- 多个域名增加 SSL 证书成本
- 用户看到奇怪的 URL
整体架构图
用户浏览器
│
▼
https://myapp.com
│
▼
[ Ingress Controller ] ← 入口网关(如 Nginx)
│
├── 请求路径 / → [ frontend-svc ] → 前端 Pod(Nginx)
│
└── 请求路径 /api/... → [ backend-svc ] → 后端 Pod(API 服务)
核心:Ingress 根据 URL 路径,把流量路由到不同 Service
操作步骤
准备工作:部署前后端服务
假设你已将前后端打包成 Docker 镜像:
- 前端镜像:
my-frontend:latest(监听 80 端口) - 后端镜像:
my-backend:latest(监听 8080 端口)
1. 部署前端(Nginx 静态服务)
yaml
# frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deploy
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: my-frontend:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 80
2. 部署后端(API 服务)
yaml
# backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-deploy
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: api
image: my-backend:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: backend-svc
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 80
targetPort: 8080 # 注意:Service 端口可映射到容器不同端口
应用配置:
bash
kubectl apply -f frontend.yaml
kubectl apply -f backend.yaml
验证服务是否就绪:
bash
kubectl get svc
# 应看到 frontend-svc 和 backend-svc
配置 Ingress 路由规则
创建 ingress.yaml:
yaml
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
# 可选:让 Nginx 透传真实路径(重要!)
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.com # 你的域名
http:
paths:
- path: /api/
pathType: Prefix
backend:
service:
name: backend-svc
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
rewrite-target 注解
默认情况下,Ingress 会把完整路径转发给后端。
比如访问 /api/users,后端收到的还是 /api/users。
但你的后端 API 可能只认 /users(没有 /api 前缀)!
所以加这行注解:
yaml
nginx.ingress.kubernetes.io/rewrite-target: /
它的作用是:
- 把
/api/xxx重写成/xxx再转发给后端 - 前端
/不受影响
如果你的后端 API 本身就设计为 /api/users,则不需要这个注解。
应用 Ingress
bash
kubectl apply -f ingress.yaml
本地测试
方式 1:Minikube 用户
bash
# 获取 Ingress 控制器 IP
minikube ip
# 假设输出:192.168.49.2
修改本地 hosts 文件(/etc/hosts 或 Windows 的 C:\Windows\System32\drivers\etc\hosts):
192.168.49.2 myapp.com
然后访问:
http://myapp.com/→ 前端页面http://myapp.com/api/users→ 后端接口
成功!
方式 2:Kind 或远程集群
如果你有公网 IP 或 LoadBalancer:
bash
kubectl get ingress
得到 EXTERNAL-IP(如 203.0.113.10),同样绑定域名到该 IP 即可。
进阶:支持 HTTPS
只需两步:
1. 创建 TLS Secret(假设你有证书)
bash
kubectl create secret tls myapp-tls \
--cert=fullchain.pem \
--key=privkey.pem
2. 在 Ingress 中启用 TLS
yaml
spec:
tls:
- hosts:
- myapp.com
secretName: myapp-tls
rules:
- host: myapp.com
http:
paths:
- path: /api/
...
- path: /
...
现在访问 https://myapp.com 就是安全的!
自动申请免费证书?用 Cert-Manager + Let's Encrypt(下期主题!)
常见问题
Q1:为什么访问 /api 返回 404?
- 检查后端是否真的监听
/users(而不是/api/users) - 如果后端需要
/api/users,去掉rewrite-target注解
Q2:前端页面加载了,但 API 调用失败?
- 打开浏览器开发者工具,看 Network 请求是否发到正确路径
- 确保前端代码里 API 地址是相对路径:
fetch('/api/users'),不是http://localhost:8080/api/users
Q3:能同时支持多个域名吗?
可以!在 rules 下加多个 host:
yaml
- host: admin.myapp.com
http:
paths:
- path: /
backend:
service: admin-svc
port: { number: 80 }
总结
| 路径 | 转发到 | 关键配置 |
|---|---|---|
/ |
前端 Service | path: / |
/api/... |
后端 Service | path: /api/ + rewrite-target(按需) |
核心价值:
- 用户体验好:一个干净的域名
- 运维简单:统一入口,统一 HTTPS
- 前后端解耦:各自独立部署,互不影响
有了这套配置,你的项目就具备了生产级部署能力!