
# Kthena ModelServing
随着大语言模型（LLM）参数规模的指数级增长，单一计算节点的显存与算力瓶颈日益凸显。为突破物理资源限制，业界正加速向PD分离（Prefill-Decode Disaggregation）与大/小模型混部等创新架构演进。这一变革促使推理任务的执行模式从单Pod独享转向多Pod协作的分布式形态。
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
多Pod协作在推理任务中的核心定位：无论是传统的单节点同质化部署，还是复杂的PD分离架构，多Pod协作已成为提升算力利用率、保障端到端延迟（E2E Latency）以及支撑超大规模并行（TP/PP）的必然选择。
Kthena ModelServing专为云原生环境下的LLM推理设计，提供声明式的生命周期管理。其核心目标是突破Kubernetes原生负载（如Deployment/StatefulSet）在拓扑感知、原子调度及复杂推理工作流编排上的局限，为PD分离等高级模式构建坚实底座。
#### 架构设计
为解决Kubernetes原生资源（如Deployment或StatefulSet）在处理多角色协作场景下的局限性，Kthena采用ModelServing → ServingGroup → Role的三层结构，每一层承担不同的职责，共同协作以实现高性能、可扩展的推理服务。
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002555468265.png "点击放大")
表1架构层级与职责 
| 层级           | 管理对象           | 核心职责                                                                        |
|:---|:---|:---|
| ModelServing | ServingGroup集合 | 作为全生命周期的统一控制平面，负责维护全局配置一致性，实现版本控制（Revision），提供推理集群的状态查询能力。提供统一接口，管理全局副本和版本。 |
| ServingGroup | Role集合         | 作为推理服务的独立功能单元，是连接顶层控制与底层执行的逻辑分组。包含完成一次端到端推理所需的所有角色，确保推理逻辑的完整性和独立性。          |
| Role         | Pod集合          | 作为最小的功能执行单元，负责具体的计算任务，由一组具有确定性编号的Pod组成。执行特定的计算或分发任务，例如Prefill和Decode角色的执行。  |
   
在Role层级内部，Kthena采用双Pod模板设计，以支持分布式推理场景中的职责解耦，并通过定义特定的环境变量对Pod进行精细化控制和协作。
- Entry Pod：充当流量入口与任务协调器 。负责接收外部请求并分发计算任务。
- Worker Pod：计算执行单元。专注于执行实际的张量计算与推理任务。 为便于客户在业务中识别Pod的角色身份，控制器将自动为Entry和Worker Pod注入以下关键环境变量。
  表2关键环境变量 
  | 环境变量          | 说明                                                  |
  |:---|:---|
  | GROUP_SIZE    | 定义当前Role实例中Pod的总数，用于协调Pod之间的协作逻辑。                   |
  | ENTRY_ADDRESS | Entry Pod的内网地址（格式为Headless Service），用于Worker Pod通信。 |
  | WORKER_INDEX  | 每个Worker Pod在当前Role实例中的唯一索引，用于身份识别与任务分配。            |
     
  
 
