AIBrix StormService#

StormService 是一个专门组件,旨在管理和协调 Prefill/Decode 分离架构中推理容器的生命周期。此外,它还可用于监督各种部署模式,例如张量并行(TP)、流水线并行(PP),甚至单 GPU 模型部署。

三层架构#

StormService 采用三层架构,通过多个自定义资源定义(CRD)实现。此架构的示例如下所示:

AIBrix StormService Architecture
  • StormService:这是封装整个服务的顶层 CRD。它定义了服务单元的规范并跟踪其状态,包括副本数(即 RoleSet)、RoleSet 的统一模板、更新策略和其他配置。有关详细定义,请参阅 stormservice_types.go 文件。

  • RoleSet:RoleSet 代表角色集合,其中每个角色都可以承担特定功能(例如 Prefill 或 Decode)。有关更多信息,请参阅 roleset_types.go 文件。

  • Pods:RoleSet 中的每个角色都包含多个 Pod,这些 Pod 是执行推理任务的实际容器。

遵循此分层设计,规范的更新从 StormService 传播到其 RoleSet,然后传播到单个角色。StormService 级别的协调器将 RoleSet 的状态与 StormService 规范(主要是 Replicas 字段)同步,而 RoleSet 级别的协调器将单个角色的状态与 RoleSet 规范同步。

StormService 在其级别支持两种操作模式:滚动更新原地更新。在 RoleSet 级别,支持三种更新模式:并行顺序交错。这些将在下面详细解释。

部署模式#

Stormservice 支持两种部署模式:副本模式池化模式

注意

  1. 这两种模式互斥。没有专门的配置项来明确指定部署模式;它仅由 stormservice.spec.replicas 字段控制。

  2. StormService 的部署模式是自动确定的,当 replicas > 1 时激活副本模式,当 replicas = 1 时激活池化模式。

副本模式#

副本模式将每个 RoleSet 视为服务的独立副本。如果您已经知道 P/D 比率,可以直接配置 RoleSet 并进行复制。

特性

  • 独立副本:每个 RoleSet 独立运行,对一个 RoleSet 的更改不会直接影响其他 RoleSet

  • RoleSet 级别的伸缩:伸缩操作通过添加或删除整个 RoleSet 实例来执行。

池化模式#

池化模式RoleSet 中的每个角色视为共享池的一部分。在此模式下,每个角色都应该是独立可伸缩的。它旨在处理不同角色具有不同伸缩需求的情况。

特性

  • 资源池:Prefill 或 Decode 实例形成一个共享池。

  • 独立角色伸缩:每个角色都可以根据其特定的负载和要求独立伸缩。

更新策略#

StormService 支持多种策略来更新托管的 RoleSet。这些策略旨在处理不同的操作模式,并确保更新过程中的服务可用性。以下是对每种策略的详细解释:

滚动更新#

专为副本模式设计,滚动更新策略逐步用新的 RoleSet 替换旧的 RoleSet。这种方法通过遵守 MaxUnavailableMaxSurge 设置,确保服务在整个更新过程中保持可用。

工作原理

  1. 初始状态:开始时,所有 RoleSet 都运行旧版本。

  2. 创建新 RoleSet:控制器创建具有更新版本的新 RoleSet,确保 RoleSet 的总数(旧 + 新)不超过期望副本数和 MaxSurge 的总和。

  3. 删除旧 RoleSet:一旦新 RoleSet 准备就绪,控制器开始删除旧 RoleSet。它确保任何时候不可用的 RoleSet 数量不超过 MaxUnavailable

  4. 重复:重复步骤 2 和 3,直到所有旧 RoleSet 都被新 RoleSet 替换。

配置参数

  • MaxUnavailable:此参数定义了在更新过程中可以不可用的最大 RoleSet 数量。它确保始终有最小数量的 RoleSet 可用于服务请求。

  • MaxSurge:此参数定义了在更新过程中可以创建的超出所需副本数量的最大 RoleSet 数量。它允许控制器暂时创建额外的 RoleSet 以加速更新。

示例

假设我们有一个具有 3 个副本的 StormServiceMaxUnavailable 设置为 1,MaxSurge 设置为 1。滚动更新过程可能如下所示:

        graph LR
classDef old fill:#FFCCCC,stroke:#CC0000,stroke-width:2px;
classDef new fill:#CCFFCC,stroke:#00CC00,stroke-width:2px;

    A(Initial: 3 old RoleSets):::old --> B(Create 1 new RoleSet):::new
    B --> C(Delete 1 old RoleSet):::old
    C --> D(Create 1 new RoleSet):::new
    D --> E(Delete 1 old RoleSet):::old
    E --> F(Create 1 new RoleSet):::new
    F --> G(Delete 1 old RoleSet):::old
    G --> H(Result: 3 new RoleSets):::new
    

