为 Knative 服务配置会话保持

更新时间:
复制为 MD 格式

AI 推理、智能体等有状态服务中,同一客户端的请求若被路由到不同 Pod,会导致上下文丢失或会话断开。Knative 会话保持(Session Affinity)通过唯一的 Session Key 标识(来自 Cookie、Header 或 Token),可确保同一客户端的请求始终路由到同一 Pod。

结合 Knative 原生自动扩缩容,当前会话保持功能提供完整的“会话感知”生命周期管理:

  • 按需扩容:新会话到来时自动创建 Pod

  • 精准缩容:会话过期后自动删除对应 Pod

  • 11会话转发:支持将单个会话定向转发到对应 Pod

工作原理

会话保持为 Knative 服务提供以下三项核心能力:

能力

说明

一致性路由

同一客户端的请求始终转发到同一 Pod,保持有状态服务的上下文连续。

展开查看流程

  • 首次请求:Knative 为该会话分配一个 Pod,后续携带相同 Session Key 的请求均路由到这个 Pod。

  • 会话超时:会话空闲超过 session-timeout 后,Pod 自动回收,下次请求重新分配新 Pod。

  • 扩缩容基准:使用 metric: session 时,扩缩容以活跃会话数为基准(而非并发请求数),target: "1" 表示每个 Pod 只承载 1 个会话。

会话感知扩缩容

支持以活跃会话数为扩缩容基准,新会话触发 Pod 创建,会话到期触发 Pod 回收。

多存储模式

支持内存存储(默认)和 Redis 存储,适配不同规模和可靠性要求。

Knative 会话保持支持多种 Session Key 配置方式,灵活适配不同客户端接入模式。

Key

适用场景

说明

自定义 Cookie

Web 端聊天应用等

首次自动生成 UUID 并 Set-Cookie

Authorization Header

API Key / OAuth 接入

Bearer Token 的 SHA256 摘要作为 Key

X-Session-Key Header

自定义集成

客户端显式指定,适配内部系统

准备工作

操作步骤

1、创建支持会话保持的 Knative 服务

以下步骤以 1 个会话独占 1 个 Pod、空闲 5 分钟自动回收为例,适用于短时有状态任务(如 API 调试、短会话推理)。

长时 AI 推理会话中,建议将 session-timeout 调整为 30m 或更长,避免会话被提前回收。
  1. 登录容器计算服务控制台,在左侧导航栏选择集群列表

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择应用 > Knative

  3. 服务管理页面,选择命名空间default,单击使用模板创建,选择示例模板为自定义,使用以下 YAML 部署服务。

    示例使用对应 Annotation 的推荐默认值。如需自定义超时时间、Cookie 名称或每 Pod 会话数,请参见Annotation 参数说明
    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: my-sessions-per-pod
    spec:
      template:
        metadata:
          annotations:
            # 启用会话保持
            serving.knative.dev/session-affinity: "true"
            # 会话空闲超时时间,超过后 Pod 自动回收
            serving.knative.dev/session-timeout: "5m"
            # 用于会话识别的 Cookie 名称
            serving.knative.dev/session-affinity-cookie: "demo"
            # 以会话数为扩缩容指标
            autoscaling.knative.dev/metric: "session"
            # 每个 Pod 承载的最大会话数
            autoscaling.knative.dev/target: "1"
        spec:
          containers:
            - image: registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/knative-samples-helloworld-go-session:v1.0-bfdce98
  4. 等待my-sessions-per-pod部署完成后,在服务管理页面,获取访问网关地址和服务的默认域名

  5. 验证会话路由。

    不同 Cookie 值的请求应路由到不同 Pod。

    • 使用 Cookie demo=11 访问,路由到 Pod A。

      curl -i -H "Host: my-sessions-per-pod.default.example.com" http://47.xx.xx.xx \
        -H "Cookie: demo=11"

      Pod-A预期输出:

      HTTP/1.1 200 OK
      Date: Tue, 21 Apr 2026 09:57:44 GMT
      Content-Type: text/plain; charset=utf-8
      Content-Length: 77
      Connection: keep-alive
      
      Hello World!
      
      Cookies:
        Name:  demo
        Value: 11
      
      Raw Cookie Header: demo=11
    • 使用 Cookie demo=22 访问,路由到 Pod B。

      curl -i -H "Host: my-sessions-per-pod.default.example.com" http://47.xx.xx.xx \
        -H "Cookie: demo=22"
    • Pod-B预期输出:

      HTTP/1.1 200 OK
      Date: Tue, 21 Apr 2026 11:27:15 GMT
      Content-Type: text/plain; charset=utf-8
      Content-Length: 77
      Connection: keep-alive
      
      Hello World!
      
      Cookies:
        Name:  demo
        Value: 22
      
      Raw Cookie Header: demo=22
  6. 确认两个会话对应的 Pod 均已创建。

    kubectl get pods -l serving.knative.dev/service=my-sessions-per-pod

    预期输出显示 2 个 Running 状态的 Pod,分别承载 Cookie demo=11demo=22 的会话。Pod 数量与活跃会话数一致,表明会话感知扩缩容已生效。

