这个域名下挂着三套完全独立的东西:根路径是 WordPress,/qrcode 是一个 Nuxt 应用(二维码与文件分享),/tools 是另一个 Nuxt 应用(在线图片工具)。它们没有共用任何代码,只是恰好共用一个域名。
让这件事成立的是 Traefik 的 Ingress 路径匹配。
路径规则
Ingress 里按前缀分流,一个 host 下三条规则:
rules:
- host: www.mazter.cn
http:
paths:
- path: /qrcode
pathType: Prefix
backend:
service:
name: svc-qrcode-app
port:
number: 80
- path: /tools
pathType: Prefix
backend:
service:
name: svc-tools-app
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: svc-wordpress
port:
number: 80
匹配规则是最长前缀优先:/tools/compress 先匹配 /tools 而不是 /。所以顺序写在前面后面其实不影响结果,但把具体的写在前面更符合直觉。
要不要 stripPrefix
这是最容易踩的一个决策点。所谓 stripPrefix,是指 Ingress 把 /qrcode 这段前缀剥掉再转给后端,后端收到的就是 /。
我没有用它,理由是:现代前端框架(Nuxt、Next、Vite)都要求在构建期就知道自己的 base 路径。如果让 Ingress 偷偷把前缀剥掉,前端生成的资源链接和实际访问路径就会对不上,出现”页面能打开但 JS/CSS 全 404″。
做法是让应用自己知道前缀,构建时注入:
# Nuxt 构建期指定 baseURL
nuxt.config.ts 中:
app: {
baseURL: '/qrcode/'
}
于是后端收到的请求路径仍然是 /qrcode/xxx,应用自己也按 /qrcode 生成链接,两边对得上。
Middleware 的 API 组陷阱
Traefik v2 和 v3 的 CRD 分属不同的 API 组,写错的话资源能创建但完全不生效,而且不报错:
# v2(当前集群是 v2.11.18)
apiVersion: traefik.containo.us/v1alpha1
# v3
apiVersion: traefik.io/v1alpha1
判断方法很简单,看集群里实际装了哪些 CRD:
kubectl get crd | grep traefik
哪个组存在就用哪个。这个坑的表现是”我明明配了跳转 HTTPS,为什么不生效”,而 YAML 看起来毫无问题。
证书:一个 host 只有一张
三个应用共用一个 host,所以也只能有一张 TLS 证书。它们复用同一个 Secret(这里是 wp-tls),不需要为每个应用单独签发。cert-manager 按 host 签发,不是按路径。
这意味着新增子路径应用时,证书部分什么都不用做——这是共用域名的另一个便利。
什么时候该换子域名
子路径方案的前提是所有应用”彼此信任、共用一套 Cookie 域”。我的两个应用确实需要共享登录态(同一个 mazter_token Cookie 挂在根路径上),所以子路径是加分项。
如果某个应用需要完全独立的 Cookie、独立的安全策略,或者要交给别人维护,那就该拆成子域名。判断标准不是技术难度,是信任边界。