Appearance
谁拥有副本数?监控、弹性和 GPU 指标
上一章已经能把流量分给两个端点。但如果所有端点都在排队,换一个端点并不能变出算力。扩容看似只要改 replicas;真正难的是避免两个控制器同时写它,以及解释为什么目标副本数提高后队列还在增长。
sequenceDiagram Runtime-->>Prometheus: 每个副本报告等待数 KEDA->>Prometheus: 查询聚合指标 HPA->>Deployment: 更新期望副本数 Deployment-->>Gateway: 新副本就绪后才进入端点集合
Chart 可选 ScaledObject 查询 Prometheus 的 waiting_requests。标量查询应只有一个数值;多个时间序列要先聚合,同一指标不要因高可用采集器被重复计数。先验证 Prometheus 有样本,再启用扩容;缺失指标不等于队列为零。scale-down 稳定窗抑制 1 到 N 间缩容抖动,cooldownPeriod 主要约束缩到零;本例 min=1 给冷启动留一个热副本。
固定模式由 Operator 写 replicas;autoscale=true 时只在 Deployment 新建且副本字段为空时给初值,之后由 HPA/KEDA 写副本。并存写入会导致控制循环反复放大/缩减。新增副本仍要过节点过滤、镜像拉取、模型文件加载和 readiness。要在业务额度中覆盖弹性峰值,可预留 maxReplicas × 每副本需求;更高利用率要求扩容前动态准入,独立 chart-demo 没有 SQL 配额;对已投递的申请执行 go run . elastic ID 则以已预付 cost 限制该服务的 maxReplicaCount(实验按一槽/副本计费)。先核对 binding 中的 CR UID,再放弃副本字段控制权,并给 ScaledObject 绑定同一 owner。不是在每个 HPA 请求里另开跨系统事务,也不对物理卡提供锁。
本地实测采用 CPU + Kind。真实 NVIDIA 验证需要驱动、容器运行时、Device Plugin、可用扩展资源和兼容 vLLM 镜像,在 GPU 节点部署后再测 token/s。共享模型权重目录应区分只读缓存、模型版本和写入完成标记;缓存预热不能绕过就绪检查。
完整源码:deploy/chart/templates/stack.yaml · 第 54–73 行
yaml
kind: ScaledObject
metadata: {name: chart-demo}
spec:
scaleTargetRef: {name: chart-demo}
minReplicaCount: 1
maxReplicaCount: {{ .Values.maxReplicas }}
cooldownPeriod: 120
advanced:
horizontalPodAutoscalerConfig:
behavior:
scaleDown:
stabilizationWindowSeconds: 180
triggers:
- type: prometheus
metadata:
serverAddress: {{ .Values.prometheusURL }}
query: sum(modeldock_waiting_requests{service="chart-demo"})
threshold: "2"
ignoreNullValues: "false"
{{- end }}先确认指标链,再开扩容
Prometheus 逐端点采集,验证 query 的结果是一条新鲜标量;把图画出来是最后一步。以下命令都用实验 kubeconfig。
sh
kubectl -n modeldock-lab create configmap prometheus-config --from-file=deploy/observability/prometheus.yml --from-file=deploy/observability/alerts.yml --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f deploy/observability/stack.yaml
helm upgrade --install keda keda --repo https://kedacore.github.io/charts -n keda --create-namespace --wait
helm upgrade handbook deploy/chart -n modeldock-lab --reuse-values --set autoscale=true --set maxReplicas=2 --set prometheusURL=http://prometheus.modeldock-lab.svc:9090
kubectl -n modeldock-lab get scaledobject,hpa,deploy -w指标过阈值后副本数才上升;如果 desired 已上升但 available 不跟,查 Pod Events 和加载探针。恢复固定副本用 helm upgrade handbook deploy/chart -n modeldock-lab --reuse-values --set autoscale=false。Grafana 的 dashboard JSON 与 Prometheus 数据源配置见运维篇。真实 GPU 需节点上由 NVIDIA DCGM Exporter 暴露 DCGM_FI_DEV_GPU_UTIL、显存等并被 Prometheus 抓取。设备利用率不是租户归属;共享设备时不要把整卡数值简单计入每个 Pod。本 Mac 未验证 GPU 采集。
GPU 环境扩展:打通设备指标
只有带 NVIDIA 驱动和容器工具链的节点可以做这一段;Mac Kind 不参与。先查节点实际公布的资源,再部署与驱动兼容的 DCGM Exporter。已有 GPU Operator 管理同一 exporter 时不要重复安装;须匹配兼容版本后将 chart 版本固定到自己的部署配置。
sh
kubectl get nodes -o custom-columns='NODE:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu'
helm repo add gpu-helm-charts https://nvidia.github.io/dcgm-exporter/helm-charts
helm repo update gpu-helm-charts
helm search repo gpu-helm-charts/dcgm-exporter --versions | head
# DCGM_CHART_VERSION 设为与你的驱动兼容的版本
helm upgrade --install dcgm-exporter gpu-helm-charts/dcgm-exporter --version "$DCGM_CHART_VERSION" -n gpu-monitoring --create-namespace
kubectl -n gpu-monitoring get ds,svc,endpointslice把设备采样 job作为额外一项加入 Prometheus scrape_configs,先核对实际 Service 名、端口名,并给采集身份读取 gpu-monitoring 的 EndpointSlice、Service、Pod 的权限。重载配置并在 Targets 检查 UP,然后看 avg by (node) (DCGM_FI_DEV_GPU_UTIL)、DCGM_FI_DEV_FB_USED。无样本先查 exporter /metrics,不能把空值填成零。回收时删除该采样任务、仅卸载本次创建的 exporter。这个配置未在 GPU 上运行。