一个域名搞定前后端:用 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
  • 前后端解耦:各自独立部署,互不影响

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

相关推荐
Coder_Boy_2 小时前
Java(Spring AI)传统项目智能化改造——商业化真实案例(含完整核心代码+落地指南)
java·人工智能·spring boot·spring·微服务
桂花很香,旭很美2 小时前
Anthropic Agent 工程实战笔记 · 延伸阅读
笔记·架构·agent
Zhu_S W4 小时前
Kubernetes (K8s) 完全指南:Java 开发者的容器编排实践
java·容器·kubernetes
SmartBrain5 小时前
多智能体设计(第二部分):消息传递机制(含考题)
人工智能·架构·langchain·aigc
桂花很香,旭很美6 小时前
Anthropic Agent 工程实战笔记(二)工具设计
笔记·架构·language model
桂花很香,旭很美7 小时前
Anthropic Agent 工程实战笔记(六)安全与生产
笔记·架构·agent
王da魔8 小时前
Keepalived
网络·云原生
小义_9 小时前
【Docker】知识四
linux·运维·docker·容器
冷雨夜中漫步9 小时前
DockerDesktop打包docker镜像时报错
运维·docker·容器