Skip to content

Dispatch 平台网络架构与请求路由文档

更新时间: 2026-04-25 集群版本: K3s v1.34.3 节点: master (单节点, 192.168.1.5)


1. 外部请求完整路由路径

入口域名

平台通过两个域名对外提供服务, 最终指向同一套后端:

域名协议路径对应服务
dispatch.loserbai.cnHTTP/web/dispatch-web 前端
dispatch.loserbai.cnHTTP/dispatch-ai/AI 服务
dispatch.loserbai.cnHTTP/dispatch-server/Server 服务
loserbai.cnHTTP/HTTPS/dispatch-web 前端
loserbai.cnHTTP/HTTPS/dispatch-ai/AI 服务
loserbai.cnHTTP/HTTPS/dispatch-server/Server 服务

请求链路: dispatch.loserbai.cn

用户浏览器


[1] DNS 解析: dispatch.loserbai.cn → 阿里云公网 IP


[2] 阿里云服务器 (反向代理 / WireGuard 对端)


[3] WireGuard 隧道: 阿里云 → 本机 10.0.8.6


[4] 宿主机 192.168.1.5 (eno1 网卡, firewalld public zone)
    │  端口 80 已在 public zone 开放

[5] 宿主机 Nginx (宝塔面板, 监听 80 端口)
    │  根据 server_name 和 location 规则分发:
    │    /web     → 301 重定向到 /web/
    │    /web/    → 直接代理到 dispatch-web NodePort (32736), 去掉 /web 前缀
    │    其他路径  → 代理到 k8s Ingress Controller NodePort (31297)

[6a] dispatch-web 场景:
    宿主机 Nginx → NodePort 32736 → Pod 10.42.0.211:80
    (绕过 k8s Ingress, 直接通过 Service 转发)

[6b] 其他服务场景 (/dispatch-ai, /dispatch-server 等):
    宿主机 Nginx → k8s Ingress Controller (NodePort 31297)
    → 根据 Host + Path 路由匹配 → 后端 Service → Pod


[7] 目标 Pod (容器内 Nginx 监听端口, 处理请求)


[8] 响应沿原路返回至用户浏览器

请求链路: loserbai.cn

用户浏览器


[1] DNS 解析: loserbai.cn → 阿里云公网 IP


[2] 阿里云服务器 → WireGuard 隧道 → 本机 10.0.8.6


[3] 宿主机 Nginx (宝塔面板)
    ├── HTTP (:80) 和 HTTPS (:443) 配置一致

    ├── /                    → proxy_pass 32736 (dispatch-web Pod)
    ├── /dispatch-ai/...     → proxy_pass 31297 (k8s Ingress, Host: dispatch.loserbai.cn)
    ├── /dispatch-server/... → proxy_pass 31297 (k8s Ingress, Host: dispatch.loserbai.cn)
    ├── /gitee/...           → proxy_pass gitee.com
    └── /public/...          → alias /public/

2. 网络架构总览

                              ┌─────────────────────────────────────────┐
                              │           阿里云 (公网)                   │
                              │  dispatch.loserbai.cn / loserbai.cn     │
                              └────────────────┬────────────────────────┘
                                               │ WireGuard

┌──────────────────────────────────────────────────────────────────────────┐
│                        宿主机 master (192.168.1.5)                        │
│                                                                          │
│  ┌─────────────┐   ┌──────────────┐   ┌──────────────────────────────┐ │
│  │   eno1      │   │  firewalld   │   │          K3s 集群             │ │
│  │ 192.168.1.5 │──▶│  (nftables)  │   │                              │ │
│  │ (物理网卡)   │   │              │   │  ┌────────────────────────┐  │ │
│  └─────────────┘   │  public:     │   │  │  cni0 网桥 (10.42.0.1) │  │ │
│                    │    eno1      │   │  │                        │  │ │
│  ┌──────────────┐  │  trusted:    │   │  │  ┌───────┐ ┌────────┐ │  │ │
│  │ 宿主机 Nginx  │  │    cni0      │   │  │  │ingress│ │web Pod │ │  │ │
│  │ (宝塔面板)    │◀─│              │   │  │  │nginx  │ │ .0.211 │ │  │ │
│  │ :80 :443     │  └──────────────┘   │  │  │ .0.219│ │ :80    │ │  │ │
│  │              │                     │  │  └───────┘ └────────┘ │  │ │
│  │ /, /web/ ────────────────────────────▶ NodePort 32736       │  │ │
│  │              │                     │  │  (直连 web Pod)        │  │ │
│  │ API路径 ────────────────────────────▶ NodePort 31297         │  │ │
│  │              │                     │  │  (k8s Ingress)         │  │ │
│  └──────────────┘                     │  └────────────────────────┘  │ │
│                                       └──────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘

