You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Kubernetes Load Balancer实现粘性会话?

Kubernetes WebSocket(SignalR)粘性会话配置指南

问题背景

在Kubernetes多Pod环境中部署基于WebSocket(React+SignalR)的服务时,出现粘性会话失效问题:SignalR的协商请求与后续WebSocket连接请求未路由至同一Pod,导致连接无法建立。修改配置后仅偶尔成功,实为请求碰巧落在同一Pod的巧合,需明确正确的粘性会话配置方式。

初始配置

Deployment (deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: lct-api-deployment
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: lct-api
  template:
    metadata:
      labels:
        app: lct-api
    spec:
      containers:
        - name: lct-api
          image: localhost:7000/lct:latest
          imagePullPolicy: Always
          resources:
            requests:
                memory: "200Mi"
                cpu: "200m"
            limits:
                memory: "300Mi"
                cpu: "350m"

Service (service.yaml)

apiVersion: v1
kind: Service
metadata:
  name: lct-api-service
  annotations:
      service.beta.kubernetes.io/do-loadbalancer-protocol: "http"
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-type: "cookies"
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-cookie-name: "example"
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-cookie-ttl: "60"
spec:
  selector:
    app: lct-api
  type: LoadBalancer
  sessionAffinity: ClientIP
  externalTrafficPolicy: Local
  ports:
    - protocol: TCP
      port: 6008
      targetPort: 80

修改后配置(仍未解决问题)

# Service 部分
apiVersion: v1
kind: Service
metadata:
  name: lct-api-service
  annotations:
      service.beta.kubernetes.io/do-loadbalancer-protocol: "http"
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-type: "cookies"
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-cookie-name: "example"
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-cookie-ttl: "60"
spec:
  selector:
    app: lct-api
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
    - protocol: TCP
      port: 6008
      targetPort: 80

# Deployment 部分
apiVersion: apps/v1
kind: Deployment
metadata:
  name: lct-api
spec:
  replicas: 5
  selector: 
    matchLabels:
      app: lct-api
  template:
    metadata:
      labels:
        app: lct-api
    spec:
      containers:
        - name: lct
          image: localhost:7000/lct:latest
          imagePullPolicy: Always
          resources:
            requests:
                memory: "200Mi"
                cpu: "200m"
            limits:
                memory: "300Mi"
                cpu: "350m"
      affinity:
        podAntiAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchLabels:
                        app: lct
                  topologyKey: kubernetes.io/hostname

问题分析

  1. 粘性策略冲突:初始Service同时配置了DigitalOcean LB的Cookie粘性注解和Kubernetes原生的sessionAffinity: ClientIP,两者层级不同(LB层 vs kube-proxy层),可能导致路由逻辑混乱,无法保证请求稳定路由至同一Pod。
  2. 标签不匹配:修改后的Deployment中,Pod反亲和性规则的matchLabels: app: lct与Pod实际标签app: lct-api不一致,导致反亲和性未生效,但此问题并非粘性会话失效的直接原因。
  3. WebSocket路由兼容性:SignalR依赖协商请求与WebSocket连接请求共享同一上下文,LB需正确识别HTTP Upgrade头并保持Cookie粘性,若LB配置未正确处理WebSocket协议转换,会导致粘性失效。

正确配置方案

1. 统一粘性会话策略

优先使用Load Balancer层的Cookie粘性(适配HTTP/WebSocket场景),移除Kubernetes原生sessionAffinity配置,避免策略冲突。

2. 修正Service配置

apiVersion: v1
kind: Service
metadata:
  name: lct-api-service
  annotations:
      # 明确LB协议为HTTP,支持WebSocket Upgrade
      service.beta.kubernetes.io/do-loadbalancer-protocol: "http"
      # 启用Cookie粘性会话
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-type: "cookies"
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-cookie-name: "LCT-SESSION"
      # 设置Cookie有效期,根据业务需求调整
      service.beta.kubernetes.io/do-loadbalancer-sticky-sessions-cookie-ttl: "1800"
spec:
  selector:
    app: lct-api
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
    - protocol: TCP
      port: 6008
      targetPort: 80

3. 修正Deployment标签匹配问题

将Pod反亲和性规则的标签修正为与Pod实际标签一致:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: lct-api
spec:
  replicas: 5
  selector: 
    matchLabels:
      app: lct-api
  template:
    metadata:
      labels:
        app: lct-api
    spec:
      containers:
        - name: lct
          image: localhost:7000/lct:latest
          imagePullPolicy: Always
          resources:
            requests:
                memory: "200Mi"
                cpu: "200m"
            limits:
                memory: "300Mi"
                cpu: "350m"
      affinity:
        podAntiAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchLabels:
                        # 修正为Pod实际标签
                        app: lct-api
                  topologyKey: kubernetes.io/hostname

4. 额外优化建议

  • SignalR配置适配:确保客户端SignalR配置中启用withAutomaticReconnect(),并在服务端配置允许跨域(若前端与服务端域名不同),避免因跨域导致Cookie无法携带。
  • LB健康检查:配置LB的健康检查路径(如/health),确保LB仅将请求转发至健康Pod,避免路由至异常实例。

验证粘性会话生效

  1. Pod标识返回:在服务端接口中添加返回当前Pod名称的接口(如/api/pod-name),客户端先发送SignalR协商请求,再调用该接口,验证两次请求返回的Pod名称一致。
  2. Cookie检查:在浏览器开发者工具的Application标签中,查看是否存在配置的LCT-SESSION Cookie,且后续WebSocket连接请求携带该Cookie。
  3. 日志验证:查看各Pod的访问日志,确认同一客户端的协商请求与WebSocket连接请求均落在同一Pod上。

内容的提问来源于stack exchange,提问作者kenik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:53:17