Kthena ModelServing
随着大语言模型(LLM)参数规模的指数级增长,单一计算节点的显存与算力瓶颈日益凸显。为突破物理资源限制,业界正加速向PD分离(Prefill-Decode Disaggregation)与大/小模型混部等创新架构演进。这一变革促使推理任务的执行模式从单Pod独享转向多Pod协作的分布式形态。
多Pod协作在推理任务中的核心定位:无论是传统的单节点同质化部署,还是复杂的PD分离架构,多Pod协作已成为提升算力利用率、保障端到端延迟(E2E Latency)以及支撑超大规模并行(TP/PP)的必然选择。
Kthena ModelServing专为云原生环境下的LLM推理设计,提供声明式的生命周期管理。其核心目标是突破Kubernetes原生负载(如Deployment/StatefulSet)在拓扑感知、原子调度及复杂推理工作流编排上的局限,为PD分离等高级模式构建坚实底座。
架构设计
为解决Kubernetes原生资源(如Deployment或StatefulSet)在处理多角色协作场景下的局限性,Kthena采用ModelServing → ServingGroup → Role的三层结构,每一层承担不同的职责,共同协作以实现高性能、可扩展的推理服务。
| 层级 | 管理对象 | 核心职责 |
|---|---|---|
| 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.5及以上版本的Volcano插件:在CCE控制台“插件中心”中搜索并安装 “Volcano调度器” 插件。
在使用Volcano作为调度器时,建议将集群中所有相关工作负载统一使用Volcano调度,以避免调度冲突。
约束与限制
- 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
- 默认模式:若未配置minRoleReplicas,系统将基于所有Role的副本数进行统一计算。
- 滚动更新(Rolling Update)
Kthena提供了支持基于Partition参数的顺序滚动更新(Rolling Update)的功能。更新策略遵循从最高序号副本(Last Pod)开始的原则,以确保整个更新流程的有序性和稳定性。本文以4副本(R-0至R-3)为例描述状态迁移:
- 初始状态:所有副本均为旧版本(R-0至R-3均为就绪状态)。
- 更新启动:首先重建序号最高的R-3(状态:重启中)。
- 就绪切换:R-3就绪后,开始更新R-2(状态:R-3新版,R-2重启中)。
- 持续推进:依次更新R-1、R-0。
- 更新完成:所有副本均已完成更新(R-0至R-3均为就绪状态)。
Partition参数用于设置滚动更新的边界范围。只处理索引值大于或等于Partition的副本。控制器仅在当前副本状态由Pending变为Running,并通过就绪检查后,才会推进到下一个序号副本的更新。
由于滚动更新需要在新副本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: # ...
使用示例: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,并设置副本数限制、指标拉取端点等运行约束。
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允许的最大副本数。