K8s环境中Frontend Pod无法通过Nginx转发访问Backend Pod求助
K8s环境下Nginx配置Frontend到Backend的K8-DNS访问问题
在K8s的app命名空间中配置Nginx实现Frontend到Backend服务访问时出现异常:
- Frontend Pod内直接访问Backend Service(
curl http://backend-service.app.svc:5000/api/process?message=testevnewipw)可正常获取响应 - 但在Pod内用
localhost访问(curl http://localhost/api/process?message=testevnewipw)或外部浏览器访问时,均返回404错误
相关配置文件
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: frontend-deployment namespace: app spec: replicas: 2 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: nodeSelector: app: frontend containers: - name: frontend image: frontend-image:latest ports: - containerPort: 80 command: ["/bin/sh"] args: ["-c", "nginx -g 'daemon off;'"] env: - name: BACKEND_HOST value: "backend-service.app.svc.cluster.local" - name: BACKEND_PORT value: "5000" volumeMounts: - name: nginx-config mountPath: /etc/nginx/conf.d/frontend.conf subPath: frontend.conf resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "200m" memory: "256Mi" volumes: - name: nginx-config configMap: name: frontend-config --- apiVersion: apps/v1 kind: Deployment metadata: name: backend-deployment namespace: app spec: replicas: 2 selector: matchLabels: app: backend template: metadata: labels: app: backend spec: nodeSelector: app: backend containers: - name: backend image: backend-image:latest ports: - containerPort: 5000
service.yaml
apiVersion: v1 kind: Service metadata: name: frontend-service namespace: app spec: type: LoadBalancer selector: app: frontend ports: - protocol: TCP port: 80 targetPort: 80 --- apiVersion: v1 kind: Service metadata: name: backend-service namespace: app spec: type: ClusterIP selector: app: backend ports: - protocol: TCP port: 5000 targetPort: 5000
configmap.yaml
apiVersion: v1 kind: ConfigMap metadata: name: frontend-config namespace: app data: frontend.conf: | resolver kube-dns.kube-system.svc.cluster.local valid=5s; server { listen 80; location / { try_files $uri $uri/ @backend; } location @backend { proxy_pass http://backend-service:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ^~ /api/ { rewrite ^/api/(.*) /$1 break; proxy_pass http://backend-service:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /static/ { alias /usr/share/nginx/html/static/; expires 30d; add_header Cache-Control "public, max-age=2592000"; } location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf)$ { expires 30d; add_header Cache-Control "public, max-age=2592000"; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
nginx.conf
resolver kube-dns.kube-system.svc.cluster.local valid=5s; server { listen 80; location / { try_files $uri $uri/ @backend; } location @backend { proxy_pass http://backend-service:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ^~ /api/ { rewrite ^/api/(.*) /$1 break; proxy_pass http://backend-service:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /static/ { alias /usr/share/nginx/html/static/; expires 30d; add_header Cache-Control "public, max-age=2592000"; } location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf)$ { expires 30d; add_header Cache-Control "public, max-age=2592000"; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
错误日志
2024/04/22 05:13:27 [error] 7#7: *71 open() "/usr/share/nginx/html/api/process" failed (2: No such file or directory), client: 10.224.0.4, server: localhost, request: "GET /api/process?message=Uchit HTTP/1.1", host: "4.157.106.175", referrer: "http://4.157.106.175/" 10.224.0.4 - - [22/Apr/2024:05:13:27 +0000] "GET /api/process?message=Uchit HTTP/1.1" 404 555 "http://4.157.106.175/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36" "-" 2024/04/22 05:13:30 [error] 7#7: *71 open() "/usr/share/nginx/html/api/process" failed (2: No such file or directory), client: 10.224.0.4, server: localhost, request: "GET /api/process?message=Uchit HTTP/1.1", host: "4.157.106.175", referrer: "http://4.157.106.175/" 10.224.0.4 - - [22/Apr/2024:05:13:30 +0000] "GET /api/process?message=Uchit HTTP/1.1" 404 555 "http://4.157.106.175/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36" "-" ^C **kubectl exec -it pod/<<frontend-pod>> -n app -- curl http://localhost/api/process?message=testevnewipw/** <html> <head><title>404 Not Found</title></head> <body> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.25.5</center> </body> </html>
正常访问情况
kubectl exec -it pod/<<frontend-pod>> -n app -- curl http://backend-service.app.svc:5000/api/process?message=testevnewipw {"response":"Processed: wpiwenvetset"}
问题排查与修复
根因分析
错误日志显示Nginx尝试在本地文件系统查找/api/process,说明**/api/路径的反向代理规则未生效**,请求被路由到静态文件处理逻辑。核心原因包括:
- Nginx配置未正确加载(conf.d目录配置未被主配置引入)
- Rewrite规则错误,导致请求后端的路径与实际接口不符
- 多server块冲突(主配置与conf.d中均存在server块)
修复步骤
验证生效配置
进入Frontend Pod查看Nginx实际加载的配置:kubectl exec -it pod/<frontend-pod-name> -n app -- nginx -T确认
location ^~ /api/配置块存在。修复配置加载
修改主nginx.conf,确保包含conf.d目录的配置引入:# 在http块内添加 include /etc/nginx/conf.d/*.conf;同时删除主配置中的重复server块,将所有server配置统一放在conf.d的frontend.conf中。
调整Rewrite规则
由于后端实际接口为/api/process,无需截断/api前缀,修改location ^~ /api/配置:location ^~ /api/ { proxy_pass http://backend-service:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }更新配置并重启Pod
kubectl apply -f configmap.yaml -n app kubectl rollout restart deployment/frontend-deployment -n app验证修复
在Pod内测试本地访问:kubectl exec -it pod/<frontend-pod-name> -n app -- curl http://localhost/api/process?message=test确认返回正常响应后,再通过浏览器访问测试。
内容的提问来源于stack exchange,提问作者Jonty
相关产品推荐
相关产品推荐

