Updated on 2026-06-16 GMT+08:00

Kthena ModelServing

As the parameter scale of LLMs grows exponentially, the memory and compute bottlenecks of a single compute node become increasingly prominent. To break through the limits of physical resources, the industry is rapidly evolving towards innovative architectures such as prefill-decode disaggregation and hybrid deployment of large and small models. This transformation shifts the execution of inference tasks from a mode where only a single pod is used to a mode where multiple distributed pods collaborate.

Core positioning of multi-pod collaboration in inference tasks: Regardless of the traditional single-node homogeneous deployment or a complex prefill-decode disaggregation architecture, multi-pod collaboration has become an inevitable choice for improving compute utilization, ensuring end-to-end latency, and supporting ultra-large-scale parallelism (such as tensor parallelism or pipeline parallelism).

Kthena ModelServing is designed specifically for LLM inference in cloud native environments and provides declarative lifecycle management. Its core objective is to overcome the limitations of Kubernetes native workloads (such as Deployments and StatefulSets) in topology awareness, atomic scheduling, and complex inference workflow orchestration, thereby laying a solid foundation for advanced modes such as prefill-decode disaggregation.

Architecture Design

To overcome the limitations of Kubernetes native resources (such as Deployments or StatefulSets) in multi-role collaboration scenarios, Kthena adopts a three-layer architecture: ModelServing → ServingGroup → Role. Each layer serves a distinct function, and they collaborate to deliver high-performance, scalable inference services.

Table 1 Architecture layers and functions

Layer

Managed Object

Function

ModelServing

A set of ServingGroups

As a control plane throughout the lifecycle, it maintains global configuration consistency, implements revision control, and provides the capability to query the status of inference clusters. It provides a unified interface to manage global replicas and revisions.

ServingGroup

A set of Roles

As an independent functional unit of the inference services, it is a logical group that connects the top-level control and bottom-level execution. It contains all roles required to complete an end-to-end inference, ensuring the integrity and independence of the inference logic.

Role

A set of pods

As the smallest functional execution unit, it handles specific computing tasks and consists of a group of pods with deterministic IDs. It executes specific computing or distribution tasks, such as the execution of prefill and decode roles.

At the Role layer, Kthena uses a dual-pod template design to support responsibility decoupling in distributed inference scenarios and to implement refined control and collaboration of pods through the definition of specific environment variables.

  • Entry pod: acts as the traffic ingress and task coordinator. It receives external requests and distributes computing tasks.
  • Worker pod: serves as a compute execution unit. It executes actual tensor computation and inference tasks.

    To help you identify the roles of pods in your services, the controller automatically injects the following key environment variables into entry and worker pods:

    Table 2 Key environment variables

    Environment Variable

    Description

    GROUP_SIZE

    The total number of pods in the current Role instance, used for coordinating collaboration logic across pods.

    ENTRY_ADDRESS

    Internal address (in the format of a headless service) of the entry pod. This address is used for communication with worker pods.

    WORKER_INDEX

    Unique index of each worker pod in the current role instance, which is used for identity identification and task assignment

Prerequisites

  • A CCE standard or Turbo cluster v1.29 or later is available.
  • The Volcano Scheduler add-on v1.21.5 or later has been installed in the cluster. If it is not installed, you can go to the CCE console and search for and install it on the Add-ons page.

    To use auto scaling, ensure Volcano v1.22.3 or later is installed.

If Volcano is used as the scheduler, you are advised to use Volcano to schedule all workloads in the cluster to avoid scheduling conflicts.

Notes and Constraints

  • ModelServing depends on the Volcano Scheduler add-on. If this add-on is not installed in the cluster, related functions will not work.
  • ModelServing workloads cannot be created using the console. They must be deployed using kubectl or YAML.
  • When minRoleReplicas is specified, the cluster must provide enough resources. Otherwise, jobs may remain pending for extended periods.