原地更新#

专为池化模式设计,原地更新策略将更改直接从 StormService 传播到所有关联的 RoleSet,而无需删除和创建新的 RoleSet。当您希望更新 RoleSet 的配置而不中断现有 Pod 时,此策略非常有用。工作原理:

工作原理

  1. 识别过时的 RoleSet:控制器识别所有未使用最新版本的 RoleSet。

  2. 更新 RoleSet:控制器直接将过时 RoleSet 的配置更新为最新版本。

  3. 同步状态:RoleSet 级别的协调器然后根据更新后的规范同步其状态。

优点

  • 最小中断:由于没有 RoleSet 被删除或创建,服务在更新过程中保持可用。

  • 快速更新:更新过程更快,因为它不涉及资源的创建和删除。

  • 无需额外 GPU:它不需要创建新的 RoleSet,从而避免在升级时使用更多 GPU。

        graph LR
classDef old fill:#FFCCCC,stroke:#CC0000,stroke-width:2px;
classDef new fill:#CCFFCC,stroke:#00CC00,stroke-width:2px;

    A(Initial: 3 old RoleSets):::old --> B(Update 3 RoleSets in-place)
    B --> C(Result: 3 new RoleSets):::new
    

滚动策略#

StormService 支持多种滚动策略来更新 RoleSet 中的角色。这些策略提供了不同的方法来管理更新,同时保持服务稳定性。

  • 顺序:角色一个接一个地按顺序更新。

  • 并行:所有角色同时更新。

  • 交错:角色以交错方式更新。此策略将每个 Role 的更新过程划分为不同的步骤。每个更新步骤都在所有角色中进行协调以同步进行。在每个操作周期中,控制器根据最不先进的角色确定全局进度状态。它指示尚未达到当前步骤的角色继续更新,而跳过已达到当前步骤的角色。

有状态与无状态#

这由 StormService 和 RoleSet 规范中的 Stateful 字段决定。它定义 RoleSet 是使用 StatefulRoleSyncer 还是 StatelessRoleSyncer,这会导致不同的行为。

  • 有状态StatefulRoleSyncer 将每个 Pod 视为一个唯一的、不可互换的实体,为每个 Pod 分配一个稳定且唯一的索引。有 n 个副本就有 n 个槽位,更新以受控的方式逐槽位执行。

  • 无状态StatelessRoleSyncer 将所有 Pod 视为相同的副本。任何 Pod 都可以被替换而不会影响整个应用程序。Pod 被作为一个集体池进行管理,伸缩操作只是添加或随机删除 Pod。更新是在池级别执行的,而不是针对特定 Pod。

自动伸缩#

  • 副本模式:StormService 在其 CRD 上启用了 /scale 子资源。伸缩单位是 RoleSet。它涉及使用动态标签选择器扩展 StormService 状态,并实现控制器逻辑以确保此选择器正确填充,从而允许外部自动伸缩器有效管理 StormService 副本。

  • 池化模式:在池化模式下,RoleSet 中的每个角色都应该是独立可伸缩的。

警告

池化模式自动伸缩(每个角色的独立伸缩)尚未支持。有关更多详细信息,请参阅问题 #1260。作为替代方案,您可以在 RoleSet 规范中调整每个角色的副本数。

ControllerRevision#

在 Kubernetes 生态系统中,ControllerRevision 是一个关键的资源对象,用于记录控制器(如 Deployment、StatefulSet 等)的版本信息。在 AIBrix 项目中,ControllerRevision 机制被用于跟踪 StormService 的版本变化,为版本管理、回滚操作和系统状态可追溯性提供强有力的支持。

  • 版本记录ControllerRevision 存储 StormService 特定版本的配置信息,主要是 spec 部分。每当 StormService 的配置发生变化时,系统就会创建一个新的 ControllerRevision 对象,并将更改后的配置以序列化形式存储在此对象中。通过这种方式,系统可以清晰地记录 StormService 在不同时间点的配置状态。

  • 版本回滚:当需要将 StormService 恢复到以前的配置状态时,可以根据 ControllerRevision 中保存的历史配置信息执行回滚操作。通过指定目标 ControllerRevision 的版本号,系统可以将 StormService 的配置恢复到与该版本对应的状态。

  • 历史可追溯性ControllerRevision 为系统运维和开发人员提供了追溯历史配置的能力。通过查看不同版本的 ControllerRevision 对象,可以了解 StormService 配置的变更历史,这有助于问题排查和系统审计。

kubectl get controllerrevisions
NAME                  CONTROLLER                                      REVISION   AGE
llm-xpyd-69df6b87d8   stormservice.orchestration.aibrix.ai/llm-xpyd   1          73s
llm-xpyd-75ddc56d8c   stormservice.orchestration.aibrix.ai/llm-xpyd   2          3s