返回归档
🌑knative

Knative Service 多版本管理指南

文章目录

本文档说明如何使用 Knative Service 管理 APP 的多个版本(Revision),通过 Tag 和 Header 实现版本路由。

概念映射

业务概念 Knative 概念 说明
APP Knative Service 一个应用对应一个 Knative Service
APP 版本 Revision 每次更新 Service 的 template 会生成新的 Revision
版本标识 Tag 通过 traffic 配置中的 tag 字段标识版本

请求方式

所有版本共用同一个 Host,通过 Knative-Serving-Tag Header 区分版本:

# 访问 v1 版本
curl -H "Knative-Serving-Tag: v1" -H "Host: echo-server.default.example.com" http://<gateway-ip>

# 访问 v2 版本
curl -H "Knative-Serving-Tag: v2" -H "Host: echo-server.default.example.com" http://<gateway-ip>

# 不带 Tag Header,走默认流量分配(percent 配置)
curl -H "Host: echo-server.default.example.com" http://<gateway-ip>

场景一:创建新 APP

创建一个新的 Knative Service,初始版本标记为 v1。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: echo-server
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "0"
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest
          ports:
            - containerPort: 8080
          env:
            - name: TARGET
              value: "World"
  traffic:
    - latestRevision: true
      percent: 100
      tag: v1

应用后查看 Revision:

kubectl get revisions -l serving.knative.dev/service=echo-server

输出示例:

NAME                  CONFIG NAME   READY   REASON
echo-server-00001     echo-server   True

场景二:创建 APP 新版本

更新 Service 的 template 并添加新的 Tag。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: echo-server
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "0"
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest
          ports:
            - containerPort: 8080
          env:
            - name: TARGET
              value: "Knative v2"
  traffic:
    # 新版本 v2,暂不分配默认流量(staging)
    - latestRevision: true
      percent: 0
      tag: v2
    # 旧版本 v1,保持 100% 默认流量
    - revisionName: echo-server-00001
      percent: 100
      tag: v1

此时:

  • 不带 Header 的请求 → 100% 路由到 v1
  • Knative-Serving-Tag: v2 的请求 → 路由到 v2
  • Knative-Serving-Tag: v1 的请求 → 路由到 v1

场景三:调整流量分配

将 v2 版本设为主版本,v1 作为备用。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: echo-server
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "0"
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest
          ports:
            - containerPort: 8080
          env:
            - name: TARGET
              value: "Knative v2"
  traffic:
    # v2 成为主版本
    - revisionName: echo-server-00002
      percent: 100
      tag: v2
    # v1 保留但不分配默认流量
    - revisionName: echo-server-00001
      percent: 0
      tag: v1

场景四:停用某个版本(maxScale=0)

将某个版本的最大副本数设为 0,使其不再接收请求。

方法:通过 Revision 级别的 annotation 无法直接修改已创建的 Revision。需要通过以下方式实现:

方案 A:从 traffic 中移除该版本

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: echo-server
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "0"
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest
          ports:
            - containerPort: 8080
          env:
            - name: TARGET
              value: "Knative v2"
  traffic:
    # 只保留 v2
    - revisionName: echo-server-00002
      percent: 100
      tag: v2
    # v1 从 traffic 中移除,不再可访问

移除后,v1 版本的 Pod 会自动缩容到 0(scale to zero)。

方案 B:使用 PodAutoscaler 强制缩容

如果需要保留 Tag 但强制停机,可以直接 patch 对应 Revision 的 PodAutoscaler:

# 查找 v1 对应的 PodAutoscaler
kubectl get pa -l serving.knative.dev/revision=echo-server-00001

# 设置 maxScale 为 0(需要 Knative 支持,部分版本可能不支持)
kubectl annotate revision echo-server-00001 \\
  autoscaling.knative.dev/maxScale="0" --overwrite

注意:Revision 的 annotation 在创建后通常不可变。更可靠的方式是从 traffic 中移除。


场景五:删除某个版本

5.1 先从 traffic 中移除

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: echo-server
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "0"
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest
          ports:
            - containerPort: 8080
          env:
            - name: TARGET
              value: "Knative v2"
  traffic:
    - revisionName: echo-server-00002
      percent: 100
      tag: v2

5.2 删除 Revision

kubectl delete revision echo-server-00001

场景六:删除整个 APP

删除 Knative Service 会自动清理所有关联的 Revision、Configuration、Route 等资源。

kubectl delete ksvc echo-server -n default

验证清理完成:

kubectl get revisions -l serving.knative.dev/service=echo-server
kubectl get configurations -l serving.knative.dev/service=echo-server
kubectl get routes -l serving.knative.dev/service=echo-server

完整示例:三版本共存

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: echo-server
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "0"
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest
          ports:
            - containerPort: 8080
          env:
            - name: TARGET
              value: "Knative v3"
  traffic:
    # v3 - 最新版本,灰度 10%
    - latestRevision: true
      percent: 10
      tag: v3
    # v2 - 主力版本,承担 90% 流量
    - revisionName: echo-server-00002
      percent: 90
      tag: v2
    # v1 - 旧版本,仅通过 Tag 访问,不分配默认流量
    - revisionName: echo-server-00001
      percent: 0
      tag: v1

访问方式:

# 按比例分配(90% v2, 10% v3)
curl -H "Host: echo-server.default.example.com" http://<gateway-ip>

# 指定访问 v1
curl -H "Knative-Serving-Tag: v1" -H "Host: echo-server.default.example.com" http://<gateway-ip>

# 指定访问 v2
curl -H "Knative-Serving-Tag: v2" -H "Host: echo-server.default.example.com" http://<gateway-ip>

# 指定访问 v3
curl -H "Knative-Serving-Tag: v3" -H "Host: echo-server.default.example.com" http://<gateway-ip>

操作速查表

操作 方法
创建新 APP 创建 Knative Service,template 中定义容器,traffic 中设置 tag
创建新版本 更新 template,在 traffic 中添加新 tag 指向 latestRevision
停用版本(保留) 从 traffic 中移除该 revisionName,或设置 percent: 0 且不带 tag
删除版本 先从 traffic 移除,再 kubectl delete revision <name>
删除整个 APP kubectl delete ksvc <name>
灰度发布 调整 traffic 中各版本的 percent 比例
回滚 将旧版本的 percent 设为 100,新版本设为 0