React应用无法访问GKE中k8s Service 报ERR_NAME_NOT_RESOLVED及CORS错误
问题判定
首先可以明确,该问题和react-router-dom的BrowserRouter路由配置没有任何关系。
报错原因分析
1. ERR_NAME_NOT_RESOLVED 根因
你用到的server-cluster-ip-service是K8s集群内部的Service域名,只有集群内部的Pod、CoreDNS组件可以解析该域名。你之前进入客户端Pod内请求成功,是因为Pod运行在集群内部网络环境中。
但React代码是编译后下发到用户本地浏览器执行的,浏览器不在K8s集群网络内,自然无法解析这个内部域名,所以会报域名解析失败。
2. CORS报错根因
这是域名解析失败派生的异常:请求因为域名解析失败异常中断后,浏览器会默认判定为跨域拦截。你服务端已经配置了app.use(cors()),只要解决域名问题,CORS报错会自动消失。
另外你客户端fetch请求中携带的Access-Control-Allow-Origin是错误用法:这个是服务端返回的响应头,客户端不需要主动携带,多余的自定义请求头反而可能触发预检请求异常。
解决方案
方案一:后端服务暴露公网访问入口
- 将后端Service的类型改为LoadBalancer,或者配置Ingress规则给后端分配公网可访问的域名/IP
- 建议用create-react-app的环境变量管理不同环境的接口地址,避免硬编码:
开发环境.env.development配置:REACT_APP_API_URL=http://localhost:5000
生产环境.env.production配置:REACT_APP_API_URL=http://你的后端公网地址 - 修改fetch代码:
fetch(`${process.env.REACT_APP_API_URL}`, { mode: 'cors' }) // 补充响应体json解析,你之前的代码没有这一步,会导致拿到的是Response对象而非数组 .then(res => res.json()) .then(data => { console.log("DATA", data); setUsers(data); });
方案二:通过前端反向代理转发请求(更推荐)
不需要暴露后端服务到公网,利用前端部署的Nginx做反向代理,将同域名下指定前缀的请求转发到集群内部的后端服务:
- 修改客户端fetch请求为相对路径:
fetch("/api", { mode: 'cors' }) .then(res => res.json()) .then(data => { console.log("DATA", data); setUsers(data); });
- 给部署React的Pod内的Nginx添加反向代理配置:
server { listen 80; server_name _; # 静态资源直接返回,同时适配BrowserRouter的路由规则 location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; } # 匹配/api前缀的请求转发到后端Service location /api { rewrite ^/api/(.*) /$1 break; proxy_pass http://server-cluster-ip-service:5000; proxy_set_header Host $host; } }
该方案所有请求和前端都是同域名,天然不会有跨域问题,也不需要暴露后端服务到公网,安全性更高。
内容的提问来源于stack exchange,提问作者Davtho1983
相关产品推荐
相关产品推荐

