Appearance
Dispatch 平台网络架构与请求路由文档
更新时间: 2026-04-25 集群版本: K3s v1.34.3 节点: master (单节点, 192.168.1.5)
1. 外部请求完整路由路径
入口域名
平台通过两个域名对外提供服务, 最终指向同一套后端:
| 域名 | 协议 | 路径 | 对应服务 |
|---|---|---|---|
dispatch.loserbai.cn | HTTP | /web/ | dispatch-web 前端 |
dispatch.loserbai.cn | HTTP | /dispatch-ai/ | AI 服务 |
dispatch.loserbai.cn | HTTP | /dispatch-server/ | Server 服务 |
loserbai.cn | HTTP/HTTPS | / | dispatch-web 前端 |
loserbai.cn | HTTP/HTTPS | /dispatch-ai/ | AI 服务 |
loserbai.cn | HTTP/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;
}
}| 请求路径 | 处理方式 | 代理目标 |
|---|---|---|
/web | 301 → /web/ | - |
/web/ | 去掉前缀 → / | NodePort 32736 (dispatch-web Pod) |
/web/umi.xxx.css | 去掉前缀 → /umi.xxx.css | NodePort 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.cn | NodePort 31297 (k8s Ingress) |
/dispatch-server/... | Host 改为 dispatch.loserbai.cn | NodePort 31297 (k8s Ingress) |
/gitee/... | 代理到 gitee.com | gitee.com |
/public/... | 本地静态文件 | /public/ |
4. K8s 集群资源详情
4.1 Ingress 路由表
所有 Ingress 共享同一域名 dispatch.loserbai.cn,通过路径前缀区分不同服务:
| Ingress 名称 | 路径 | 后端 Service | 后端端口 | 状态 |
|---|---|---|---|---|
| dispatch-web-webapp | /web | dispatch-web-webapp | 80 | Running |
| dispatch-ai-servicechart | /dispatch-ai | dispatch-ai-servicechart | 8090 | Running |
| dispatch-server-servicechart | /dispatch-server | dispatch-server-servicechart | 8080 | Running |
| dispatch-app-servicechart | /dispatch-app | dispatch-app-servicechart | 8070 | CrashLoopBackOff |
Ingress Controller: ingress-nginx-controller (Namespace: ingress-nginx)
注意: dispatch-web 的
/web路径实际已被宿主机 Nginx 接管 (直接代理到 NodePort 32736), k8s Ingress 中的这条规则目前不会被外部流量触达 (仅在内网直接访问 NodePort 31297 时生效)。
4.2 Service 列表
| Service 名称 | 类型 | Cluster IP | NodePort | 目标端口 | Selector |
|---|---|---|---|---|---|
| dispatch-web-webapp | NodePort | 10.43.89.89 | 32736 | 80 | app.kubernetes.io/instance=dispatch-web |
| dispatch-ai-servicechart | NodePort | 10.43.68.136 | 30181 | 8090 | app.kubernetes.io/instance=dispatch-ai |
| dispatch-server-servicechart | NodePort | 10.43.203.198 | 31685 | 8080 | app.kubernetes.io/instance=dispatch-server |
| dispatch-app-servicechart | NodePort | 10.43.252.162 | 31678 | 8070 | app.kubernetes.io/instance=dispatch-app |
| ingress-nginx-controller | NodePort | - | 31297 | 80 | k8s Ingress 入口 |
4.3 Pod 列表
| Pod 名称 | 状态 | Pod IP | 端口 | 节点 |
|---|---|---|---|---|
| dispatch-web-webapp-748d9cc79f-qbx69 | Running | 10.42.0.211 | 80 | master |
| dispatch-ai-servicechart-7dbcbf5b48-qtrjp | Running | 10.42.0.210 | 8090 | master |
| dispatch-server-servicechart-9d84b45d5-km27c | Running | 10.42.0.207 | 8080 | master |
| dispatch-server-servicechart-6bd4c65857-h4ct4 | CrashLoopBackOff | 10.42.0.209 | 8080 | master |
| dispatch-app-servicechart-9c8566dc4-6bd76 | CrashLoopBackOff | 10.42.0.208 | 8070 | master |
5. 网络分层详解
5.1 第一层: 外网接入
Internet → 阿里云 (dispatch.loserbai.cn / loserbai.cn) → WireGuard → 10.0.8.6- 域名通过 DNS 解析到阿里云公网 IP
- 阿里云通过 WireGuard 隧道将流量转发到本机内网 IP
10.0.8.6 - 本机物理网卡
eno1IP 为192.168.1.5
5.2 第二层: 宿主机防火墙 (firewalld / nftables)
宿主机使用 firewalld 管理防火墙规则,底层为 nftables:
| Zone | 接口 | 策略 | 说明 |
|---|---|---|---|
| public | eno1 | 默认拒绝, 白名单放行 | 物理网卡, 开放 80/443/SSH 等端口 |
| trusted | cni0 | 全部放行 (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-web192.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=809. 排障记录 (按时间顺序)
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-webapp9.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 ← 罪魁祸首根因分析:
宿主机同时存在两套防火墙系统:
| 防火墙系统 | 管理工具 | 规则类型 | 处理优先级 |
|---|---|---|---|
| iptables | kube-router / kube-proxy | K8s 网络策略和 Service 转发 | filter 优先级 0 |
| nftables | firewalld | 宿主机防火墙策略 | 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; # 旧服务!
}根因分析:
两个问题叠加:
缺少
/dispatch-server代理规则: 请求/dispatch-server/org/itemList落到location /规则, 被代理到 dispatch-web Pod 的 Nginx。Pod 的try_files找不到该文件, 返回index.html。 JS 代码对 HTML 字符串调用.map()→ TypeError。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-serverlocation: 代理到 k8s Ingress (31297), Host 设为dispatch.loserbai.cn - 80 端口: 同步新增
/dispatch-serverlocation
详见 3.2 节 完整配置。
bash
# 修改后重启 nginx
/etc/init.d/nginx restart9.5 待修复: dispatch-app / dispatch-server CrashLoopBackOff
dispatch-app-servicechart-9c8566dc4-6bd76处于 CrashLoopBackOffdispatch-server-servicechart-6bd4c65857-h4ct4处于 CrashLoopBackOff- 旧版本
dispatch-server-servicechart-9d84b45d5-km27c仍在正常运行
10. 端口映射总览
| 端口 | 服务 | 说明 |
|---|---|---|
| 80 | 宿主机 Nginx | HTTP 入口, 反向代理到后端 |
| 443 | 宿主机 Nginx | HTTPS 入口, SSL 证书终止, 反向代理到后端 |
| 31297 | k8s Ingress Controller NodePort | 宿主机 Nginx 的上游, 处理 /dispatch-ai, /dispatch-server 等路径 |
| 32736 | dispatch-web Service NodePort | 宿主机 Nginx 直接代理前端到此端口 |
| 30181 | dispatch-ai Service NodePort | 通过 k8s Ingress 路由 |
| 31685 | dispatch-server Service NodePort | 通过 k8s Ingress 路由 |
| 31678 | dispatch-app Service NodePort | 通过 k8s Ingress 路由 (当前无可用 Pod) |