Kubernetes集群部署React应用通过NGINX Ingress访问无法加载静态资源
我有一个使用Argon Dashboard Pro模板开发的简单React Web应用,部署在Kubernetes集群中。该应用的Docker镜像在本地运行正常,在集群中通过NodePort暴露服务时也可正常访问,但通过NGINX Ingress暴露服务时无法正常打开页面。该Ingress已通过其他暴露REST端点的服务和应用测试,确认可正常使用。当前问题为页面内容无法正常渲染,部分JS文件找不到,但该问题在NodePort暴露服务时不会出现。
相关Kubernetes资源配置
Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: react-deployment namespace: support labels: app: react stage: dev spec: replicas: 1 template: metadata: labels: app: react spec: containers: - name: react image: fmaus/react-test:argon ports: - containerPort: 3000 name: react-port imagePullPolicy: Always restartPolicy: Always selector: matchLabels: app: react
Ingress
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: react-ingress namespace: support annotations: nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header Accept-Encoding ""; more_set_headers "Content-Type: text/javascript; charset=UTF-8"; nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: ingressClassName: nginx rules: - http: paths: - path: /test(/|$)(.*) pathType: Prefix backend: service: name: react-service port: number: 3000
Service
apiVersion: v1 kind: Service metadata: name: "react-service" namespace: support spec: selector: app: "react" ports: - port: 3000 type: ClusterIP
错误信息
访问Ingress路径时浏览器控制台报如下错误:
Loading failed for the <script> with source “http://c105-164.cloud.gwdg.de:31600/static/js/bundle.js”. subpath:61:1 Loading failed for the <script> with source “http://c105-164.cloud.gwdg.de:31600/static/js/vendors~main.chunk.js”. subpath:61:1 Loading failed for the <script> with source “http://c105-164.cloud.gwdg.de:31600/static/js/main.chunk.js”.
根因说明
这是典型的前端应用子路径部署适配问题:
React应用默认编译生成的静态资源引用都是绝对路径/static/xxx,当你通过Ingress的/test子路径访问应用时,浏览器会直接请求域名根路径下的/static/xxx资源,而你的Ingress只配置了/test前缀的转发规则,根路径没有对应服务,所以静态资源全部404。NodePort访问时是直接访问服务的根路径,所以不会出现该问题。
另外你当前Ingress里配置的more_set_headers "Content-Type: text/javascript; charset=UTF-8";属于多余配置,还会导致非JS类资源返回错误的Content-Type,反而加剧异常。
修复步骤
方案1:修改React应用适配子路径(推荐)
在React项目的package.json中添加homepage字段,指定应用的部署子路径:
{ "name": "your-react-app", "homepage": "/test", ... }
重新编译打包镜像后部署即可,修改后React生成的静态资源引用会自动带上/test前缀,和Ingress的路径匹配。
方案2:修改Ingress配置添加静态资源转发规则
如果不想修改前端代码,可以直接调整Ingress配置,增加/static路径的转发:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: react-ingress namespace: support annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: ingressClassName: nginx rules: - http: paths: - path: /test pathType: Prefix backend: service: name: react-service port: number: 3000 - path: /static pathType: Prefix backend: service: name: react-service port: number: 3000
同时删除原来多余的rewrite、configuration-snippet相关注解即可。
内容的提问来源于stack exchange,提问作者Fabian

