K8s NodePort服务转发流量至未就绪Pod问题咨询
Kubernetes Service的预期行为确实是只将流量转发到处于就绪状态、且在Endpoints列表中的Pod,你遇到的情况属于异常,下面是几个最可能的原因及排查/解决方法:
1. 会话亲和性(Session Affinity)导致旧会话残留
如果你的Service配置了sessionAffinity: ClientIP,kube-proxy会为每个客户端IP创建持久化转发规则,默认超时时间为10800秒(3小时)。即使Pod从Endpoints中移除,已建立会话的客户端仍会被转发到该Pod,直到会话超时。
排查步骤
查看Service的会话亲和性配置:
kubectl get service <your-service-name> -o yaml | grep -A5 sessionAffinity
若返回结果包含sessionAffinity: ClientIP,即可确认是该问题。
解决方法
- 临时处理:更换客户端IP(比如重启本地网络)或等待会话超时;
- 永久修复:修改Service配置,将
sessionAffinity设为None,或缩短sessionAffinityConfig.clientIP.timeoutSeconds的值(例如设为60秒)。
2. kube-proxy规则未及时同步
kube-proxy负责将Endpoints的变更同步到节点的iptables/IPVS规则中,节点负载过高、kube-proxy进程卡顿等情况可能导致同步延迟。
排查步骤
- 进入未就绪Pod所在的Kind节点:
docker exec -it <kind-node-name> bash
- 检查iptables规则中是否仍包含该Pod的IP:
iptables-save | grep <unready-pod-ip>
若能查到相关规则,说明kube-proxy未完成规则同步。
解决方法
重启节点上的kube-proxy Pod:
kubectl delete pod -n kube-system -l k8s-app=kube-proxy
kube-proxy重启后会重新同步Endpoints规则。
3. Pod容器端口未正常释放
虽然就绪探针失败,但容器内的HTTP端口可能仍处于监听状态(比如进程崩溃后端口被其他进程接管,或PID 1进程未正确关闭端口)。这种情况虽不影响Service转发,但需确认是否存在异常。
排查步骤
进入未就绪Pod,检查端口监听状态:
kubectl exec <unready-pod-name> -- netstat -tulpn | grep <your-service-port>
若端口仍显示为LISTEN状态,说明进程异常但端口未释放。
解决方法
- 修复应用程序逻辑,确保进程崩溃时能正确释放端口;
- 为Pod配置
livenessProbe,当进程崩溃时自动重启Pod,避免未就绪但持续运行的状态。
4. Port-forward的API Server缓存延迟
使用kubectl port-forward service/<your-service-name> <local-port>:<service-port>时,流量通过Kubernetes API Server转发。API Server的Endpoints缓存可能导致短暂的延迟,多次测试后通常会恢复正常。
排查步骤
直接查询Endpoints,确认未就绪Pod已被移除:
kubectl get endpoints <your-service-name>
若以上方法均无法解决问题,建议提供Deployment和Service的YAML配置,以便进一步排查。
内容的提问来源于stack exchange,提问作者user3442122