#### 前提条件
- 已创建CCE Standard/Turbo集群，集群版本建议为v1.29及以上。
- 已安装1.21.7及以上版本的Volcano插件：在CCE控制台"插件中心"中搜索并安装 "Volcano调度器" 插件。 若使用弹性伸缩功能，需安装1.22.5及以上版本的Volcano插件。
  
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/caution_3.0-zh-cn.png)
在使用Volcano作为调度器时，建议将集群中所有相关工作负载统一[使用Volcano调度](https://support.huaweicloud.com/usermanual-cce/cce_10_0722.html)，以避免调度冲突。
#### 约束与限制
- ModelServing依赖Volcano调度器插件，若集群未安装该插件，相关功能将无法生效。
- 当前CCE控制台暂不支持图形化创建ModelServing，需通过kubectl或YAML文件进行部署。
- 若使用minRoleReplicas，需确保集群资源充足，否则可能导致作业长期处于Pending状态。
 
 #### 关键特性解析
#### 作业调度（Gang Scheduling）
Kthena深度集成了Volcano调度器，支持"All or Nothing"的原子调度逻辑，有效避免了在分布式推理组中由于部分Pod无法就绪而导致的调度死锁和资源浪费问题。其核心思想为检查Job下的Pod已调度数量是否满足了最小运行数量，当Job的最小运行数量得到满足时，为Job下的所有Pod执行调度动作，否则不执行。
系统通过minMember计算每个ModelServing实例所需的最小Pod数，保障调度的高效与可控。minMember计算逻辑如下：
- 默认模式：若未配置minRoleReplicas，系统将基于所有Role的副本数进行统一计算。
  ```
  minMember = replicas × role.replicas × (1 + role.workerReplicas)
  ```
  
- 精细化模式：若配置了minRoleReplicas，系统将根据索引逻辑（从0至minRoleReplicas\[roleName\] - 1），为每个Role独立计算其必须就绪的最小Pod数量，从而支持更灵活的启动策略。 配置示例：在本示例中，prefill和decode两个Role各有4个副本，但系统将确保至少2个副本成功调度和就绪，从而提升整体调度效率和资源利用率。
  ```
  apiVersion: workload.serving.volcano.sh/v1alpha1
  kind: ModelServing
  metadata:
    name: sample
    namespace: default
  spec:
    schedulerName: volcano
    replicas: 1  # servingGroup replicas
    template:
      restartGracePeriodSeconds: 60
      gangPolicy:
        minRoleReplicas:
          prefill: 2
          decode: 2
      roles:
        - name: prefill
          replicas: 4 
          # ... additional role pod configuration
        - name: decode
          replicas: 4
          # ... additional role pod configuration
  ```
  
 
#### 滚动更新（Rolling Update）
Kthena提供了支持基于Partition参数的顺序滚动更新（Rolling Update）的功能。更新策略遵循从最高序号副本（Last Pod）开始的原则，以确保整个更新流程的有序性和稳定性。本文以4副本（R-0至R-3）为例描述状态迁移：
1. 初始状态：所有副本均为旧版本（R-0至R-3均为就绪状态）。
2. 更新启动：首先重建序号最高的R-3（状态：重启中）。
3. 就绪切换：R-3就绪后，开始更新R-2（状态：R-3新版，R-2重启中）。
4. 持续推进：依次更新R-1、R-0。
5. 更新完成：所有副本均已完成更新（R-0至R-3均为就绪状态）。
Partition参数用于设置滚动更新的边界范围。只处理索引值大于或等于Partition的副本。控制器仅在当前副本状态由Pending变为Running，并通过就绪检查后，才会推进到下一个序号副本的更新。
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/caution_3.0-zh-cn.png)
由于滚动更新需要在新副本running后才会处理下一个副本，如果系统资源不足，导致第一个滚动副本都无法正常启动和就绪，整个更新过程将被阻塞。因此，建议提前预留足够的资源，确保第一个副本能够顺利启动和进入就绪状态，从而避免滚动更新停滞。
#### 重启策略（Recovery Policy）
该策略定义了当Pod发生故障时，模型的粒度控制与行为模式：
- ServingGroupRecreate：以ServingGroup为粒度控制。若组内任意一个Pod发生故障，系统将重建该ServingGroup下的所有Pod，以确保整个服务组的高度一致性。
- RoleRecreate：以Role为粒度控制。若某个Role下的任意Pod发生故障，系统将重建该Role下的所有Pod。 配置示例：以下YAML展示了如何定义ModelServing资源，其中recoveryPolicy配置为RoleRecreate。
  ```
  apiVersion: workload.serving.volcano.sh/v1alpha1
  kind: ModelServing
  metadata:
    name: sample
    namespace: default
  spec:
    schedulerName: volcano
    replicas: 1  # servingGroup replicas
    recoveryPolicy: RoleRecreate
    template:
    # ...
  ```
  
 