宿主机 Nginx 请求分发逻辑

              请求到达宿主机 Nginx (:80 / :443)

             ┌───────────┴───────────────────────┐
             │                                   │
      server_name                               server_name
   dispatch.loserbai.cn                       loserbai.cn
             │                                   │
     ┌───────┴───────┐              ┌────────────┴────────────┐
     │               │              │                         │
  /web ?         其他路径        /dispatch-* ?            其他路径
     │               │              │                         │
 301→/web/    proxy_pass      proxy_pass              proxy_pass
     │        → 31297          → 31297                  → 32736
 proxy_pass   (Ingress)       (Ingress)               (web Pod)
 → 32736
 (web Pod)

3. 宿主机 Nginx 配置

3.1 dispatch.loserbai.cn

配置文件: /www/server/panel/vhost/nginx/dipatch.loserbai.cn.conf

nginx
server {
    listen 80;
    server_name dispatch.loserbai.cn;

    # /web 无尾部斜杠 → 301 重定向到 /web/
    location = /web {
        return 301 $scheme://$host/web/;
    }

    # /web/ → 直接代理到 dispatch-web NodePort (32736), 去掉 /web/ 前缀
    location /web/ {
        proxy_pass http://192.168.1.5:32736/;
        proxy_set_header Host dispatch.loserbai.cn;
        proxy_set_header X-real-ip $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 其他请求 → k8s Ingress Controller (31297)
    location / {
        proxy_pass http://192.168.1.5:31297/;
        proxy_set_header Host dispatch.loserbai.cn;
        proxy_set_header X-real-ip $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
请求路径处理方式代理目标
/web301 → /web/-
/web/去掉前缀 → /NodePort 32736 (dispatch-web Pod)
/web/umi.xxx.css去掉前缀 → /umi.xxx.cssNodePort 32736 (dispatch-web Pod)
/dispatch-ai/...保持原路径NodePort 31297 (k8s Ingress)
/dispatch-server/...保持原路径NodePort 31297 (k8s Ingress)

3.2 loserbai.cn

配置文件: /www/server/panel/vhost/nginx/loserbai.cn.conf

HTTP (:80) 和 HTTPS (:443) 配置一致:

nginx
server {
    listen 443 ssl;
    server_name www.loserbai.cn loserbai.cn;
    ssl_certificate /www/ssl/loserbai.cn/loserbai.cn.pem;
    ssl_certificate_key /www/ssl/loserbai.cn/loserbai.cn.key;

    location /public {
        alias /public/;
    }

    location /dispatch-ai {
        proxy_set_header Host "dispatch.loserbai.cn";
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://192.168.1.5:31297;
    }

    location /dispatch-server {
        proxy_set_header Host "dispatch.loserbai.cn";
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://192.168.1.5:31297;
    }

    location /gitee {
        proxy_pass http://gitee.com/;
        proxy_set_header Host gitee.com;
    }

    location / {
        proxy_pass http://192.168.1.5:32736/;
        proxy_set_header Host $host;
        proxy_set_header X-real-ip $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

server {
    listen 80;
    server_name www.loserbai.cn loserbai.cn;
    # (location 规则与 HTTPS 块完全相同)
}
请求路径处理方式代理目标
/直接代理NodePort 32736 (dispatch-web Pod)
/umi.xxx.css直接代理NodePort 32736 (dispatch-web Pod)
/dispatch-ai/...Host 改为 dispatch.loserbai.cnNodePort 31297 (k8s Ingress)
/dispatch-server/...Host 改为 dispatch.loserbai.cnNodePort 31297 (k8s Ingress)
/gitee/...代理到 gitee.comgitee.com
/public/...本地静态文件/public/

4. K8s 集群资源详情

4.1 Ingress 路由表

所有 Ingress 共享同一域名 dispatch.loserbai.cn,通过路径前缀区分不同服务:

Ingress 名称路径后端 Service后端端口状态
dispatch-web-webapp/webdispatch-web-webapp80Running
dispatch-ai-servicechart/dispatch-aidispatch-ai-servicechart8090Running
dispatch-server-servicechart/dispatch-serverdispatch-server-servicechart8080Running
dispatch-app-servicechart/dispatch-appdispatch-app-servicechart8070CrashLoopBackOff

Ingress Controller: ingress-nginx-controller (Namespace: ingress-nginx)

注意: dispatch-web 的 /web 路径实际已被宿主机 Nginx 接管 (直接代理到 NodePort 32736), k8s Ingress 中的这条规则目前不会被外部流量触达 (仅在内网直接访问 NodePort 31297 时生效)。

4.2 Service 列表

Service 名称类型Cluster IPNodePort目标端口Selector
dispatch-web-webappNodePort10.43.89.893273680app.kubernetes.io/instance=dispatch-web
dispatch-ai-servicechartNodePort10.43.68.136301818090app.kubernetes.io/instance=dispatch-ai
dispatch-server-servicechartNodePort10.43.203.198316858080app.kubernetes.io/instance=dispatch-server
dispatch-app-servicechartNodePort10.43.252.162316788070app.kubernetes.io/instance=dispatch-app
ingress-nginx-controllerNodePort-3129780k8s Ingress 入口

4.3 Pod 列表

Pod 名称状态Pod IP端口节点
dispatch-web-webapp-748d9cc79f-qbx69Running10.42.0.21180master
dispatch-ai-servicechart-7dbcbf5b48-qtrjpRunning10.42.0.2108090master
dispatch-server-servicechart-9d84b45d5-km27cRunning10.42.0.2078080master
dispatch-server-servicechart-6bd4c65857-h4ct4CrashLoopBackOff10.42.0.2098080master
dispatch-app-servicechart-9c8566dc4-6bd76CrashLoopBackOff10.42.0.2088070master

5. 网络分层详解

5.1 第一层: 外网接入

Internet → 阿里云 (dispatch.loserbai.cn / loserbai.cn) → WireGuard → 10.0.8.6
  • 域名通过 DNS 解析到阿里云公网 IP
  • 阿里云通过 WireGuard 隧道将流量转发到本机内网 IP 10.0.8.6
  • 本机物理网卡 eno1 IP 为 192.168.1.5

5.2 第二层: 宿主机防火墙 (firewalld / nftables)

宿主机使用 firewalld 管理防火墙规则,底层为 nftables:

Zone接口策略说明
publiceno1默认拒绝, 白名单放行物理网卡, 开放 80/443/SSH 等端口
trustedcni0全部放行 (ACCEPT)K8s Pod 网络网桥

已开放的常用端口 (public zone): 22(SSH), 80(HTTP), 443(HTTPS), 8080, 3306, 6379, 5432 等

5.3 第三层: 宿主机 Nginx (宝塔面板)

宿主机上运行宝塔面板安装的 Nginx,作为所有 HTTP/HTTPS 请求的入口反向代理。 根据 server_name 区分不同域名,根据 location 规则分发到不同后端。 详见上方 第 3 节

5.4 第四层: K8s Ingress (Nginx Ingress Controller)

k8s Ingress Controller 运行在 NodePort 31297,处理除 /web 外的所有路由:

宿主机 Nginx → :31297 → ingress-nginx-controller Pod (10.42.0.219)

                              ├─ Host: dispatch.loserbai.cn, Path: /dispatch-ai
                              │   → dispatch-ai-servicechart:8090

                              ├─ Host: dispatch.loserbai.cn, Path: /dispatch-server
                              │   → dispatch-server-servicechart:8080

                              └─ Host: dispatch.loserbai.cn, Path: /dispatch-app
                                  → dispatch-app-servicechart:8070

关键: Ingress 按 Host: dispatch.loserbai.cn 匹配, 因此 loserbai.cn 的 API 请求 必须在宿主机 Nginx 中设置 proxy_set_header Host "dispatch.loserbai.cn" 才能正确路由。

5.5 第五层: K8s Service (kube-proxy)

Service 通过 kube-proxy (iptables 模式) 实现负载均衡和端口转发:

ClusterIP:Port → iptables DNAT → PodIP:Port

同时每个 Service 暴露 NodePort,可直接通过节点 IP + NodePort 访问:

  • 192.168.1.5:32736 → dispatch-web
  • 192.168.1.5:30181 → dispatch-ai

5.6 第六层: Pod 网络 (Flannel CNI)

cni0 网桥: 10.42.0.1/24
    ├── vethxxx → ingress-nginx-controller (10.42.0.219)
    ├── vethxxx → dispatch-web-webapp       (10.42.0.211)
    ├── vethxxx → dispatch-ai-servicechart   (10.42.0.210)
    ├── vethxxx → dispatch-server            (10.42.0.207)
    └── vethxxx → 其他 Pod...
  • CNI: Flannel
  • Pod CIDR: 10.42.0.0/24 (单节点)
  • Service CIDR: 10.43.0.0/16
  • 每个 Pod 通过 veth pair 连接到 cni0 网桥

6. 请求路由示例

示例 1: 通过 loserbai.cn 访问前端 (最短路径)

GET https://loserbai.cn/

[1] 浏览器 → DNS → 阿里云 → WireGuard → 10.0.8.6:443
[2] 宿主机 Nginx (loserbai.cn :443 SSL)
[3] location / → proxy_pass http://192.168.1.5:32736/
[4] kube-proxy NodePort 32736 → Pod 10.42.0.211:80
[5] 容器内 Nginx: try_files / → /index.html
[6] 返回 HTML (引用 ./umi.e82a76b0.css)

GET https://loserbai.cn/umi.e82a76b0.css

[7] 宿主机 Nginx location / → proxy_pass 32736/umi.e82a76b0.css
[8] Pod 返回 CSS → 200 OK ✓

示例 2: 通过 dispatch.loserbai.cn 访问前端

GET http://dispatch.loserbai.cn/web

[1] 浏览器 → DNS → 阿里云 → WireGuard → 10.0.8.6:80
[2] 宿主机 Nginx (dispatch.loserbai.cn :80)
[3] location = /web → 301 重定向到 /web/

GET http://dispatch.loserbai.cn/web/

[4] 宿主机 Nginx: location /web/ → proxy_pass 32736/ (去掉 /web/ 前缀)
[5] kube-proxy NodePort 32736 → Pod 10.42.0.211:80
[6] 容器内 Nginx: try_files / → /index.html
[7] 返回 HTML (引用 ./umi.e82a76b0.css)

GET http://dispatch.loserbai.cn/web/umi.e82a76b0.css

[8] 浏览器解析 ./umi.css → /web/umi.css (因为当前 URL 是 /web/)
[9] 宿主机 Nginx: location /web/ → proxy_pass 32736/umi.e82a76b0.css
[10] Pod 返回 CSS → 200 OK ✓

示例 3: loserbai.cn 调用后端 API

GET https://loserbai.cn/dispatch-server/org/itemList

[1] 宿主机 Nginx (loserbai.cn :443 SSL)
[2] location /dispatch-server → proxy_pass 31297 + Host: dispatch.loserbai.cn
[3] k8s Ingress 匹配: host=dispatch.loserbai.cn, path=/dispatch-server
[4] → dispatch-server-servicechart:8080 → Pod 10.42.0.207:8080
[5] 返回 JSON 数据 ✓

示例 4: AI 聊天接口 (SSE)

GET https://loserbai.cn/dispatch-ai/chat/

[1] 宿主机 Nginx (loserbai.cn :443 SSL)
[2] location /dispatch-ai → proxy_pass 31297 + Host: dispatch.loserbai.cn
[3] k8s Ingress 匹配: host=dispatch.loserbai.cn, path=/dispatch-ai
[4] → dispatch-ai-servicechart:8090 → Pod 10.42.0.210:8090
[5] AI 服务处理, SSE 流式返回 ✓

7. 容器内 Nginx 配置

dispatch-web 容器内 Nginx 配置如下:

nginx
server {
    listen 80;
    server_name localhost;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
  • 监听 80 端口
  • 静态文件目录: /usr/share/nginx/html
  • SPA 支持: try_files 回退到 index.html (支持 React Router hash 路由)

8. 部署架构

CI/CD 流程

Git Push (main 分支)
    → GitLab CI/CD Pipeline
        → Build Stage: docker build → 推送到 Harbor 镜像仓库
        → Deploy Stage: helm upgrade --install
            → dispatch-web-webapp (Deployment)
            → Service (NodePort)
            → Ingress (nginx class, host: dispatch.loserbai.cn, path: /web)

Helm 部署参数

bash
helm upgrade --install dispatch-web $WEB_APP_CHART \
  --namespace dispatch \
  --set image.repository=$HAR_DOCKER_HOST/dispatch/dispatch-web \
  --set image.tag=$IMAGE_TAG \
  --set service.targetPort=80 \
  --set service.type=NodePort \
  --set ingress.enabled=true \
  --set ingress.className=nginx \
  --set ingress.hosts[0].host=dispatch.loserbai.cn \
  --set ingress.hosts[0].paths[0].path=/web \
  --set ingress.hosts[0].paths[0].pathType=Prefix \
  --set ingress.hosts[0].paths[0].backend.service.name=dispatch-web-webapp \
  --set ingress.hosts[0].paths[0].backend.service.port.number=80

9. 排障记录 (按时间顺序)

9.1 问题一: Ingress Service Name 不匹配 → 503

现象: 浏览器访问 http://dispatch.loserbai.cn/web 返回 503 Service Unavailable

排查过程:

bash
# 1. 检查 Ingress 状态, 发现后端解析失败
$ kubectl describe ingress dispatch-web-webapp -n dispatch
Rules:
  Host                  Path  Backends
  dispatch.loserbai.cn
                        /web   dispatch-web:80 (<error: endpoints "dispatch-web" not found)

# 2. 检查 Service, 发现实际名称是 dispatch-web-webapp
$ kubectl get svc -n dispatch
NAME                           TYPE       CLUSTER-IP
dispatch-web-webapp            NodePort   10.43.89.89    # 实际名称

根因: .gitlab-ci.yml 第 40 行 Helm 部署参数设置了:

bash
--set ingress.hosts[0].paths[0].backend.service.name=dispatch-web

但实际创建的 Service 名称为 dispatch-web-webapp (Helm chart 自动添加了 release name 前缀)。

修复:

bash
# 临时修复: 直接修改 Ingress 资源
kubectl patch ingress dispatch-web-webapp -n dispatch \
  --type='json' \
  -p='[{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/service/name", "value": "dispatch-web-webapp"}]'

# 验证
$ kubectl describe ingress dispatch-web-webapp -n dispatch | grep Backends
                        /web   dispatch-web-webapp:80 (10.42.0.211:80)  ✓

永久修复: 需要修改 .gitlab-ci.yml 第 40 行:

bash
# 修改前
--set ingress.hosts[0].paths[0].backend.service.name=dispatch-web

# 修改后
--set ingress.hosts[0].paths[0].backend.service.name=dispatch-web-webapp

9.2 问题二: firewalld 阻断 Pod 间通信 → 502

现象: 修复 503 后访问 http://dispatch.loserbai.cn/web 返回 502 Bad Gateway

排查过程:

bash
# 1. 检查 Ingress Controller 日志, 发现连接 Pod 失败
$ kubectl logs -n ingress-nginx ingress-nginx-controller-xxx --tail=30
connect() failed (113: Host is unreachable) while connecting to upstream,
upstream: "http://10.42.0.211:80/web"

# 2. 从 Ingress Pod 内部测试, 确认无法连通目标 Pod
$ kubectl exec -n ingress-nginx <pod> -- ping -c 2 10.42.0.211
100% packet loss

# 3. 从宿主机测试, 发现宿主机可以连通
$ ping -c 2 10.42.0.211
2 packets transmitted, 2 received, 0% packet loss

# 4. Ingress Pod 可以 ping 通网关, 但 ping 不通其他 Pod
$ kubectl exec -n ingress-nginx <pod> -- ping -c 2 10.42.0.1
2 received
$ kubectl exec -n ingress-nginx <pod> -- ping -c 2 10.42.0.211
100% packet loss

# 5. 抓包分析, 发现是 admin prohibited
$ tcpdump -i cni0 icmp
IP master > 10.42.0.219: ICMP host 10.42.0.211 unreachable - admin prohibited filter

# 6. 检查 nftables 规则, 发现 firewalld 兜底拒绝
$ nft list ruleset | grep "reject with icmpx admin-prohibited"
filter_FORWARD_POLICIES chain 末尾:
    reject with icmpx admin-prohibited 罪魁祸首

根因分析:

宿主机同时存在两套防火墙系统:

防火墙系统管理工具规则类型处理优先级
iptableskube-router / kube-proxyK8s 网络策略和 Service 转发filter 优先级 0
nftablesfirewalld宿主机防火墙策略filter 优先级 10 (后执行)

流量处理流程:

Pod A → cni0 网桥 → iptables FORWARD (kube-router 处理, ACCEPT) → nftables FORWARD (firewalld 处理)

iptables 正确 ACCEPT 了 Pod 间流量, 但随后 nftables 的 firewalld 规则再次处理该包。由于 cni0 接口没有加入任何 firewalld zone, 流量命中了 filter_FORWARD_POLICIES 链末尾的兜底规则 reject with icmpx admin-prohibited

nftables filter_FORWARD 链:
    ct state { established, related } accept   ← 已有连接放行
    ct status dnat accept                       ← DNAT 放行
    jump filter_FORWARD_POLICIES
        ├── br-87630bfe77e0 规则...             ← Docker 网桥有专门处理
        ├── docker0 规则...                     ← Docker 默认网桥有专门处理
        ├── ...                                 ← 其他接口有专门处理
        ├── (cni0 没有任何规则!)                 ← cni0 被忽略
        └── reject with icmpx admin-prohibited  ← 兜底: 全部拒绝!
    reject with icmpx admin-prohibited

修复:

bash
# 将 cni0 加入 firewalld trusted zone (target: ACCEPT, 全部放行)
firewall-cmd --zone=trusted --add-interface=cni0 --permanent
firewall-cmd --reload

# 验证
$ firewall-cmd --zone=trusted --list-all
trusted (active)
  target: ACCEPT
  interfaces: cni0

修复后 nftables 对 cni0 接口的流量直接 ACCEPT, 不再经过 filter_FORWARD_POLICIES 的兜底拒绝规则。

重启 Ingress Controller (此前因网络不通可能状态异常):

bash
kubectl rollout restart deployment ingress-nginx-controller -n ingress-nginx

影响范围: 修复前, 所有 K8s Pod 间通信均被阻断 (Ingress → 任何后端 Pod 都无法连通)。


9.3 问题三: 前端静态资源 404 → 页面白屏

现象: 修复 502 后, 页面不再报错但白屏, 浏览器控制台报:

GET http://dispatch.loserbai.cn/umi.e82a76b0.css net::ERR_ABORTED 404 (Not Found)
GET http://dispatch.loserbai.cn/umi.95c5704d.js  net::ERR_ABORTED 404 (Not Found)

根因分析:

浏览器相对路径解析规则:

当前 URL          相对路径 ./umi.css    解析结果
────────────────────────────────────────────────
/web              ./umi.css          → /umi.css       ✗ 匹配不到 Ingress
/web/             ./umi.css          → /web/umi.css   ✓ 正确

完整故障链路:

[1] 用户访问 http://dispatch.loserbai.cn/web
[2] 宿主机 Nginx → k8s Ingress → dispatch-web Pod
[3] Pod 返回 index.html, 其中引用 ./umi.e82a76b0.css
[4] 浏览器当前 URL 为 /web (无尾部斜杠), ./ 解析到根目录 /
[5] 浏览器请求 http://dispatch.loserbai.cn/umi.e82a76b0.css
[6] 宿主机 Nginx location / → k8s Ingress → 无匹配的 path 规则 → 404

核心矛盾:

  • 容器内 Nginx 配置为根路径 (location /) 提供服务
  • k8s Ingress 通过 /web 前缀路由到该容器
  • 容器不知道自己被挂在 /web 路径下, 静态资源引用路径与 Ingress 路径不匹配

修复: 在宿主机 Nginx 添加代理规则:

  • location = /web → 301 重定向到 /web/ (确保相对路径正确解析)
  • location /web/proxy_pass http://192.168.1.5:32736/; (尾部斜杠自动去掉 /web 前缀)

详见 3.1 节 完整配置。


9.4 问题四: loserbai.cn 前端 API 调用失败 → TypeError: Cannot read properties of undefined (reading 'map')

现象: https://loserbai.cn/#/home 页面加载后白屏, 控制台报:

TypeError: Cannot read properties of undefined (reading 'map')
    at ue (p__items__index.7c4699d0.async.js:2:8235)

排查过程:

bash
# 1. 确认 items 页面的 API 调用
# src/pages/items/service.ts:
const ItemListUri = "/dispatch-server/org/itemList"

# 2. 检查 loserbai.cn 的 nginx 配置, 发现缺少 /dispatch-server 代理
$ cat /www/server/panel/vhost/nginx/loserbai.cn.conf
# 只有 /dispatch-ai, 没有 /dispatch-server!

# 3. 检查 HTTPS 配置, 发现 443 端口还在代理旧服务
location ~*^.+$ {
    proxy_pass http://localhost:8200;   # 旧服务!
}

根因分析:

两个问题叠加:

  1. 缺少 /dispatch-server 代理规则: 请求 /dispatch-server/org/itemList 落到 location / 规则, 被代理到 dispatch-web Pod 的 Nginx。Pod 的 try_files 找不到该文件, 返回 index.html。 JS 代码对 HTML 字符串调用 .map() → TypeError。

  2. HTTPS 配置未更新: 443 端口仍代理到 localhost:8200 (旧版 bai_server.conf 配置), 没有指向 dispatch-web。

修复:

更新 /www/server/panel/vhost/nginx/loserbai.cn.conf:

  • 443 端口: 从 proxy_pass http://localhost:8200 改为与 80 端口一致的代理规则
  • 新增 /dispatch-server location: 代理到 k8s Ingress (31297), Host 设为 dispatch.loserbai.cn
  • 80 端口: 同步新增 /dispatch-server location

详见 3.2 节 完整配置。

bash
# 修改后重启 nginx
/etc/init.d/nginx restart

9.5 待修复: dispatch-app / dispatch-server CrashLoopBackOff

  • dispatch-app-servicechart-9c8566dc4-6bd76 处于 CrashLoopBackOff
  • dispatch-server-servicechart-6bd4c65857-h4ct4 处于 CrashLoopBackOff
  • 旧版本 dispatch-server-servicechart-9d84b45d5-km27c 仍在正常运行

10. 端口映射总览

端口服务说明
80宿主机 NginxHTTP 入口, 反向代理到后端
443宿主机 NginxHTTPS 入口, SSL 证书终止, 反向代理到后端
31297k8s Ingress Controller NodePort宿主机 Nginx 的上游, 处理 /dispatch-ai, /dispatch-server 等路径
32736dispatch-web Service NodePort宿主机 Nginx 直接代理前端到此端口
30181dispatch-ai Service NodePort通过 k8s Ingress 路由
31685dispatch-server Service NodePort通过 k8s Ingress 路由
31678dispatch-app Service NodePort通过 k8s Ingress 路由 (当前无可用 Pod)