Key Features

  • Gang Scheduling

    Kthena integrates deeply with the Volcano scheduler to support atomic, all-or-nothing scheduling. This prevents scheduling deadlocks and resource waste that occur when only some pods in a distributed inference group become ready. The scheduler checks whether the number of pods scheduled for a job meets the minimum required for execution. If the threshold is met, all job pods are scheduled simultaneously. Otherwise, none are scheduled.

    The system uses minMember to determine the minimum number of pods required for each ModelServing instance, ensuring efficient and predictable scheduling. The calculation logic is as follows:

    • Default mode: minRoleReplicas is not configured. In this mode, the system calculates the minimum number of pods based on the total replica count across all roles.
      minMember = replicas × role.replicas × (1 + role.workerReplicas)
    • Refined mode: minRoleReplicas is configured. In this mode, the system independently calculates the minimum number of pods that must be ready for each role, using index logic (0 to minRoleReplicas[roleName] - 1). This supports more flexible startup policies.

      Configuration example: In this example, the prefill and decode roles each has four replicas. The system ensures that at least two replicas per role are successfully scheduled and ready, improving overall scheduling efficiency and resource utilization.

      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 supports rolling updates controlled by the Partition parameter. The update proceeds from the replica with the highest sequence number (last pod) downward to ensure an orderly and stable process. The following example uses four replicas (R-0 to R-3) to illustrate the state transitions:

    1. Initialization: All replicas run the old revision. (R-0 to R-3 are in the ready state.)
    2. Initiation: R-3 with the highest index is recreated first. (R-3 is in the restarting state.)
    3. Switchover: After R-3 becomes ready, R-2 is updated. (R-3 is of the new revision, and R-2 is in the restarting state).
    4. Progression: R-1 and R-0 are updated in sequence.
    5. Completion: All replicas run the new revision. (R-0 to R-3 are in the ready state.)

    The Partition parameter defines the update boundary. Only replicas with an index greater than or equal to the Partition value are updated. The controller proceeds to the next replica only after the current replica changes to the Running state and passes the readiness check.

    During a rolling update, the next replica is processed only after the current one is running and ready. If cluster resources are insufficient, the first updated replica may fail to start or become ready, blocking the entire update. Ensure sufficient resources are reserved before initiating an update so that the first replica can start successfully and prevent the rolling update from stalling.

  • Recovery Policy

    This policy defines the granularity and behavior for handling faulty pods in model serving.

    • ServingGroupRecreate: Fine-grained control is performed by ServingGroup. If any pod in the group fails, all pods in the ServingGroup will be recreated to ensure strong consistency across the entire group.
    • RoleRecreate: Fine-grained control is performed by role. If any pod under a role fails, all pods under that role will be recreated.

      Configuration example: The following YAML defines a ModelServing resource with recoveryPolicy set to RoleRecreate:

      apiVersion: workload.serving.volcano.sh/v1alpha1
      kind: ModelServing
      metadata:
        name: sample
        namespace: default
      spec:
        schedulerName: volcano
        replicas: 1  # servingGroup replicas
        recoveryPolicy: RoleRecreate
        template:
        # ...

Example: a ModelServing Workload (Nginx)

In this example, there are two roles: prefill and decode. The prefill role has two replicas, each containing two pods: one entry and one worker. The decode role has three replicas, each containing three pods: one entry and two workers. For details about other scheduling features, see Key Features.

apiVersion: workload.serving.volcano.sh/v1alpha1
kind: ModelServing
metadata:
  name: sample
  namespace: default
spec:
  schedulerName: volcano
  replicas: 1  # servingGroup replicas
  recoveryPolicy: RoleRecreate # Recovery policy
  template:
    restartGracePeriodSeconds: 60
    gangPolicy: # Gang scheduling policy
      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

Example: Automatic Scaling (Using vLLM)

Kthena decouples policies from targets through two core custom resources (CRDs), enabling flexible autoscaling configurations:

  • AutoscalingPolicy: defines scaling policies, including monitoring metrics, target values, stable/emergency mode thresholds, and observation windows.
  • AutoscalingPolicyBinding: defines the scaling target, binds a policy to a specific ModelServing or Role, and configures constraints such as replica limits and the metrics scrape endpoint.

Pods must expose service metrics in a Prometheus-compatible format (for example, vLLM's built-in /metrics endpoint). The Autoscaler periodically scrapes these metrics to drive scaling decisions.

Example AutoscalingPolicy

The following example uses vllm:num_requests_waiting as the metric to configure autoscaling for vLLM ModelServing workloads at the ServingGroup or Role level.

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

Field

Description

metricName

Name of the metric scraped from the pod's /metrics endpoint.

targetValue

Target average value per replica. Scale-out is triggered when the observed value continuously exceeds this threshold.

tolerancePercent

Tolerance percentage. For example, 10% means scaling is suppressed when the metric is within [90, 110] to avoid jitter.

scaleUp.panicPolicy

Emergency scale-out policy for rapid response to traffic surges.

panicThresholdPercent

Threshold for triggering emergency mode, as a percentage of targetValue. For example, 150% triggers emergency mode when the metric reaches 150 (100 x 1.5).

panicModeHold

Duration to maintain emergency mode, preventing premature exit and unexpected scale-in.

scaleUp.stablePolicy

Standard scale-out policy based on sustained trends.

stabilizationWindow

Stabilization window. For example, 1m means scale-out occurs only when the metric exceeds the target for 1 minute, preventing false triggers.

period

Period over which the Autoscaler calculates metrics and makes decisions.

scaleDown

Scale-in configuration. A long stabilization window is typically used to prevent frequent pod churn.

Example AutoscalingPolicyBinding

  • Binding an AutoscalingPolicy to a ModelServing (ServingGroup level)
    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

    Field

    Description

    policyRef

    Reference an AutoscalingPolicy that defines the scaling logic, including metrics and thresholds.

    homogeneousTarget

    Used when scaling a single target workload with homogeneous replicas. It contains the target reference and scaling constraints.

    targetRef

    Top-level resource to be scaled.

    minReplicas

    Minimum number of replicas for the ServingGroup.

    maxReplicas

    Maximum number of replicas for the ServingGroup.

  • Binding an AutoscalingPolicy to a Role (Role level)
    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

    Field

    Description

    subTargets

    (Optional) Refined scaling of specific components within the target workload.

    subTargets.kind

    Sub-target type. Its value is fixed to Role.

    subTargets.name

    Name of the Role as defined in ModelServing (for example, decode).

    minReplicas

    Minimum number of replicas for the specific Role.

    maxReplicas

    Maximum number of replicas for the specific Role.