(可选)2、配置 Redis 存储模式

生产环境多 Activator 副本场景下,需使用 Redis 存储模式保证会话一致性。在 knative-serving 命名空间的 config-defaults ConfigMap 中设置 Redis 地址。

关于两种模式的详细对比,请参见会话存储模式对比
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-defaults
  namespace: knative-serving
data:
  # 替换为实际 Redis 实例的连接地址
  session-storage-redis-addr: "r-xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379"

配置参考

Annotation 参数说明

以下为会话保持相关的全部 Annotation,可在 Knative 服务的 spec.template.metadata.annotations 中按需配置。

Annotation

说明

默认值

示例

serving.knative.dev/session-affinity

启用会话保持

false

"true"

serving.knative.dev/session-affinity-cookie

自定义 Cookie 名称

自动检测

"my-session-id"

serving.knative.dev/session-timeout

会话空闲超时

30m

"15m", "1h"

autoscaling.knative.dev/metric

扩缩容指标类型

concurrency

"session"

autoscaling.knative.dev/target

每个 Pod 承载的会话数

1(session 模式)

"1", "5"

会话存储模式对比

内存模式开箱即用,更适用于开发测试;Redis 模式支持多 Activator 副本,更适用于生产环境。

维度

内存模式(默认)

Redis 模式

部署复杂度

零依赖,开箱即用

需阿里云 Redis 实例

多 Activator 支持

不支持

完全支持

一致性

最终一致

强一致

Activator 重启后会话

可能丢失

即时恢复

适用场景

单 Activator,可容忍部分会话丢失

生产环境(推荐)

典型场景:AI 推理会话(11 隔离)

每个推理会话独占一个 GPU Pod,会话期间 Pod 不释放。session-timeout: 30m 表示用户 30 分钟无操作后 GPU Pod 才释放,避免频繁冷启动影响响应速度,同时防止长时间空闲占用 GPU 资源产生不必要费用。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: ai-inference
spec:
  template:
    metadata:
      annotations:
        serving.knative.dev/session-affinity: "true"
        # 会话空闲 30 分钟后自动回收 GPU Pod
        serving.knative.dev/session-timeout: "30m"
        # 用于会话识别的 Cookie 名称
        serving.knative.dev/session-affinity-cookie: "demo"
        autoscaling.knative.dev/metric: "session"
        # 每个 GPU Pod 仅承载 1 个推理会话
        autoscaling.knative.dev/target: "1"
    spec:
      containers:
      - image: registry-vpc.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:73fbdd56
        resources:
          limits:
            nvidia.com/gpu: "1"

常见问题

内存模式和 Redis 模式如何选择?

根据部署规模和可靠性要求选择合适的存储模式。

场景

推荐模式

开发测试

内存模式

生产环境和 11 隔离

Redis 模式

多 Activator 副本

Redis 模式

需要会话持久化

Redis 模式

设置了会话保持但没有生效怎么办?

检查以下项:

  1. serving.knative.dev/session-affinity: "true" 是否设置在 Revision 的 spec.template.metadata.annotations 中。

  2. 请求中是否携带了可识别的 Session Key 。

  3. 使用自定义 Cookie 时,session-affinity-cookie 的值是否与请求 Cookie 名称一致。

  4. 查看 Activator 日志:kubectl -n knative-serving logs -l app=activator -c activator

一个 Knative 服务可以同时使用 sessionconcurrency 指标吗?

不可以。sessionconcurrency/RPS 扩缩容指标互斥,一个服务只能配置其中一种。

灰度发布与会话保持如何协同工作?

两者是正交关系:流量首先按配置的百分比分发到不同 Revision,每个 Revision 内独立维持会话保持。

维度

作用域

目的

流量比例

跨 Revision

控制灰度发布的流量分配

会话保持

Revision 内

保证同一客户端在同一 Revision 的 Pod 上保持一致