#### 拓扑亲和调度
Kthena通过Volcano实现网络拓扑感知调度。为了屏蔽数据中心网络类型的差异，Volcano定义了一个新的CRD，即HyperNode，并提供了一个标准化的API接口。HyperNode代表一个网络拓扑性能域，通常映射到交换机或ToR（Top of Rack）设备，多个HyperNode以层级结构连接，形成树状拓扑，详情请参见[网络拓扑感知调度概述](https://support.huaweicloud.com/usermanual-cce/cce_10_1126.html)。
Kthena ModelServing提供了用于配置ServingGroup及Role的网络拓扑约束字段。以下示例配置表明：
- ServingGroup：通过groupPolicy约束，允许部署在tier 2或其下属的叶子节点中。
- Role：通过rolePolicy约束，允许部署在tier 1或其下属的叶子节点中。
```
spec:
  replicas: 1  # servingGroup replicas
  template:
    networkTopology:
      rolePolicy:
        mode: hard
        highestTierAllowed: 1
      groupPolicy:
        mode: hard
        highestTierAllowed: 2
```
#### Eviction保护（Eviction Protection）
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
Eviction保护需Volcano插件版本不低于1.22.24，并在插件YAML中开启kthena.enable_evictionWebhook: true后方可生效。
Kthena提供面向ModelServing推理拓扑的驱逐保护能力，在节点维护、节点缩容、kubectl drain等主动驱逐场景下，防止关键推理实例被过量驱逐，保障在线推理服务的最小可用性。
Kubernetes原生的PodDisruptionBudget（PDB）仅支持基于Pod数量的保护粒度，难以适配ModelServing的多层结构。ModelServing采用ModelServing**→** ServingGroup**→**Role的层级模型，尤其在大语言模型（LLM）推理场景中，单Pod通常无法代表一个完整可用的推理实例。在PD分离、分布式推理及多Role协作等架构下，需以ServingGroup或Role为维度评估服务可用性。
Kthena支持两种保护粒度：
- ServingGroup级保护：以ServingGroup为保护单元，确保可用ServingGroup数量不低于minAvailable，保障整体推理服务完整性。
- Role级保护：以Role为保护单元，分别保障Prefill、Decode等关键Role的可用实例数不低于设定阈值，避免核心推理阶段受损。
工作机制：当系统接收到Pod驱逐请求时，Kthena会识别目标Pod所属的ModelServing、ServingGroup及Role，并结合已配置的保护策略进行预判断。若本次驱逐后，可用实例数仍能满足最小可用性要求，则允许驱逐；否则将拒绝该驱逐请求。
**示例配置**
- ServingGroup级保护 本示例中，replicas: 3表示ModelServing包含3个ServingGroup，minAvailable: 2表示系统需保障至少2个ServingGroup处于可用状态。在节点维护等主动驱逐场景下，系统最多允许1个ServingGroup不可用。若继续驱逐将导致可用ServingGroup数量低于minAvailable阈值，Kthena将拒绝该Eviction请求。
  ```
  apiVersion: workload.serving.volcano.sh/v1alpha1
  kind: ModelServing
  metadata:
    name: sample
    namespace: default
  spec:
    schedulerName: volcano
    replicas: 3
    rolloutStrategy:
      evictionStrategy:
        protectionLevel: ServingGroup
        minAvailable: 2
  ```
  
- Role级保护 本示例分别对prefill和decode两个关键Role的可用实例数进行保护。即便所属ServingGroup中仍有其他副本在线，只要本次驱逐将导致任一受保护Role的可用实例数低于配置阈值，Kthena都将拒绝该Eviction请求。
  ```
  apiVersion: workload.serving.volcano.sh/v1alpha1
  kind: ModelServing
  metadata:
    name: sample
    namespace: default
  spec:
    schedulerName: volcano
    replicas: 2
    template:
      roles:
        - name: prefill
          replicas: 2
        - name: decode
          replicas: 3
    rolloutStrategy:
      evictionStrategy:
        protectionLevel: Role
        roleMinAvailable:
          prefill: 1
          decode: 2
  ```
  
**配置建议**
minAvailable和roleMinAvailable均支持绝对值和百分比两种配置形式，例如：minAvailable: 2或minAvailable: 80%。
- 普通多副本推理服务：建议使用ServingGroup级保护，保障完整推理实例数量。
- PD分离或多Role协作场景：建议使用Role级保护，分别保障Prefill、Decode等关键Role的可用性。
- 允许节点维护期间少量实例被驱逐：minAvailable应小于总副本数。
- 业务容量随自动扩缩容动态变化：建议使用百分比形式配置保护阈值。
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/caution_3.0-zh-cn.png)
该功能参考Kubernetes原生PDB的使用机制，仅保护Pod驱逐场景，不保护Pod删除场景。需特别注意的是通过节点打污点触发的Pod驱逐，实际执行的是删除动作，因此该机制无法保护节点打污点场景。
#### 使用示例：ModelServing负载完整用例（以Nginx负载为例）
本示例包含prefill和decode两个Role，其中prefill角色有2个副本，每个副本包含1个Entry和1个Worker，共两个Pod；Decode角色有3个副本，每个副本包含1个Entry和2个Worker，共3个Pod。关于其他调度特性的描述，请查看[关键特性解析]。
```
apiVersion: workload.serving.volcano.sh/v1alpha1
kind: ModelServing
metadata:
  name: sample
  namespace: default
spec:
  schedulerName: volcano
  replicas: 1  # servingGroup replicas
  recoveryPolicy: RoleRecreate # 重启策略
  template:
    restartGracePeriodSeconds: 60
    gangPolicy: # Gang Scheduling策略
      minRoleReplicas:
        prefill: 2
        decode: 1
    roles:
      - name: prefill
        replicas: 2       # role replicas
        entryTemplate:
          spec:
            containers:
              - name: worker
                image: nginx:latest
                resources:
                  limits:
                    cpu: 250m
                    memory: 512Mi
                  requests:
                    cpu: 250m
                    memory: 512Mi
            imagePullSecrets:
            - name: default-secret
        workerReplicas: 1
        workerTemplate:
          spec:
            containers:
              - name: worker
                image: nginx:latest
                resources:
                  limits:
                    cpu: 250m
                    memory: 512Mi
                  requests:
                    cpu: 250m
                    memory: 512Mi
            imagePullSecrets:
            - name: default-secret
      - name: decode
        replicas: 3  # role replicas
        entryTemplate:
          spec:
            containers:
              - name: worker
                image: nginx:latest
                resources:
                  limits:
                    cpu: 250m
                    memory: 512Mi
                  requests:
                    cpu: 250m
                    memory: 512Mi
            imagePullSecrets:
            - name: default-secret
        workerReplicas: 2
        workerTemplate:
          spec:
            containers:
              - name: worker
                image: nginx:latest
                resources:
                  limits:
                    cpu: 250m
                    memory: 512Mi
                  requests:
                    cpu: 250m
                    memory: 512Mi
            imagePullSecrets:
            - name: default-secret
```
#### 使用示例：自动扩缩容用例（以vllm负载为例）
Kthena采用策略与目标解耦的设计模式，通过两个核心自定义资源（CRD）实现弹性伸缩的灵活配置：
- **AutoscalingPolicy**：定义扩缩容策略，包含监控指标、目标值、稳定/紧急模式配置、观测窗口等参数。
- **AutoscalingPolicyBinding**：定义伸缩目标，将策略绑定到具体的ModelServing或Role，并设置副本数限制、指标拉取端点等运行约束。
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/caution_3.0-zh-cn.png)
Pod需以Prometheus兼容格式（例如，vLLM内置的/metrics端点）暴露业务指标，Autoscaler将定期从此端点抓取指标以驱动扩缩容决策。
#### AutoscalingPolicy示例
以下示例展示了如何以vllm:num_requests_waiting为指标，对vllm-modelserving负载进行以ServingGroup或Role级别的扩缩配置。
```
apiVersion: workload.serving.volcano.sh/v1alpha1
kind: AutoscalingPolicy
metadata:
  name: vllm-scaling-policy
spec:
  metrics:
  - metricName: vllm:num_requests_waiting 
    targetValue: 100 
  tolerancePercent: 10 
  behavior:
    scaleUp:
      panicPolicy:
        panicThresholdPercent: 150
        panicModeHold: 5m
      stablePolicy:
        stabilizationWindow: 1m
        period: 30s
    scaleDown:
      stabilizationWindow: 5m
      period: 1m
```
| **字段**                | 说明                                                             |
|:---|:---|
| metricName            | 从Pod/metrics端点抓取的指标名称。                                         |
| targetValue           | 每个副本期望的指标平均值。观测值持续超过此值将触发扩容。                                   |
| tolerancePercent      | 容差百分比。例如，10%表示指标在\[90, 110\]范围内时不触发伸缩，避免抖动。                    |
| scaleUp.panicPolicy   | 紧急扩容策略，用于流量激增时快速响应。                                            |
| panicThresholdPercent | 紧急模式的触发阈值（基于targetValue）。150%表示指标达到150 (100 \* 1.5) 时立即进入紧急模式。 |
| panicModeHold         | 紧急模式保持时长，防止频繁退出紧急模式并误缩容。                                       |
| scaleUp.stablePolicy  | 标准的稳定扩容策略，基于持续趋势决策。                                            |
| stabilizationWindow   | 稳定窗口时长。例如，1m表示必须连续1分钟观测到指标高于目标值，才执行扩容，防止误触发。                   |
| period                | 评估周期，Autoscaler按此周期计算指标并决策。                                    |
| scaleDown             | 缩容配置，通常设较长的stabilizationWindow以避免Pod频繁启停。                      |
   
