已合并
[docs] 补充自动弹性扩缩容文档 #490
jason lyu创建于 7月13日
[docs] 补充自动弹性扩缩容文档 #490
已合并
共 5 个文件变更+291-12
| @@ -65,7 +65,7 @@ motor/coordinator/metrics/ | |||
| 65 | | `QUEUE_GAUGE` | Sum | `num_requests_waiting` | | 65 | | `QUEUE_GAUGE` | Sum | `num_requests_waiting` | |
| 66 | | `CACHE_METRIC` | Mean | `kv_cache_usage_perc` | | 66 | | `CACHE_METRIC` | Mean | `kv_cache_usage_perc` | |
| 67 | | `HOTSPOT_RESOURCE_GAUGE` | Max | `kv_cache_usage_perc_max` | | 67 | | `HOTSPOT_RESOURCE_GAUGE` | Max | `kv_cache_usage_perc_max` | |
| 68 | -| `METADATA_GAUGE` | Passthrough | `process_max_fds`、所有 `motor_*` 指标 | | 68 | +| `METADATA_GAUGE` | Passthrough | `process_max_fds`、所有 `motor:*` 指标 | |
| 69 | | `HISTOGRAM_LATENCY` | Histogram Merge | `e2e_request_latency_seconds` 等 | | 69 | | `HISTOGRAM_LATENCY` | Histogram Merge | `e2e_request_latency_seconds` 等 | |
| 70 | | `SLA_METRIC` | Histogram Merge + 分位数 | `time_to_first_token_seconds` 等 | | 70 | | `SLA_METRIC` | Histogram Merge + 分位数 | `time_to_first_token_seconds` 等 | |
| 71 | | `RATIO_NUMERATOR` / `RATIO_DENOMINATOR` | Sum | `prefix_cache_hits_total` / `queries_total` | | 71 | | `RATIO_NUMERATOR` / `RATIO_DENOMINATOR` | Sum | `prefix_cache_hits_total` / `queries_total` | |
| @@ -134,7 +134,7 @@ get_metrics("full") | |||
| 134 | ```python | 134 | ```python |
| 135 | @dataclass | 135 | @dataclass |
| 136 | class ComputedMetricDef: | 136 | class ComputedMetricDef: |
| 137 | - name: str # 指标名,如 "motor_generation_tokens_per_second" | 137 | + name: str # 指标名,如 "motor:generation_tokens_per_second" |
| 138 | help: str # HELP 文本 | 138 | help: str # HELP 文本 |
| 139 | phase: str # "pre_aggregation"(DP 级)| "post_aggregation"(Service 级) | 139 | phase: str # "pre_aggregation"(DP 级)| "post_aggregation"(Service 级) |
| 140 | compute_type: str # "counter_rate" | "worker_count" | 未来扩展 | 140 | compute_type: str # "counter_rate" | "worker_count" | 未来扩展 |
| @@ -168,7 +168,7 @@ class MotorMetricComputer: | |||
| 168 | _MOTOR_COMPUTED_METRICS: list[ComputedMetricDef] = [ | 168 | _MOTOR_COMPUTED_METRICS: list[ComputedMetricDef] = [ |
| 169 | # -- DP 级: counter rate → tokens-per-second -- | 169 | # -- DP 级: counter rate → tokens-per-second -- |
| 170 | ComputedMetricDef( | 170 | ComputedMetricDef( |
| 171 | - name="motor_prompt_tokens_per_second", | 171 | + name="motor:prompt_tokens_per_second", |
| 172 | help="Prompt tokens per second computed from vllm:prompt_tokens_total counter deltas", | 172 | help="Prompt tokens per second computed from vllm:prompt_tokens_total counter deltas", |
| 173 | phase="pre_aggregation", | 173 | phase="pre_aggregation", |
| 174 | compute_type="counter_rate", | 174 | compute_type="counter_rate", |
| @@ -176,7 +176,7 @@ _MOTOR_COMPUTED_METRICS: list[ComputedMetricDef] = [ | |||
| 176 | role_filter=None, | 176 | role_filter=None, |
| 177 | ), | 177 | ), |
| 178 | ComputedMetricDef( | 178 | ComputedMetricDef( |
| 179 | - name="motor_generation_tokens_per_second", | 179 | + name="motor:generation_tokens_per_second", |
| 180 | help="Generation tokens per second computed from vllm:generation_tokens_total counter deltas", | 180 | help="Generation tokens per second computed from vllm:generation_tokens_total counter deltas", |
| 181 | phase="pre_aggregation", | 181 | phase="pre_aggregation", |
| 182 | compute_type="counter_rate", | 182 | compute_type="counter_rate", |
| @@ -185,7 +185,7 @@ _MOTOR_COMPUTED_METRICS: list[ComputedMetricDef] = [ | |||
| 185 | ), | 185 | ), |
| 186 | # -- Service 级: worker 计数 -- | 186 | # -- Service 级: worker 计数 -- |
| 187 | ComputedMetricDef( | 187 | ComputedMetricDef( |
| 188 | - name="motor_active_prefill_workers", | 188 | + name="motor:active_prefill_workers", |
| 189 | phase="post_aggregation", | 189 | phase="post_aggregation", |
| 190 | compute_type="worker_count", | 190 | compute_type="worker_count", |
| 191 | role_filter=["prefill"], | 191 | role_filter=["prefill"], |
| @@ -229,7 +229,7 @@ Motor 使用 `(job_name, dp_rank)` 作为稳定标识(`job_name` 跨重启不 | |||
| 229 | 229 | ||
| 230 | ### 场景一:新增 DP 级 counter rate 指标 | 230 | ### 场景一:新增 DP 级 counter rate 指标 |
| 231 | 231 | ||
| 232 | -例如,新增一个 `motor_new_tokens_per_second` 指标,基于 `vllm:new_tokens_total` 计算速率。 | 232 | +例如,新增一个 `motor:new_tokens_per_second` 指标,基于 `vllm:new_tokens_total` 计算速率。 |
| 233 | 233 | ||
| 234 | **Step 1:在 `_MOTOR_COMPUTED_METRICS` 注册表中添加定义** | 234 | **Step 1:在 `_MOTOR_COMPUTED_METRICS` 注册表中添加定义** |
| 235 | 235 | ||
| @@ -237,7 +237,7 @@ Motor 使用 `(job_name, dp_rank)` 作为稳定标识(`job_name` 跨重启不 | |||
| 237 | 237 | ||
| 238 | ```python | 238 | ```python |
| 239 | ComputedMetricDef( | 239 | ComputedMetricDef( |
| 240 | - name="motor_new_tokens_per_second", | 240 | + name="motor:new_tokens_per_second", |
| 241 | help="New tokens per second computed from vllm:new_tokens_total counter deltas", | 241 | help="New tokens per second computed from vllm:new_tokens_total counter deltas", |
| 242 | phase="pre_aggregation", | 242 | phase="pre_aggregation", |
| 243 | compute_type="counter_rate", | 243 | compute_type="counter_rate", |
| @@ -251,7 +251,7 @@ ComputedMetricDef( | |||
| 251 | 编辑 `motor/coordinator/metrics/metric_registry.py`,在 `_VLLM_METRIC_REGISTRY` 末尾添加: | 251 | 编辑 `motor/coordinator/metrics/metric_registry.py`,在 `_VLLM_METRIC_REGISTRY` 末尾添加: |
| 252 | 252 | ||
| 253 | ```python | 253 | ```python |
| 254 | -"motor_new_tokens_per_second": MetricSemanticConfig( | 254 | +"motor:new_tokens_per_second": MetricSemanticConfig( |
| 255 | semantic=MetricSemantic.METADATA_GAUGE, | 255 | semantic=MetricSemantic.METADATA_GAUGE, |
| 256 | ), | 256 | ), |
| 257 | ``` | 257 | ``` |
| @@ -260,13 +260,13 @@ ComputedMetricDef( | |||
| 260 | 260 | ||
| 261 | ### 场景二:新增 Service 级聚合指标 | 261 | ### 场景二:新增 Service 级聚合指标 |
| 262 | 262 | ||
| 263 | -例如,新增一个 `motor_decode_queue_depth` 指标,统计 decode 实例的总排队请求数。 | 263 | +例如,新增一个 `motor:decode_queue_depth` 指标,统计 decode 实例的总排队请求数。 |
| 264 | 264 | ||
| 265 | **Step 1:在 `_MOTOR_COMPUTED_METRICS` 注册表中添加定义** | 265 | **Step 1:在 `_MOTOR_COMPUTED_METRICS` 注册表中添加定义** |
| 266 | 266 | ||
| 267 | ```python | 267 | ```python |
| 268 | ComputedMetricDef( | 268 | ComputedMetricDef( |
| 269 | - name="motor_decode_queue_depth", | 269 | + name="motor:decode_queue_depth", |
| 270 | help="Total requests waiting in decode queue", | 270 | help="Total requests waiting in decode queue", |
| 271 | phase="post_aggregation", | 271 | phase="post_aggregation", |
| 272 | compute_type="gauge_sum_by_role", | 272 | compute_type="gauge_sum_by_role", |
| @@ -377,7 +377,7 @@ python3 deploy.py --config_dir ../infer_engines/vllm/pd_hybrid --update_instance | |||
| 377 | - 除 `hybrid_instances_num` 外,不允许同时修改其他配置项。 | 377 | - 除 `hybrid_instances_num` 外,不允许同时修改其他配置项。 |
| 378 | - CRD 默认方式下,脚本更新 `infer_service.yaml` 中 union 角色的 replicas 后执行 apply,由 CRD controller 完成扩缩容。 | 378 | - CRD 默认方式下,脚本更新 `infer_service.yaml` 中 union 角色的 replicas 后执行 apply,由 CRD controller 完成扩缩容。 |
| 379 | 379 | ||
| 380 | -更多说明请参考 [手动扩缩容用户手册](../../features/manual_instance_scaling.md)。 | 380 | +更多说明请参考 [手动扩缩容用户手册](../../features/manual_scaling.md)。 |
| 381 | 381 | ||
| 382 | ## 卸载 | 382 | ## 卸载 |
| 383 | 383 | ||
| @@ -0,0 +1,278 @@ | |||
| 1 | +# 自动弹性扩缩容 | ||
| 2 | + | ||
| 3 | +## 特性介绍 | ||
| 4 | + | ||
| 5 | +自动弹性扩缩容功能支持根据推理实例的实时负载自动调整 Prefill 和 Decode 实例数量。当请求量上升时自动扩容,当负载回落时自动缩容,在保障服务 SLA 的同时提升资源利用率。 | ||
| 6 | + | ||
| 7 | +核心机制:Infer Operator 为推理实例创建 HPA(Horizontal Pod Autoscaler)资源,HPA 通过 External Metrics Adaptor 获取 PyMotor 汇聚的引擎级负载指标(如排队请求数、TPS、KV Cache 使用率等),按用户配置的扩缩容阈值自动调整实例副本数。 | ||
| 8 | + | ||
| 9 | +## 原理说明 | ||
| 10 | + | ||
| 11 | +```text | ||
| 12 | +┌──────────────────────────────────────────────────────────────────┐ | ||
| 13 | +│ K8s Cluster │ | ||
| 14 | +│ │ | ||
| 15 | +│ ┌────────────┐ ┌───────────┐ ┌───────────────────┐ │ | ||
| 16 | +│ │ HPA │ │ Infer │ │ Engine Pods │ │ | ||
| 17 | +│ │(autoscaler)|────>│ Operator │────>│ (Prefill / Decode)│ │ | ||
| 18 | +│ └────────────┘ └───────────┘ └─────────┬─────────┘ │ | ||
| 19 | +│ ^ │ │ | ||
| 20 | +│ │ │ │ | ||
| 21 | +│ │ ┌──────────────────┐ │ │ | ||
| 22 | +│ │ │ PyMotor │ │ │ | ||
| 23 | +│ └────────│ Coordinator │<───────────┘ │ | ||
| 24 | +│ (External │ (aggregation/TPS)│ /metrics │ | ||
| 25 | +│ Metrics API) └──────────────────┘ │ | ||
| 26 | +│ │ | ||
| 27 | +└──────────────────────────────────────────────────────────────────┘ | ||
| 28 | + | ||
| 29 | +1. PyMotor Coordinator 从所有引擎 Pod 采集 Prometheus 指标,按语义聚合后通过 `/metrics` 端点暴露。 | ||
| 30 | +2. External Metrics Adaptor 周期性从 Coordinator 拉取指标,转换为 Kubernetes External Metrics API。 | ||
| 31 | +3. HPA 从 External Metrics API 获取负载数据,与用户配置的目标阈值对比。 | ||
| 32 | +4. 当指标持续超出阈值时,HPA 通知 Infer Operator 增加副本;低于阈值时减少副本。 | ||
| 33 | + | ||
| 34 | +## 支持的产品型号 | ||
| 35 | + | ||
| 36 | +- Atlas 800I A2 推理服务器 | ||
| 37 | +- Atlas 800I A3 超节点服务器 | ||
| 38 | + | ||
| 39 | +## 前置条件 | ||
| 40 | + | ||
| 41 | +- 已完成 Infer Operator 的安装部署。 | ||
| 42 | +- 已完成 PyMotor 推理服务的部署(PD 分离或 PD 混部模式)。 | ||
| 43 | +- 已部署 External Metrics Adaptor,用于将 PyMotor 指标转换为 Kubernetes External Metrics。可直接使用 [mindcluster-deploy 提供的 Metrics Adaptor 示例](https://gitcode.com/Ascend/mindcluster-deploy/tree/master/infer-operator-metrics-adaptor)进行部署。 | ||
| 44 | + | ||
| 45 | +## 配置 PyMotor 暴露 Metrics | ||
| 46 | + | ||
| 47 | +PyMotor Coordinator 默认通过 `/metrics` 端点暴露聚合后的引擎指标,无需额外配置即可使用。 | ||
| 48 | + | ||
| 49 | +Coordinator `/metrics` 端点提供多种聚合视图,通过 `type` 参数切换: | ||
| 50 | + | ||
| 51 | +| type 值 | 说明 | 适用场景 | | ||
| 52 | +|---------|------|---------| | ||
| 53 | +| `full`(默认) | 全局聚合,所有实例指标聚合为单一值 | Prometheus 抓取、HPA 全局扩缩容 | | ||
| 54 | +| `instance` | 实例级指标,注入 `instance_id`、`role` 标签 | 单实例排障 | | ||
| 55 | +| `role` | 按角色(Prefill / Decode)聚合 | 按角色独立扩缩容 | | ||
| 56 | + | ||
| 57 | +```bash | ||
| 58 | +# 查看全局聚合指标(默认) | ||
| 59 | +curl http://{coordinator-ip}:1027/metrics | ||
| 60 | + | ||
| 61 | +# 按角色分别查看指标 | ||
| 62 | +curl http://{coordinator-ip}:1027/metrics?type=role&role=prefill | ||
| 63 | +curl http://{coordinator-ip}:1027/metrics?type=role&role=decode | ||
| 64 | +``` | ||
| 65 | + | ||
| 66 | +## 部署 External Metrics Adaptor | ||
| 67 | + | ||
| 68 | +External Metrics Adaptor 负责将 Coordinator 的 Prometheus 格式指标转换为 Kubernetes External Metrics API,供 HPA 消费。 | ||
| 69 | + | ||
| 70 | +可使用 [mindcluster-deploy 提供的适配器示例](https://gitcode.com/Ascend/mindcluster-deploy/tree/master/infer-operator-metrics-adaptor) 直接部署,也可按需自行实现。 | ||
| 71 | + | ||
| 72 | +部署前需确认 Adaptor 配置了正确的 Coordinator metrics 端点地址和抓取间隔。部署完成后,执行以下命令验证指标可用: | ||
| 73 | + | ||
| 74 | +```bash | ||
| 75 | +kubectl get --raw /apis/external.metrics.k8s.io/v1beta1 | grep -E "num_requests_waiting|motor:generation_tokens_per_second" | ||
| 76 | +``` | ||
| 77 | + | ||
| 78 | +## 配置弹性扩缩容策略 | ||
| 79 | + | ||
| 80 | +在 `examples/deployer/yaml_template/infer_service_template.yaml` 中,为 Prefill 和 Decode 角色的配置块下添加 `scalingPolicy`。 | ||
| 81 | + | ||
| 82 | +以下示例为 Prefill 按排队请求数扩缩容,Decode 按生成 token 速率扩缩容: | ||
| 83 | + | ||
| 84 | +```yaml | ||
| 85 | +roles: | ||
| 86 | + # ========== Prefill 角色 ========== | ||
| 87 | + - name: prefill | ||
| 88 | + replicas: 4 | ||
| 89 | + workload: | ||
| 90 | + apiVersion: apps/v1 | ||
| 91 | + kind: StatefulSet | ||
| 92 | + scalingPolicy: # 新增:弹性扩缩容策略 | ||
| 93 | + type: HPA | ||
| 94 | + spec: | ||
| 95 | + minReplicas: 1 | ||
| 96 | + maxReplicas: 4 | ||
| 97 | + metrics: | ||
| 98 | + - type: External | ||
| 99 | + external: | ||
| 100 | + metric: | ||
| 101 | + name: vllm:num_requests_waiting | ||
| 102 | + target: | ||
| 103 | + type: AverageValue | ||
| 104 | + averageValue: "5" | ||
| 105 | + metadata: | ||
| 106 | + labels: | ||
| 107 | + infer.huawei.com/gang-schedule: 'true' | ||
| 108 | + spec: | ||
| 109 | + # ... 其余配置保持不变 ... | ||
| 110 | + | ||
| 111 | + # ========== Decode 角色 ========== | ||
| 112 | + - name: decode | ||
| 113 | + replicas: 4 | ||
| 114 | + workload: | ||
| 115 | + apiVersion: apps/v1 | ||
| 116 | + kind: StatefulSet | ||
| 117 | + scalingPolicy: # 新增:弹性扩缩容策略 | ||
| 118 | + type: HPA | ||
| 119 | + spec: | ||
| 120 | + minReplicas: 1 | ||
| 121 | + maxReplicas: 4 | ||
| 122 | + metrics: | ||
| 123 | + - type: External | ||
| 124 | + external: | ||
| 125 | + metric: | ||
| 126 | + name: motor:generation_tokens_per_second | ||
| 127 | + target: | ||
| 128 | + type: AverageValue | ||
| 129 | + averageValue: "10" | ||
| 130 | + metadata: | ||
| 131 | + labels: | ||
| 132 | + infer.huawei.com/gang-schedule: 'true' | ||
| 133 | + spec: | ||
| 134 | + # ... 其余配置保持不变 ... | ||
| 135 | +``` | ||
| 136 | + | ||
| 137 | +### scalingPolicy 参数说明 | ||
| 138 | + | ||
| 139 | +| 参数 | 说明 | 取值 | | ||
| 140 | +|------|------|------| | ||
| 141 | +| `scalingPolicy.type` | 弹性扩缩容策略类型 | 当前仅支持 `HPA` | | ||
| 142 | +| `scalingPolicy.spec.minReplicas` | 缩容下限,实例数不会低于此值 | 正整数 | | ||
| 143 | +| `scalingPolicy.spec.maxReplicas` | 扩容上限,实例数不会超过此值 | 正整数,且 ≥ minReplicas | | ||
| 144 | +| `scalingPolicy.spec.metrics[].type` | 指标类型 | `External`(由 External Metrics Adaptor 提供) | | ||
| 145 | +| `scalingPolicy.spec.metrics[].external.metric.name` | 外部指标名称 | 需与 Adaptor 暴露的指标名一致 | | ||
| 146 | +| `scalingPolicy.spec.metrics[].external.target.type` | 目标值类型 | `AverageValue`(Pod 平均值) | | ||
| 147 | +| `scalingPolicy.spec.metrics[].external.target.averageValue` | 目标平均值阈值 | 按指标量纲设定 | | ||
| 148 | + | ||
| 149 | +> [!NOTE] | ||
| 150 | +> `scalingPolicy.spec.metrics[].external.metric.name` 需填写 External Metrics Adaptor 暴露的指标名。Adaptor 可能对 PyMotor 原始 Prometheus 指标名(如 `vllm:num_requests_waiting`)做映射或重命名。部署 Adaptor 后,可通过以下命令查看实际暴露的指标列表: | ||
| 151 | +> | ||
| 152 | +> ```bash | ||
| 153 | +> kubectl get --raw /apis/external.metrics.k8s.io/v1beta1 | grep -E "vllm:|motor:" | ||
| 154 | +> ``` | ||
| 155 | +> | ||
| 156 | +> 若 Adaptor 暴露的指标名与本文示例不同,请以实际返回值为准。 | ||
| 157 | +> | ||
| 158 | +> 本特性依赖 MindCluster Infer Operator 版本 ≥ 26.1.0。用户需按上文示例在 `infer_service_template.yaml` 中手动添加 `scalingPolicy` 配置。 | ||
| 159 | + | ||
| 160 | +## 推荐的扩缩容指标 | ||
| 161 | + | ||
| 162 | +PyMotor `/metrics` 端点提供了丰富的引擎级指标,下表列出推荐用于自动扩缩容的关键指标: | ||
| 163 | + | ||
| 164 | +### Prefill 扩缩容推荐指标 | ||
| 165 | + | ||
| 166 | +| 指标名 | 类型 | 说明 | 推荐阈值建议 | | ||
| 167 | +|--------|------|------|-------------| | ||
| 168 | +| `vllm:num_requests_waiting` | Gauge | 等待调度的请求数 | > 5 触发扩容,< 2 触发缩容 | | ||
| 169 | +| `vllm:num_requests_running` | Gauge | 当前运行中的请求数 | 视 NPU 规格和模型而定 | | ||
| 170 | +| `vllm:kv_cache_usage_perc` | Gauge | KV Cache 使用率(0-1) | > 0.8 触发扩容 | | ||
| 171 | +| `motor:prompt_tokens_per_second` | Gauge | Prompt token 处理速率(Motor 计算) | 按 SLA 目标设定 | | ||
| 172 | +| `vllm:time_to_first_token_seconds` | Histogram | 首 token 延迟(TTFT) | 按 SLA 目标(如 p95 < 500ms) | | ||
| 173 | + | ||
| 174 | +### Decode 扩缩容推荐指标 | ||
| 175 | + | ||
| 176 | +| 指标名 | 类型 | 说明 | 推荐阈值建议 | | ||
| 177 | +|--------|------|------|-------------| | ||
| 178 | +| `vllm:num_requests_waiting` | Gauge | 等待调度的请求数 | > 5 触发扩容 | | ||
| 179 | +| `vllm:num_requests_running` | Gauge | 当前运行中的请求数 | 视 NPU 规格和模型而定 | | ||
| 180 | +| `motor:generation_tokens_per_second` | Gauge | 生成 token 速率(Motor 计算) | 按 SLA 目标设定 | | ||
| 181 | +| `vllm:e2e_request_latency_seconds` | Histogram | 端到端请求延迟 | 按 SLA 目标(如 p95 < 2s) | | ||
| 182 | +| `vllm:time_per_output_token_seconds` | Histogram | 跨 token 延迟(TPOT) | 按 SLA 目标(如 p95 < 50ms) | | ||
| 183 | + | ||
| 184 | +> [!NOTE]说明 | ||
| 185 | +> | ||
| 186 | +>- `motor:prompt_tokens_per_second` 和 `motor:generation_tokens_per_second` 是 PyMotor Coordinator 计算的服务级指标,基于 vLLM 原始 counter 计算 delta rate 得到,更准确反映实时吞吐。 | ||
| 187 | +>- Histogram 类型指标(如 `vllm:e2e_request_latency_seconds`)需要在 Adaptor 侧计算分位数(p50/p95/p99)后作为独立指标暴露。 | ||
| 188 | +>- 建议为 Prefill 和 Decode 分别配置不同的扩缩容指标,以匹配各自的计算特征(Prefill 为计算密集型,Decode 为访存密集型)。 | ||
| 189 | + | ||
| 190 | +### 多指标组合策略 | ||
| 191 | + | ||
| 192 | +可在 HPA 中配置多个指标,HPA 会选择**最保守的扩缩容决策**(即当前副本数最接近触发扩容或缩容的指标): | ||
| 193 | + | ||
| 194 | +```yaml | ||
| 195 | +scalingPolicy: | ||
| 196 | + type: HPA | ||
| 197 | + spec: | ||
| 198 | + minReplicas: 1 | ||
| 199 | + maxReplicas: 4 | ||
| 200 | + metrics: | ||
| 201 | + - type: External | ||
| 202 | + external: | ||
| 203 | + metric: | ||
| 204 | + name: num_requests_waiting | ||
| 205 | + target: | ||
| 206 | + type: AverageValue | ||
| 207 | + averageValue: "5" | ||
| 208 | + - type: External | ||
| 209 | + external: | ||
| 210 | + metric: | ||
| 211 | + name: kv_cache_usage_perc | ||
| 212 | + target: | ||
| 213 | + type: AverageValue | ||
| 214 | + averageValue: "0.8" | ||
| 215 | +``` | ||
| 216 | + | ||
| 217 | +## 验证扩缩容效果 | ||
| 218 | + | ||
| 219 | +### 查看 HPA 状态 | ||
| 220 | + | ||
| 221 | +```bash | ||
| 222 | +kubectl get hpa -n {namespace} | ||
| 223 | +``` | ||
| 224 | + | ||
| 225 | +回显示例如下: | ||
| 226 | + | ||
| 227 | +```text | ||
| 228 | +NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE | ||
| 229 | +prefill-my-test StatefulSet/prefill-my-test 3/5 1 4 2 10m | ||
| 230 | +decode-my-test StatefulSet/decode-my-test 8/10 1 4 2 10m | ||
| 231 | +``` | ||
| 232 | + | ||
| 233 | +- `TARGETS` 列显示 `当前值/目标值`,当前值超过目标值时触发扩容。 | ||
| 234 | +- `REPLICAS` 列显示当前实际副本数。 | ||
| 235 | + | ||
| 236 | +### 模拟负载触发扩容 | ||
| 237 | + | ||
| 238 | +发送大量并发推理请求,观察 HPA 是否自动扩容: | ||
| 239 | + | ||
| 240 | +```bash | ||
| 241 | +# 并发发送请求 | ||
| 242 | +for i in {1..100}; do | ||
| 243 | + curl -X POST "http://{service-ip}:31015/v1/chat/completions" \ | ||
| 244 | + -H "Content-Type: application/json" \ | ||
| 245 | + -d '{"model": "your-model", "max_tokens": 100, "messages": [{"role": "user", "content": "Hello"}]}' & | ||
| 246 | +done | ||
| 247 | +``` | ||
| 248 | + | ||
| 249 | +随后查看 HPA 状态,确认 `REPLICAS` 是否增加,以及新增引擎 Pod 是否正常运行: | ||
| 250 | + | ||
| 251 | +```bash | ||
| 252 | +kubectl get hpa -n {namespace} --watch | ||
| 253 | +kubectl get pod -n {namespace} | grep -E "prefill|decode" | ||
| 254 | +``` | ||
| 255 | + | ||
| 256 | +### 验证缩容 | ||
| 257 | + | ||
| 258 | +停止负载后,观察数分钟(由 HPA `--horizontal-pod-autoscaler-downscale-stabilization` 默认 5 分钟),确认实例数回落至 `minReplicas`: | ||
| 259 | + | ||
| 260 | +```bash | ||
| 261 | +kubectl get hpa -n {namespace} --watch | ||
| 262 | +``` | ||
| 263 | + | ||
| 264 | +## 注意事项 | ||
| 265 | + | ||
| 266 | +- HPA 弹性扩缩容当前仅支持 Prefill 和 Decode 实例;Router 不参与扩缩容。 | ||
| 267 | +- 缩容存在稳定窗口(默认 5 分钟),避免负载短暂波动导致频繁扩缩。 | ||
| 268 | +- 扩容的新实例没有 KV Cache 缓存,Prefix Cache 特性会逐步重建缓存,因此新实例的推理性能可能出现小幅度劣化并在一段时间后恢复。 | ||
| 269 | +- External Metrics Adaptor 需持续运行并正确配置 Coordinator 地址。若 Adaptor 异常,HPA 将无法获取指标,可能导致扩缩容失效。 | ||
| 270 | +- 建议 `minReplicas` 至少设为 1,避免缩容到 0 导致服务完全不可用。 | ||
| 271 | +- Counter 类型指标(如 token 总数)不会因 `/metrics` 请求而重置,建议优先使用 Gauge 类型指标或 PyMotor 计算的 TPS 指标作为扩缩容依据。 | ||
| 272 | +- 若使用不带 `type` 参数的 `/metrics` 端点(默认 `full`),HPA 获取到的是全局聚合值。如需按 Prefill/Decode 角色独立扩缩容,Adaptor 需分别请求 `/metrics?type=role&role=prefill` 和 `/metrics?type=role&role=decode`。 | ||
| 273 | + | ||
| 274 | +## 参考文档 | ||
| 275 | + | ||
| 276 | +- [配置基于负载的弹性扩缩容](https://gitcode.com/Ascend/mind-cluster/blob/master/docs/zh/scheduling/04_usage/09_infer_operator_best_practice/05_configuring_elastic_scaling.md) — Infer Operator 弹性扩缩容策略配置指南 | ||
| 277 | +- [Metrics 可观测性指标设计文档](../../design/metrics.md) — PyMotor Metrics 子系统架构与指标说明 | ||
| 278 | +- [监控接口](../api/monitoring_interfaces.md) — PyMotor `/metrics` 端点使用说明 | ||
Rdocs/zh/user_guide/features/manual_instance_scaling.md→docs/zh/user_guide/features/manual_scaling.md+0-0
文件重命名但无更改。
Prefill 扩缩容指标表格中列出了
vllm:num_requests_waiting,但上方 YAML 示例(第 101 行)中写的是num_requests_waiting(不带vllm:前缀)。用户按表格名称配置 HPA 可能找不到指标,建议统一或加说明解释 External Metrics 名称与 Prometheus 名称的映射关系。