Kubernetes服务认知误区:React与Rust后端通信故障排查
你遇到的核心问题是浏览器无法解析Kubernetes集群内部的Service DNS名称。backend是集群内ClusterIP服务的域名,只有集群里的Pod能通过K8s DNS服务解析,而你的前端请求在用户浏览器中发起(浏览器处于集群外部),自然无法识别这个域名,导致ERR_NAME_NOT_RESOLVED错误。
下面是几种可行的解决方案,按生产实用性排序:
方案一:Nginx反向代理(生产首选)
把React应用打包后部署在Nginx容器中,通过Nginx配置反向代理,将前端的API/WebSocket请求转发到集群内的backend服务。Nginx运行在K8s Pod里,属于集群内部,能正常解析backend域名。
1. 修改前端请求路径
将前端代码中的绝对地址改为相对路径:
- 把
http://backend:8080/test改为/api/test - 把
ws://<minikube-ip>/ws改为/ws
2. 编写Nginx配置文件(nginx.conf)
server { listen 80; server_name localhost; # 托管React静态文件 root /usr/share/nginx/html; index index.html; # 处理React路由刷新404问题 location / { try_files $uri $uri/ /index.html; } # 反向代理API请求到后端服务 location /api/ { proxy_pass http://backend:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 反向代理WebSocket请求 location /ws { proxy_pass http://backend:8080/ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } }
3. 构建包含Nginx的前端镜像
创建Dockerfile:
# 阶段1:构建React应用 FROM node:18-alpine as builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # 阶段2:部署到Nginx FROM nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
重新构建并推送镜像:
docker build -t quan1um/react-test:nginx . docker push quan1um/react-test:nginx
4. 更新前端Deployment配置
修改前端Deployment的容器镜像和端口:
apiVersion: apps/v1 kind: Deployment metadata: name: client-deployment labels: app: client spec: replicas: 1 selector: matchLabels: app: client template: metadata: labels: app: client tier: frontend spec: containers: - name: client image: quan1um/react-test:nginx imagePullPolicy: Always ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: client-service spec: selector: app: client tier: frontend ports: - protocol: "TCP" port: 80 targetPort: 80 type: LoadBalancer
部署更新后的配置:
kubectl apply -f client-deployment.yaml
现在通过minikube service client-service访问前端,所有/api和/ws请求会自动被Nginx转发到backend:8080,解决域名解析问题。
方案二:暴露后端服务+前端环境变量注入
如果不想用Nginx,可以把后端服务暴露为NodePort/LoadBalancer,然后在前端代码中通过环境变量注入后端的外部访问地址。
1. 修改后端Service为NodePort
apiVersion: v1 kind: Service metadata: name: backend spec: selector: app: backend ports: - protocol: TCP port: 8080 targetPort: http nodePort: 30080 # 可选,指定固定端口 type: NodePort
获取后端外部访问地址:
minikube service backend --url
2. 给前端Deployment添加环境变量
spec: containers: - name: client image: quan1um/react-test:latest imagePullPolicy: Always ports: - containerPort: 3000 env: - name: REACT_APP_API_URL value: "http://<minikube-ip>:30080" # 替换为上面获取的地址 - name: REACT_APP_WS_URL value: "ws://<minikube-ip>:30080"
3. 前端代码使用环境变量
// API请求 fetch(`${process.env.REACT_APP_API_URL}/test`) .then(res => res.json()) .then(data => console.log(data)); // WebSocket连接 const ws = new WebSocket(`${process.env.REACT_APP_WS_URL}/ws`);
重新构建前端镜像并部署即可。
方案三:Ingress统一路由
通过Kubernetes Ingress资源,将同一个域名下的不同路径映射到前端和后端服务,既解决域名解析问题,又避免跨域。
1. 启用minikube Ingress插件
minikube addons enable ingress
2. 创建Ingress配置文件(ingress.yaml)
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: rules: - host: app.local http: paths: - path: /(.*) pathType: Prefix backend: service: name: client-service port: number: 3000 - path: /api/(.*) pathType: Prefix backend: service: name: backend port: number: 8080 - path: /ws pathType: Exact backend: service: name: backend port: number: 8080
3. 修改本地hosts文件
在/etc/hosts(Linux/macOS)或C:\Windows\System32\drivers\etc\hosts(Windows)中添加:
<minikube-ip> app.local
4. 前端代码改为相对路径
和方案一一致,将API请求改为/api/test,WebSocket改为/ws。
部署Ingress:
kubectl apply -f ingress.yaml
现在访问http://app.local即可打开前端,请求会自动通过Ingress路由到对应服务。
关于Nginx配置的疑问解答
你看到的Nginx配置中使用K8s服务名称,就是方案一中的思路:Nginx运行在集群内部Pod,能解析K8s DNS服务的域名,所以可以直接用http://backend:8080作为代理目标,而浏览器只需要访问前端的地址,无需知道后端的存在。
内容的提问来源于stack exchange,提问作者quantum