#### AutoscalingPolicyBinding示例
- 绑定到整个ModelServing（ServingGroup级别）
  ```
  apiVersion: workload.serving.volcano.sh/v1alpha1
  kind: AutoscalingPolicyBinding
  metadata:
    name: vllm-scaling-binding
  spec:
    policyRef:
      name: vllm-scaling-policy
    homogeneousTarget:
      target:
        targetRef:
          kind: ModelServing
          name: vllm-modelserving
          namespace: default
        metricEndpoint:
          uri: "/metrics"
          port: 8000
      minReplicas: 2
      maxReplicas: 8
  ```
  
  | **字段**            | **描述**                              |
  |:---|:---|
  | policyRef         | 引用包含伸缩逻辑（指标、阈值等）的AutoscalingPolicy。 |
  | homogeneousTarget | 当伸缩单实例类型时使用。包含目标识别信息和伸缩约束。          |
  | targetRef         | 指定要伸缩的顶层资源。                         |
  | minReplicas       | 该ServingGroup允许的最小副本数。              |
  | maxReplicas       | 该ServingGroup允许的最大副本数。              |
     
  
- 绑定到ModelServing中的特定Role（Role级别）
  ```
  apiVersion: workload.serving.volcano.sh/v1alpha1
  kind: AutoscalingPolicyBinding
  metadata:
    name: vllm-scaling-binding
  spec:
    policyRef:
      name: vllm-scaling-policy
    homogeneousTarget:
      target:
        subTargets:
          kind: Role
          name: decode
        targetRef:
          kind: ModelServing
          name: vllm-modelserving
          namespace: default
        metricEndpoint:
          uri: "/metrics"
          port: 8000
      minReplicas: 2
      maxReplicas: 8
  ```
  
  | **字段**          | **描述**                           |
  |:---|:---|
  | subTargets      | 可选。用于对目标内部的特定组件进行精细化伸缩。          |
  | subTargets.kind | 子目标类型，此处固定为Role。                 |
  | subTargets.name | ModelServing中定义的角色名称（例如，decode）。 |
  | minReplicas     | 该特定Role允许的最小副本数。                 |
  | maxReplicas     | 该特定Role允许的最大副本数。                 |
     
  
 
