K8s Nginx Ingress部署静态网站时无法加载CSS/JS等静态资源
问题根因
静态资源加载失败是两个配置问题叠加导致的:
- 你当前配置的
nginx.ingress.kubernetes.io/rewrite-target: /规则没有做路径捕获,所有匹配/app1、/app2前缀的请求,只会把前缀部分替换成/转发给后端服务。但你部署的静态页面里,CSS、JS的引用基本都是根相对路径(比如<script src="/js/app.js">、<link rel="stylesheet" href="/css/app.css">),浏览器解析这类地址时,会直接请求http://k8s.example.k8s/js/app.js这类不带/app1//app2前缀的路径,根本匹配不到你配的Ingress规则,直接返回404。 - 现有rewrite逻辑没有处理尾斜杠兼容问题,访问
/app1(不带尾斜杠)时的跳转逻辑会打乱静态资源的相对路径解析,即使资源路径带了前缀也可能加载失败。
解决方案
根据你的部署场景选一种即可:
方案1:修正Ingress rewrite规则(无需修改静态站代码,优先选择)
把普通前缀路径改成正则匹配路径,增加路径捕获组,正确拼接前缀后的子路径转发给后端,同时补充尾斜杠兼容配置,修改后的Ingress配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: # 开启正则路径匹配 nginx.ingress.kubernetes.io/use-regex: "true" # 通过捕获组将前缀后的子路径拼接至转发目标 nginx.ingress.kubernetes.io/rewrite-target: /$2 # 兼容尾斜杠跳转,避免静态资源相对路径解析异常 nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^(/app1)$ $1/ permanent; rewrite ^(/app2)$ $1/ permanent; name: ingress-test spec: ingressClassName: nginx rules: - host: k8s.example.k8s http: paths: - path: /app1(/|$)(.*) pathType: Prefix backend: service: name: app1-svc port: number: 80 - path: /app2(/|$)(.*) pathType: Prefix backend: service: name: app2-svc port: number: 80
配置修改完成后执行kubectl apply -f 你的ingress配置文件.yaml,等待10秒左右规则生效后再测试访问。
注意:该方案要求静态站内的资源引用使用相对路径(例如
./css/app.css、js/app.js,不要在路径开头加/),如果是根路径开头的引用,仍然会从域名根路径查找资源,需要搭配方案2调整。
方案2:调整静态站构建配置(稳定性最高,无Ingress规则兼容问题)
如果是自主构建的前端静态站(Vue、React、纯静态HTML项目均可),直接在构建阶段配置对应子路径前缀即可:
- 纯静态站:将所有CSS、JS、媒体资源的引用路径改为带对应前缀的根路径,例如app1的资源统一修改为
/app1/css/xxx.css、/app1/js/xxx.js - Vue项目:在
vue.config.js中配置publicPath: '/app1/'(app2对应修改为/app2/)后重新打包部署 - React项目:在
package.json中增加配置"homepage": "/app1"(app2对应修改)后重新打包部署
该方案下可以直接移除rewrite-target注解,使用普通前缀路径匹配即可,不会出现路径转发的兼容问题。
快速排查方法
如果调整后仍有异常,直接按F12打开浏览器开发者工具,在「网络」面板查看加载失败的CSS/JS请求的完整路径,确认是否缺少/app1//app2前缀、返回状态码是否为404,对照实际请求路径调整规则即可。
内容的提问来源于stack exchange,提问作者Mohamed Rafraf
相关产品推荐
相关产品推荐

