Commit Graph
7 Commits
Author SHA1 Message Date
rock d7b96fb29b fix(minio): freeze the community image by digest and alert on pull failure
MinIO deleted the community edition images upstream. Docker Hub reports
{"message":"object not found"} for minio/minio, and an anonymous pull of
quay.io/minio/mc returns HTTP 401. talos-cp-1 dropped the cached image during
the DiskPressure event on 2026-09-22. The tenant pod was recreated on
2026-09-23 and has been in ImagePullBackOff since. MinIO served no traffic for
13 days, which put vault-0 and loki-0 into CrashLoopBackOff and left the
paperless backups stuck.

Pin the tenant image to the digest of the last community release, so a retag or
a deletion on the mirror cannot break the pull again. Repoint the two
quay.io/minio/mc references at the archived Bitnami client image, also by
digest. Alert on ImagePullBackOff and on a pod that stays not ready, because
neither case raised any alert.

Evidence: https://hub.docker.com/v2/repositories/minio/minio/tags -> {"message":"object not found"}
2026-10-06 11:42:51 +08:00
rock c7d52b5971 fix(llm-serving): V1 prefill scheduling + admission-control observability (#51)
The reasoning engine starves every other request while one long prompt
prefills. Measured: 262 tok/s contended prefill, ~250s for a 65k prompt,
with Avg generation throughput 0.0-0.1 tok/s at Running: 2-4 reqs.

Root cause is NOT what the issue first diagnosed. The issue proposed
--max-num-partial-prefills / --max-long-partial-prefills, which are V0-only
knobs. Verified in the live container: vLLM 0.11.0 ships V1 only (vllm/core/
is absent, so there is no V0 to fall back to), and EngineArgs.
_is_v1_supported_oracle returns False whenever either flag differs from its
default, calling _raise_or_fallback("Concurrent Partial Prefill") ->
"Falling back to V0" -> AssertionError. With strategy Recreate that is an
outage, not a slow rollout. Both flags are therefore NOT set, and a comment
records why so they are not reintroduced.

V1 needs no such flag: it has no prefill/decode phase at all. Every step it
walks self.running and hands out tokens from one shared budget
(vllm/v1/core/sched/scheduler.py). The real defect is that the per-request
cap is disabled by default (long_prefill_token_threshold=0), so one long
prompt takes the WHOLE budget, token_budget hits 0, the `while ... and
token_budget > 0` loop exits, and every other request is skipped.

The cap is applied before the budget clamp, so threshold >= budget never
binds. Replaying the loop: 8192/8192 serves 1 request per step (still
starved); 8192/2048 serves 4, and two long prompts advance together, which
is the issue's actual acceptance criterion.

  --max-num-batched-tokens=8192      (was unset -> default 2048)
  --long-prefill-token-threshold=2048 (was unset -> 0, cap disabled)
  --max-num-seqs=5, --gpu-memory-utilization=0.95

The ~166k KV figure is marked as a projection; the live reading is
num_gpu_blocks=9527 x block_size=16 = 152,432 tokens and is authoritative
post-boot. A preemption alert covers the accept-and-watch risk.

Observability for the companion admission gate (homelab-frontend#64, now
deployed at 64f2bfc1):
  - four dashboard panels: parked, rejected by reason, engine state stale,
    and gateway-view vs engine-truth. Each carries a description, because
    an unexplained blank panel reads as a broken dashboard.
  - alerts on observer_degraded and engine_state_stale_total, both with an
    absent() guard: the gate fails OPEN, so a missing or renamed metric must
    alert rather than look healthy. Verified live that the guards do not
    false-fire (both series present, 3 each).
  - LLMPreemptions and LLMPrefillStarvation: the acceptance metric and the
    regression direction this change introduces.
  - max(vllm_requests_running), not sum(): one engine-global gauge is read
    by all three gateway replicas, so sum() read 3x and could never agree.

Also corrects comments that were factually wrong. An earlier revision of
this branch claimed llm_ttft_seconds/llm_itl_seconds/llm_tokens_total were
dead code; homelab-frontend#63 wired them, verified live as 3 series each.
request_duration_seconds is the genuinely dead one (0 samples, zero
non-test call sites) and is now marked as such instead of being listed as
working.

Closes #51
2026-09-30 19:49:05 +08:00
rock 1f3439c9e0 feat(monitoring): LLM observability dashboard + fix dead CAG rule
New Grafana dashboard (llm-observability) with 27 panels across 5 rows:
TTFT, inter-token latency, batching/scheduling, KV cache, throughput.

Both metric sources are shown side by side because they answer different
questions and neither is complete alone:

  vLLM 0.11.0 (reasoning) — engine truth: kv_cache_usage_perc,
    num_requests_running/waiting, num_preemptions_total, prefill vs
    decode time, prefix cache, per-request histogram quantiles.
  TEI 1.8.2 (embeddings, reranker) — te_batch_next_size, te_queue_size,
    te_embed_duration, te_embed_queue_duration.
  api-gateway — the ONLY per-request latency source covering Ollama
    models (ornith:35b, qwen2.5:3b-instruct), which expose no metrics.
    It is derived from the SSE byte stream, so it is streaming-only and
    counts SSE chunks rather than true tokens. vLLM's own histograms are
    authoritative for reasoning.

All 44 panel queries were executed against live Prometheus before commit —
all return success. vLLM/TEI panels have live series; gateway panels show
no data until the netpol fix in homelab-frontend PR #62 merges.

Also fixes a dead alert. alerts/cag-kv-cache-rules.yaml derived
vllm:prefix_cache_hit_rate from vllm:cache_query_hit_total and
vllm:cache_query_miss_total. Those metric names do not exist in vLLM
0.11.0 — the real series are vllm:prefix_cache_hits_total and
vllm:prefix_cache_queries_total. The recording rule produced no data, so
VLLMPrefixCacheHitRateLow could never fire.

Not included: real GPU hardware metrics (SM utilisation, framebuffer,
power, temperature). Only nvidia-device-plugin is deployed, which exposes
none of them; DCGM exporter is required. vllm:kv_cache_usage_perc and
preemption rate are the only GPU-pressure proxies available today.
2026-09-29 22:11:28 +08:00
rock 605bc706e0 feat(cag): PrometheusRule + Grafana panels for KV cache observability
- cag-kv-cache-rules.yaml: recording rule vllm:prefix_cache_hit_rate
  (from cache_query_hit/miss counters), 3 alert rules:
  KVWarmupFailureHigh, KVWarmupMissHigh, VLLMPrefixCacheHitRateLow
- api-latency-dashboard.yaml: 5 new panels (id 7-11):
  prefix cache hit rate, warmup hit/miss, warmup latency p50/p95,
  standing context tier hits, alert panel with fixed threshold 0.01/s
2026-09-27 18:37:03 +08:00
rock 4c63f8b125 feat: add cluster and api-gateway alert rules with SLA targets 2026-09-04 22:37:48 -07:00
Story Crater Bot 61b906cce1 feat(monitoring): enable Alertmanager (null receiver, longhorn PVC, az-a) + fix forgejo-rules ns forgejo->cicd — alerting delivery was disabled; forgejo PrometheusRule targeted a nonexistent namespace 2026-08-18 15:08:04 -07:00
Story Crater Bot 41f5b05395 refactor(k8s): consolidate to infra/+apps/ single-source tree, dedicated per-app CNPG (authentik-db/temporal-db), wire monitoring-config, forgejo→cicd ns, drop orphan/stale (data-schemas, ollama, story-crater, sqs/argocd, key-rotation) 2026-08-18 15:08:03 -07:00