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

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

相关推荐
天空属于哈夫克34 天前
企业微信二次开发:精准实现关键词自动回复
架构·企业微信
虎头金猫4 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
分布式存储与RustFS4 天前
MinIO 官方 Docker 镜像被移除:依赖它的项目该怎么办
docker·云原生·devops·对象存储·minio·分布式存储
晨米酱4 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
这个DBA有点耶4 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
codeejun4 天前
每日一Go·MySQL-5、锁机制全解析
云原生·golang
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
moMo4 天前
从固定流程到问题路由:让 LangGraph RAG 按需检索
架构
赵文宇(温玉)4 天前
CoreDNS的hosts插件的缺行配置导致k8s集群异常
容器·kubernetes·rancher
guo_wen_qiang4 天前
上传本地镜像到harbor中
docker·容器·持续部署