Kubernetes 中实现会话保持(Session Affinity)

在 Kubernetes 中实现会话保持(Session Affinity),也称为粘性会话(Sticky Sessions),主要有以下几种方法,每种方法适用于不同的场景和层级。

核心方法概览

 
方法实现层级机制优点缺点适用场景
1. Service sessionAffinity L4 (传输层) 基于客户端 IP 地址 配置简单,K8s 原生支持 不精确(同一 NAT 后的用户被视为同一客户端) 对会话要求不高的简单应用
2. Ingress 注解/规则 L7 (应用层) 基于 Cookie 精确、可靠、可配置 需要 Ingress 控制器支持(如 Nginx) 生产环境最常用的方式
3. ServiceMesh (e.g., Istio) L7 (应用层) 基于 HTTP 头、Cookie 等 功能最强大,粒度最细 架构复杂,学习成本高 需要精细流量管理的大型微服务架构

方法详解

1. 使用 Service 的 sessionAffinity (IP-based)

这是 Kubernetes Service 自带的基础功能,工作在传输层(TCP/UDP)。

  • 原理:将来自同一个客户端 IP 的所有请求都转发到同一个后端 Pod。

  • 配置:在 Service 的 YAML 文件中设置 sessionAffinity: ClientIP

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  sessionAffinity: ClientIP # 默认为 None,这里设置为 ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800 # 会话保持的持续时间(秒),默认是 10800(3小时)
  • 优点:

    • 配置非常简单,是 K8s 内置功能。

  • 缺点:

    • 不精确:在很多网络环境下(如公司 NAT、4G/5G 网络),多个真实用户会共享同一个公网 IP,导致他们的请求都被发往同一个 Pod,无法实现真正的用户级会话保持。

    • 如果客户端 IP 发生变化(例如移动网络切换),会话就会中断。

2. 使用 Ingress 控制器 (Cookie-based)

这是生产环境中最推荐、最常用的方法,工作在应用层(HTTP/HTTPS)。它通过 Set-Cookie 来精确识别用户。

以最流行的 Nginx Ingress Controller 为例:

  • 原理:Ingress 控制器在第一个响应中为客户端设置一个唯一的 Cookie,客户端后续请求会带上这个 Cookie,Ingress 根据 Cookie 的值将请求路由到对应的 Pod。

a) 使用注解(Annotations)

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie" # 开启基于 Cookie 的会话保持
    nginx.ingress.kubernetes.io/session-cookie-name: "route" # 自定义 Cookie 名称
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800" # Cookie 过期时间(秒)
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" # Cookie 最大年龄(秒)
spec:
  ingressClassName: nginx
  rules:
  - host: my-app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

b) 使用 Ingress 规则中的 loadBalancer 配置 (更新、更规范的方式)

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: my-app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80
  loadBalancer:
    ingressClassName: nginx
    # 核心配置在这里
    affinity:
      cookie:
        name: SESSION_COOKIE # 自定义 Cookie 名称
        maxAge: 86400 # 生存期
        # 注意:不同版本的K8s和Ingress控制器,此处的API可能略有不同。
  • 优点:

    • 非常精确:基于每个浏览器会话,不受 NAT 影响。

    • 可靠:即使 Pod 重启,只要 Service 能将请求发往替代的 Pod,应用层可以重建会话(需要应用支持会话外部化,见下文最佳实践)。

  • 缺点:

    • 需要特定的 Ingress 控制器支持(Nginx, Traefik, HAProxy 等都支持)。

3. 使用 Service Mesh (例如 Istio)

在更复杂的微服务架构中,Service Mesh 提供了最强大的流量控制能力。

  • 原理:在 VirtualService 等 CRD 资源中配置基于 HTTP 头(如 x-user-id)或 Cookie 的负载均衡策略。

Istio 配置示例:

yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-destination-rule
spec:
  host: my-service
  trafficPolicy:
    loadBalancer:
      consistentHash:
        # 可以基于多种方式,这里使用 HTTP Header
        httpHeaderName: "x-user-id" # 根据此 Header 的值进行哈希
        # 也可以使用 httpCookie, useSourceIp 等
        # httpCookie:
        #   name: user-cookie
        #   ttl: 0s
  • 优点:

    • 粒度最细:可以基于任何 HTTP 头、Cookie 甚至来源 IP 进行哈希。

    • 功能强大:与其他流量管理功能(如金丝雀发布、超时、重试)无缝集成。

  • 缺点:

    • 复杂:需要部署和维护 Service Mesh(Istio、Linkerd等),学习和运维成本高。


最佳实践与重要考虑

  1. 会话数据外部化(无状态应用)

    • 这是最重要的最佳实践! 不要将会话数据存储在单个 Pod 的内存中。

    • 使用外部集中式存储来保存会话状态,例如 Redis、Memcached 或数据库。

    • 好处:

      • 即使 Pod 被销毁或重新调度,用户的会话也不会丢失。

      • 可以实现真正的水平扩展,任何 Pod 都可以处理任何用户的请求,会话保持只是为了优化(例如缓存局部性),而非必需。

  2. 选择正确的方法

    • 简单测试/内部应用:可以尝试 Service 的 sessionAffinity

    • 绝大多数生产 Web 应用:使用 Ingress 控制器(Cookie-based) 并配合 外部会话存储(如 Redis)。

    • 大型、复杂的微服务架构:考虑使用 Service Mesh。

  3. 注意 Pod 终止

    • 当 Pod 被终止时,K8s 会先将其从 Service 的 Endpoint 列表中移除,然后发送 SIGTERM 信号。确保你的应用能优雅处理终止,并在宽限期内完成正在处理的请求。

总结

 
场景推荐方法
快速测试/对会话要求不高 Service sessionAffinity: ClientIP
标准的 Web 应用(生产环境) Ingress (Nginx) Cookie Affinity + 外部 Redis 存储会话
需要极细粒度控制的微服务 Service Mesh (如 Istio)

结合 “Ingress 基于 Cookie 的会话保持” 和 “会话数据外部化”,是在 Kubernetes 中实现高可用、可扩展且有状态 Web 应用的黄金标准。

 
 
 
posted @ 2025-11-20 10:35  滴滴滴  阅读(31)  评论(0)    收藏  举报