为何Kubernetes集群中单会话请求始终指向同一Pod?
可能的原因及检查方向
1. Kubernetes Service的会话亲和性配置
Kubernetes Service默认会话亲和性为None,但如果被设置为ClientIP,会导致同一客户端IP的请求持续发往同一后端Pod。
- 执行命令查看目标Service的配置:
kubectl get service <你的服务名称> -n mynamespace -o yaml - 重点检查
spec.sessionAffinity字段,若值为ClientIP,就是导致请求固定的核心原因,同时可查看spec.sessionAffinityConfig下的超时设置,确认IP粘性的生效时长。
2. OpenShift Router(HAProxy)的隐性粘性设置
虽然你的Route注解未配置粘性,但HAProxy可能因HTTP头(如Cookie)自动启用会话粘性,或者Router全局配置默认开启了相关规则。
- 进入Router Pod查看实际运行的HAProxy配置:
kubectl exec -n openshift-ingress <router-pod-name> -- cat /var/lib/haproxy/conf/haproxy.cfg - 查找对应路由的backend配置段,检查是否存在
cookie相关配置(比如cookie SRV insert),这类配置会强制开启会话粘性。
3. Service的外部流量策略影响
如果Service的externalTrafficPolicy设置为Local,CLB会直接将请求路由到运行目标Pod的EC2实例,结合Service的IP粘性,会导致同一客户端IP的请求一直落到该实例上的同一个Pod。
- 检查Service配置中的
spec.externalTrafficPolicy字段,若为Local,可尝试改为默认的Cluster,让流量先经过集群内部的负载均衡再分发到Pod。
4. 浏览器DNS缓存导致的EC2实例固定
Route53的Simple策略会随机返回EC2实例的IP,但浏览器会缓存DNS解析结果,同一标签页会一直使用缓存的IP访问某个EC2实例;而该EC2实例上的Service如果有IP粘性,就会把请求固定到同一个Pod。隐身窗口不共享常规窗口的DNS缓存,所以会解析到另一个EC2实例,进而关联到另一个Pod。
对应解决方案
修改Service会话亲和性:如果Service的
sessionAffinity为ClientIP,修改为None:spec: sessionAffinity: None执行
kubectl apply -f <service配置文件路径>更新配置。禁用OpenShift Router的Cookie粘性:在Route注解中添加禁用配置:
annotations: haproxy.router.openshift.io/disable_cookies: "true" haproxy.router.openshift.io/timeout: 300s meta.helm.sh/release-name: appname-routing meta.helm.sh/release-namespace: mynamespace更新Route配置后,HAProxy会停止基于Cookie的会话粘性。
调整DNS缓存策略:缩短Route53记录的TTL值(比如设置为30秒),减少浏览器缓存IP的时长;或者改用Route53的加权路由策略,配合短TTL实现更均匀的流量分发。
调整Service外部流量策略:若
externalTrafficPolicy为Local,改为Cluster,让集群内部的负载均衡层参与流量分发,避免EC2实例级别的固定。
内容的提问来源于stack exchange,提问作者Coder

