IP_HASH在Kubernetes中不生效,因云LB(如AWS ALB、阿里云SLB)不支持该算法且会覆盖真实客户端IP;需在云平台显式开启源IP会话保持,或改用Ingress Cookie粘性方案。
为什么 IP_HASH 在 Kubernetes 中不生效
因为大多数云厂商的负载均衡器(如 aws alb、阿里云 slb)根本不支持 ip_hash,它只在 nginx ingress controller 自身作为七层代理时才起作用;一旦前面套了云 lb,真实客户端 ip 就被替换成 lb 的内网 ip,所有请求看起来都来自同一个地址,ip_hash 失效是必然结果。
- 云 LB 默认做的是四层(TCP/UDP)或七层(HTTP)转发,不透传原始
X-Forwarded-For或不启用「会话保持」功能时,后端根本收不到真实 IP - 即使你配置了 Nginx 的
ip_hash,Ingress Controller 收到的也是 LB 的固定源 IP,哈希结果永远一样 - Kubernetes Service 类型为
LoadBalancer时,底层调用的是云平台 API,和 Nginx 配置完全无关
如何让云负载均衡器开启会话保持(Sticky Session)
必须在云平台控制台或 Terraform/CLI 中显式开启,不能靠 Ingress 配置“蒙混过关”。不同厂商开关位置和名称不同,但核心参数就两个:sticky_session_enabled 和 sticky_session_type(通常选 source_ip 或 application_cookie)。
- AWS ALB:需在 Target Group 中启用
Stickiness,类型选Source IP,超时时间建议设为3600秒以上 - 阿里云 SLB:监听配置里打开
会话保持,选择源 IP 会话保持,注意后端 ECS 必须在同一可用区才支持 - Tencent Cloud CLB:监听器 > 会话保持 > 开启,类型选
源 IP,不依赖 Cookie 或后端应用配合 - 如果用的是 TLS 穿透模式(即 LB 终止 HTTPS),确保
X-Forwarded-For头未被清洗,否则 Nginx 日志里看到的仍是 LB 内网 IP
当无法控制云 LB 时,改用 Cookie 会话保持的实操要点
这是最可控的兜底方案,但必须前后端协同:Ingress 负责注入 Cookie,后端服务不能忽略或覆盖它。
- Nginx Ingress 中给
Ingress加注解:nginx.ingress.kubernetes.io/affinity: "cookie"和nginx.ingress.kubernetes.io/session-cookie-name: "ROUTEID" - 务必加
nginx.ingress.kubernetes.io/session-cookie-expires和session-cookie-max-age,否则默认 1728000 秒(20 天),长期无效 Cookie 会堆积 - 后端应用不能自行设置同名 Cookie(比如 Spring Boot 默认的
JSESSIONID),否则会覆盖 Ingress 注入的路由标记 - 如果用了 Istio,
DestinationRule的trafficPolicy.loadBalancer.cookie也能实现类似效果,但仅限于网格内流量
验证会话是否真正保持的三个关键检查点
别只看日志里有没有报错,要确认请求确实落在了同一个 Pod 上,且状态能延续。
- 查 Pod 日志:用
kubectl logs -f <pod-name></pod-name>同时开多个终端,发带唯一 ID 的请求(比如curl -H "X-Request-ID: test-01" http://your.app/health),观察哪几个 Pod 打印了该 ID - 查 Ingress 访问日志:开启
nginx.ingress.kubernetes.io/enable-access-log: "true",确认同一客户端 IP 或 Cookie 值反复命中同一个 upstream 地址 - 检查响应头:成功启用 Cookie 粘性后,首次响应应含
Set-Cookie: ROUTEID=...; Path=/; HttpOnly; Max-Age=...,后续请求必须带上这个 Cookie,且 Ingress 不再重写它
真实环境里最容易漏掉的是云 LB 的健康检查路径——它不带 Cookie、也不走正常用户流量逻辑,会被轮询到任意后端,但这不是 bug,是设计使然。只要用户流量稳住,就没问题。










