witty-spinning-lampson.md) + GPS plan v4 (gpu-placement-sharing.md) · model-registry-service · kịch bản mẫu, số liệu minh hoạ (không phải dữ liệu thật). Tuần 2026-10-19 → 2026-10-25, timezone Asia/Ho_Chi_Minh.allow_downtime.// POST /admin/deploy-schedules (CMP: /api/v1/cmp/deploy-schedules) { "name": "gpu-pool-h100-shared", "timezone": "Asia/Ho_Chi_Minh", "mode": "enforce", // enforce | observe (observe = chỉ tính, không submit) "transition_order": "release_first", // L1: mặc định; acquire_first phải khai báo "targets": [ // ownership: 1 deploy ↔ 1 schedule { "model_deploy_id": "md-llama70b", "default_state": "stopped", // ngoài mọi window "default_allow_downtime": true }, // A có alias → cần consent { "model_deploy_id": "md-qwen32b", "default_state": "running" } ], "windows": [ { "name": "business-hours", "kind": "recurring", "priority": 10, "cron": "0 8 * * 1-5", "duration": "10h", // [08:00, 18:00) T2–T6 "states": [ { "model_deploy_id": "md-llama70b", "desired_state": "running" }, { "model_deploy_id": "md-qwen32b", "desired_state": "stopped" } ] }, { "name": "maint-wed", "kind": "one_shot", "priority": 100, // override thắng business-hours "active_from": "2026-10-21T13:00:00+07:00", "active_until": "2026-10-21T15:00:00+07:00", "states": [ { "model_deploy_id": "md-llama70b", "desired_state": "stopped", "allow_downtime": true }, { "model_deploy_id": "md-qwen32b", "desired_state": "running" } ] } ] }
| Target | Desired | Quyết định bởi | Ghi chú |
|---|
:apply-now)deploy_schedule_control.execution: off hoặc đọc lỗi → không submit gì (fail-closed). observe → tính toán + ghi status, không submit.pg_try_advisory_lock trên connection riêng (dùng chung với apply-now, 409 nếu bận). Lock chỉ để đỡ tốn công — tính đúng dựa vào fence + CAS + idempotency (prod chạy 3 replica).deploy_schedule_control.cursor), giới hạn số schedule mỗi pass · system actor · snapshot schedule + version.gpu_sharing (L5) → ineligible{reason} terminal + fix text.submitting → submit với ETag đã chụp + idempotency_keySELECT … FOR SHARE schedule · version · state=enabled · gate · claim · CAS status_version · insert action submitting → commit.AliasGuardWired() = false hoặc đọc guard lỗi → không stop → alias_blocked.accepted{operation_ids}. Converged khi STOPPED và không còn pod terminating (bằng chứng GPU đã nhả).STOP timeout → stop_timeout.PreviewCapacity (chỉ đọc) = insufficient → capacity_wait; quá nominal_start + 15m (hoặc hết interval) → capacity_unavailable.Unschedulable → start_unschedulable (L3: giữ allocation, báo trong status).submitting (crash, mất response, mất lock) → submit lại cùng key; core trả lại Operation cũ hoặc mutate đúng một lần.target_status trên (status_version, target_generation) · event khi đổi phase / lỗi · metrics (deployschedule_target_serving, boundary lag, actions by reason).STOPPED sớm (đã gửi lệnh xoá) nhưng step stop chỉ converged khi hết pod terminating. B có hai đồng hồ: capacity-wait (≤ 15m) rồi readiness.target_status (mọi lỗi đều về terminal có reason + fix text — không treo mãi)allow_downtime — hoặc alias guard chưa wire / đọc lỗi (fail-closed). A tiếp tục chạy; transition dừng ở terminal. :dry-run báo trước. Fix: thêm consent, hoặc sửa wiring.:apply-now.ineligible{endpoint_partially_running} (L4).target_failed (L2), cmp_managed (admin schedule trên deploy CMP), fwc / batch / finetune, gpu_placement_unsupported (L5), scope đổi. Kiểm lại mỗi pass.UNIQUE(model_deploy_id)). Gate off: không submit mới; action đã accepted vẫn chạy xong.// targets + windows (chỉ phần khác so với mục 1) "targets": [ { "model_deploy_id": "md-llama70b", // 8 GPU / replica "default_state": "running", "default_replicas": 1 }, // ngoài giờ: 1 replica { "model_deploy_id": "md-qwen-8gpu", "default_state": "running" } ], "windows": [ { "name": "business-hours", "cron": "0 8 * * 1-5", "duration": "10h", "states": [ { "model_deploy_id": "md-llama70b", "desired_state": "running", "replicas": 2 }, // pin desired=min=max=2 { "model_deploy_id": "md-qwen-8gpu", "desired_state": "stopped" } ] } ] // "replicas" vắng mặt → scheduler không đụng tới scale // replicas = 0 bị reject → muốn về 0 thì dùng "stopped"
allow_downtime kể cả khi A có alias. Scale 2→1 chỉ giảm capacity phục vụ, scheduler ghi event cảnh báo capacity_reduced.PreviewCapacity cho phần tăng thêm (delta), không tính lại toàn bộ deploy.
running, replicas=1, B running. Bước nhả: scale A. Bước chiếm: start B.spec.components[serve].replicas 2→1) và Resources.roles[serve].replicas = {1,1,1} — chỉ sửa Resources thì workload không đổi.max là bắt buộc: deploy PINNED giữ chỗ theo ceiling (MaxReplicas). Giữ max=2 thì accounting vẫn tính A chiếm 16 GPU, B bị từ chối.UPDATING → DGD xoá 1 replica. Converged khi applied generation, desired = 1, ready group = 1 và không còn pod terminating (ObserveReplicas, không đếm 0 khi lỗi).PreviewCapacity(B) = fits (flavorfit theo từng node, tránh phân mảnh).UPDATING → READY → converged. Không fits trong 15m → capacity_unavailable.replicas=2, B stopped. Bước nhả: stop B. Bước chiếm: scale A 1→2.STOPPED + capacity publish → PreviewCapacity(A, +1 replica = 8 GPU) = fits. Chưa fits thì A ở capacity_wait với 1 replica.{2,2,2}. Role accounting có thể từ chối (quota flavor) → quota_refused (terminal; preflight đã chặn trước khi stop B nếu xác định được).RunningReplicas(A) == 2 và READY → converged.SetReplicaIntent khi STOPPED chỉ lưu (persist-only), lấy ETag mới, rồi mới Start. Start dùng spec đang lưu.exclusive{8/replica} vào R1+R2; ngoài giờ B bind exclusive{8} vào R2 → B chỉ được phép rơi vào đúng 8 UUID A vừa nhả, không workload ngoài nào chiếm được (Track H: scheduler ép; Track S: node pin + witness). Đây là "eligibility được bảo vệ", không phải bảo đảm B chắc chắn READY.unsupported_scale_for_mode khi tạo/sửa schedule. Theo U4, GA chỉ scale cho Admin, replica cố định, qua thao tác mới ở core SetReplicaIntent (G6).| Kiểu deploy | Code hiện tại scale thế nào | Vấn đề | Trong GA? |
|---|---|---|---|
DGD aggregated, role serve, replica cố định (không có scalingAdapter) | Patch = WorkloadPatch (component replicas) + Resources roles. Precedent: fireworks-compat patchScaling / WithRoleReplicas | Phải gửi lại toàn bộ spec.components (merge patch thay cả list) → SetReplicaIntent gói việc này ở core | Có |
Như trên nhưng multinode (nodesPerReplica > 1) | Như trên | Nhả / chiếm GPU theo cả nhóm node; convergence đếm theo replica group, preview tính theo nhóm | Có |
| Deployment / LWS không có HPA | Replica trong workload spec | Như DGD aggregated | Có |
DGD có scalingAdapter (SLA Planner) | Apply mirror replica từ live (mirrorAdapterReplicas); operator chặn sửa trực tiếp | Patch spec không có tác dụng; phải hạ policy của Planner (DynamoScaling.MaxReplicas) hoặc qua DGDSA | Sau GA |
| Deployment / LWS + HPA | holdAutoscaledReplicas: chỉ nâng lên số live | HPA đang giữ 2 thì scale-down không ăn; phải hạ max của HPA | Sau GA |
| KServe / Knative (concurrency, scale-to-zero) | min/max annotation | Cần định nghĩa riêng min/max theo window | Sau GA |
| Disagg prefill / decode | 2 role, fixed single-node | replicas: 1 nghĩa là gì còn mơ hồ (prefill? decode? cả hai?) | Từ chối |
| Endpoint CMP (mọi kiểu) | — | Không có điểm kiểm quota khi scale-up ở orchestrator | Sau GA (CMP chỉ start/stop) |
replicas → unsupported_scale_for_mode khi tạo/sửa schedule, kiểm tra lại mỗi pass. Không âm thầm diễn giải. Start/stop vẫn dùng được cho mọi kiểu deploy hợp lệ.rsv-gpu42-shared giữ 1 GPU (viền đậm) trên hla-worker-042, namespace cmp-<project>. 3 member shared, replicas=1, KAI NonMemoryEnforced (compute time-sliced, VRAM policy none — không có VRAM cap). Số liệu bộ nhớ lấy từ receipt gpu42; UUID rút gọn.memory_mib các member đang chạy trên GPU 0 (H200 = 143 771 MiB, headroom 0.95 → 136 582 MiB)Start/SetReplicaIntent, tuần tự theo generation của reservation: Σ memory_mib của member đang chạy thật + action đang bay + action đề xuất ≤ budget. Vượt → terminal reservation_overcommitted. Start tay (U1) cũng qua bước này.--gpu-memory-utilization của vLLM do MRS suy ra từ memory_mib; user args mâu thuẫn → reject.schedulerName qua SchedulingPolicy (không hard-code), queue do server suy ra, node pin = node của reservation, annotation gpu-memory = memory_mib.nvidia.com/container.<c>.gpus.devices nếu S0 xác nhận, không thì DCGM): UUID ∈ reservation → converged; ngoài reservation → placement_mismatch. Không exec nvidia-smi.none: budget chỉ là luật admission của MRS — vLLM vẫn có thể cấp phát vượt và làm neighbour OOM. Tuỳ chọn guard = KAI HamiCore (HAMi-core chặn VRAM, compute vẫn time-slice) — chỉ bật sau khi S0 test với vLLM (quyết định T2).kai-scheduler, gpu-memory, nodeSelector = node của reservation.placement_mismatch (terminal, có fix text, không tự sửa).DRAConsumableCapacity beta → HAMi-DRA) hoặc NVIDIA DRA GPU plugin hỗ trợ chính thức. S0 chọn một.devicesnapshot) thay cho nvidia.com/gpu.| Cơ chế | Chọn UUID trước | VRAM cap | Trạng thái trên HLA |
|---|---|---|---|
KAI NonMemoryEnforced (hiện tại) | Không | Không | Đang chạy (gpu42) |
KAI HamiCore (≥ v0.17) | Không | Có (CUDA intercept) | Chưa cài kai-resource-isolator |
| HAMi-DRA | Có (annotation) | Có | Cần DRAConsumableCapacity (alpha trên 1.35) + CDI |
| NVIDIA DRA driver | Có (CEL) | Không (time-slicing) | GPU allocation "not yet officially supported" |
7f73589f ↔ main; giữ 000214/215; check DB read-only (cần duyệt) → schedule M1–M2, release R0| # | Quyết định | Trạng thái |
|---|---|---|
| Q1 | Re-pin = API có audit, fence theo generation | đã chốt |
| Q2 | Reservation một phần node sau khi S0 chứng minh barrier | đã chốt |
| Q3 | Bill reservation-hour kể cả idle; dừng ở DEGRADED/RELEASING | đã chốt |
| Q4 | Raw CMP DGD đi qua quota + billing | đã chốt |
| Q5 | Bỏ queue/node_name do tenant truyền | đã chốt |
| — | Không MPS, không MIG; time-slicing | đã chốt |
| T1 | Track S ngay; Track H sau K8s 1.36 | chờ user |
| T2 | VRAM none như hiện tại; HamiCore opt-in sau S0 | chờ user |
| T3 | CMP time-slicing chỉ trong reservation của chính project, có ack | chờ user |