一个域名搞定前后端:用 Ingress 配置 / 和 /api 路由

概述

一个典型的 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
  • 前后端解耦:各自独立部署,互不影响

有了这套配置,你的项目就具备了生产级部署能力!

相关推荐
LONGZETECH16 分钟前
汽车故障诊断仿真教学软件【风光580】:技术架构、功能实现与落地实践
架构·汽车·汽车仿真教学软件·汽车教学软件
斯普信云原生组19 分钟前
Docker 开源软件应急处理方案及操作手册——容器运行异常处理
docker·容器·eureka
Ulyanov21 分钟前
从零构建现代化Python音频播放器:ttk深度应用与皮肤系统设计
python·架构·音视频·数据可视化
C'ᴇsᴛ.小琳 ℡23 分钟前
架构重构的技术
重构·架构
摆烂z44 分钟前
对外访问网络限制*.aliyuncs.com开放也拉不下来和查看docker容器结构
运维·docker·容器
斯普信云原生组1 小时前
Docker 开源软件应急处理方案及操作手册——资源限制与性能瓶颈
docker·容器·eureka
嵌入式老牛2 小时前
SST专题3-1 基于光分路器的MMC分布式控制系统架构
分布式·架构·驱动·光纤·sst
heimeiyingwang2 小时前
【架构实战】ETL架构演进:从批处理到实时流处理
数据仓库·架构·etl
我科绝伦(Huanhuan Zhou)2 小时前
分享一个很实用的K8S巡检脚本
linux·docker·kubernetes
墨雪遗痕2 小时前
工程架构认知一:一次请求到大量请求
架构