Releases: opscart/opscart-k8s-watcher
Release list
v1.10.2 - Persistence & Authentication Recovery
OpsCart v1.10.2
This recovery release retains all v1.10.1 functionality while correcting persistence, authentication, security, and container-platform issues.
Fixed
- Graceful scanner and HTTP shutdown before closing SQLite
- WAL checkpointing during controlled shutdown
- Required persistence now fails startup instead of silently entering ephemeral mode
- Contextual SQLite startup diagnostics and bounded retry handling
- Helm-generated credentials now survive pod restarts and upgrades
- Existing
auth.existingSecretbehavior remains supported - Correct native Linux AMD64 and ARM64 container builds
- Updated
golang.org/x/textto v0.39.0
Helm authentication
When auth.existingSecret is empty, Helm creates and preserves a release-managed Secret. Retrieve credentials using the commands printed by helm install or helm upgrade.
Important storage note
Multi-node Minikube commonly uses node-local hostPath storage. A PVC backed by hostPath is not shared across nodes. Pin the workload to the storage node for local testing, or use genuinely shared/durable storage.
Image
ghcr.io/opscart/opscart-dashboard:v1.10.2
Supported platforms:
linux/amd64linux/arm64
OCI index:
sha256:623e77263aa1702de2b069daff574c147485fb5dfaa504161fcaba020c9f6010
v1.10.0 — Workload-Scoped Incidents
v1.10.0 — Workload-Scoped Incidents
The Investigation and Incidents pages no longer anchor on the Pod — the most ephemeral object in Kubernetes — they anchor on the workload that actually owns the problem.
The problem this fixes
A 5-minute-old pod could display a 26-day-old incident timeline. The underlying tracking was correct (an incident should persist across pod replacements — that's what makes it memory), but the presentation wasn't: AGE: 0d sitting beside FIRST DETECTED: 26 days ago read as a contradiction, not as "this Deployment has been unstable for weeks across several pod replacements."
What's new
Deterministic focus selection. When multiple pods briefly match the same incident fingerprint (a pod mid-termination alongside its replacement), OpsCart now selects one canonical Focus Pod — highest restart count wins, pod name breaks ties — instead of the previous arbitrary, scan-order-dependent choice.
Cross-pod contamination fixed. Restart-milestone and drift comparisons now check whether the Focus Pod actually stayed the same between scans. Previously, a pod replacement (249 restarts → 2 restarts) could be misread as a trend on the same object; now a resource change correctly resets the comparison instead of producing a false signal.
Workload-first Incidents table. The Incident column is now Workload, showing the owning Deployment/StatefulSet/DaemonSet as the primary identity with the current pod as a secondary line — matching what the Investigation page shows when you click through.
Investigation page redesign:
Situation Briefing — observational only, no causal claims ("has been observed in a critical state since Jul 10," not "root cause is X" or "never resolved")
Operational Identity card — Classification, Severity, Tracking scope (accurately labeled per controller type: Deployment-wide, StatefulSet-instance-scoped, etc.), Open Since
Current Observation card — Namespace, Workload, Focus Pod, Pod Age, Restart Count, Container, live status, with a ready-to-copy kubectl describe command
Namespace-scoped findings (missing NetworkPolicy, idle namespaces) preserved exactly as before — no pod-shaped data forced onto them
Removed the raw timeline event count, since it was inflated by a still-open flapping investigation — no numbers shown that aren't currently trustworthy
Fixed: Incidents and War Room links no longer pass a synthetic pod parameter for namespace-level findings, and no longer leak the internal current-context placeholder into shareable URLs.
Not in this release
Recurrence statistics (recovered/reopened counts) and pod-replacement timeline events are intentionally held back until an ongoing flapping investigation is resolved — shipping derived stats on top of unverified data would be worse than not shipping them at all.
v1.9.0 — Verdict-First Overview: Operational Memory, Finally Visible
The Overview page no longer opens with a KPI grid — it opens with a written verdict.
New:
Situation Briefing — a two-sentence cluster assessment ("what's wrong, what's improved") backed by real incident data
Operational Memory scoreboard — total seen, resolved, reopened, accelerating, longest-running incident, most unstable namespace
What's Changed Since Last Scan — shows only what happened since your last visit
Top 5 Things To Fix — now shows first-detected age, reopen count, trend; routes correctly (single incident → Investigate, multi-pod group → filtered Incidents view)
Cluster / Namespace / Security health cards, capped with "View all" links
Bottom strip shows real trend deltas ("+8 since yesterday") on cost, waste, and scores
Fixed: Top 5 links were hardcoded to War Room regardless of the issue; the verdict could disagree with Top 5 about the worst issue; a few UI/data inconsistencies found via live testing.
No changes to War Room, Incidents, or Investigation. Standard helm upgrade — no new config required.
Operational memory now survives pod restarts and helm uninstall
Chart parity with deploy/dashboard.yaml plus hardening from in-cluster
verification on multi-node minikube:
- Persistence: templated PVC (persistence.enabled/size/storageClassName/
existingClaim), annotated helm.sh/resource-policy: keep so operational
memory survives helm uninstall; strategy Recreate when enabled (RWO) - Namespace: remove templated namespace (use --create-namespace);
namespace helper resolves .Release.Namespace so -n is honored - Volume ownership: fsGroup 65534; values-toggled volumePermissions
init container for provisioners that ignore fsGroup on hostPath
(minikube default) — symptom was silent NullStore fallback - nodeSelector support — required on multi-node minikube where hostPath
PVs have no node affinity (rescheduled pod mounts empty dir) - NOTES.txt, chart README (persistence, minikube gotchas, local image
workflow, full values table), root README refreshed (timeline, blast
radius, operational memory; chart declared canonical) - Chart 0.1.0 → 0.2.0, appVersion → v1.7.0; dashboard.yaml image bumped
v1.3.0 — Operational Memory
What's New
Operational Memory (SQLite)
OpsCart now remembers what happened. A lightweight local database tracks cluster
snapshots, incident history, and scan metadata across scans.
- Trend arrows on all KPI cards — up/down/flat with correct semantics
(green when improving, red when degrading) - 7-point sparkline on Incident Score showing recent history
- Incident tracking — first seen, last seen, active/resolved status per fingerprint
- NullStore fallback — persistence is never required; degrades gracefully if DB unavailable
Investigation Page v2
- OpsCart Assessment — rules-based operational summary paragraph
- Evidence section — restarts, state, age, owner chips before recommendations
- Confidence-rated hints — High / Medium / Low with color coding
- Each hint includes a specific kubectl command
War Room Visual Differentiation
- Per-type card accent colors (red for CrashLoop, yellow for ImagePullBackOff, purple for Privileged, blue for NetworkPolicy)
- SVG icons per issue type
Install
# Helm
helm install opscart-watcher ./helm/opscart-watcher \
--namespace opscart-system \
--create-namespace
# kubectl
kubectl apply -f https://raw.githubusercontent.com/opscart/opscart-k8s-watcher/main/deploy/dashboard.yamlSecurity
- Trivy scan: 0 vulnerabilities
- Scratch image, non-root UID 65534
- Pure Go SQLite (modernc.org/sqlite, CGO_ENABLED=0 compatible)
What's Next
- PVC-backed persistence (
persistence.enabled=truein Helm) - Blast radius analysis
- Change detection ("new since yesterday")
v1.1.0 — Operational Intelligence Navigation
v1.1.0 — Operational Intelligence Navigation
New Pages
- Incidents — Full grid view of all War Room issues (Critical + High Severity)
- Security Posture — CIS Kubernetes Benchmark v1.8 controls, risk breakdown, priority actions
- Waste & Drift — Zombie pods, orphaned PVCs, zero-replica workloads, abandoned namespaces
New Features
- Incident Score (0-100) — Composite score aggregating crash loops, image pulls, OOM kills, security posture, and waste
- War Room panel — Multi-card scrollable layout showing top 4 critical issues with kubectl quick fixes
- Sidebar restructured — Overview/War Room → Investigate → Analyze → Configure
Security
- Scratch image, non-root (UID 65534)
- Trivy scan: 0 vulnerabilities
- Read-only ClusterRole
Deploy
kubectl apply -f https://raw.githubusercontent.com/opscart/opscart-k8s-watcher/main/deploy/dashboard.yaml
New in v1.1.0:
- Incident Score (0-100)
- Incidents page
- Security Posture page
- Waste & Drift page
- Sidebar restructure
- War Room multi-card panel
v1.0.0 - Operational Intelligence
Major Features:
- New Overview page: Top 5 Things to Fix + War Room featured panel
- Sidebar restructure: Overview → Operations → Analysis
- Critical Issues as primary KPI (replaces Running Pods)
- Trust badges: Read-only, No agents, No cloud credentials
- Issue grouping with severity-based prioritization
Engineering:
- Complete CLI refactor: cmd/opscart-scan/main.go 1682 → 724 lines (57% reduction)
- Dashboard refactor: templates extracted, main.go 2428 → 1867 lines
- 46 unit tests passing
- Trivy scan: 0 vulnerabilities
Security:
- Scratch image (~50MB)
- Non-root (UID 65534)
- Read-only ClusterRole (no mutations)
- No external dependencies
- All Go deps updated to latest
Tested on:
- Real production cluster (53 namespaces, 17 critical issues found)
- Minikube opscart development cluster"
v0.9.0 — Kubernetes Intelligence Dashboard
🎯 OpsCart K8s Watcher v0.9.0 — Full Kubernetes Intelligence Dashboard
Five working tabs. One kubectl apply. Zero dependencies.
What's New
🖥️ Infrastructure Tab
Node pool deep-dive with VM SKU detection, CPU/memory utilization
bars, $/node/month, pool totals, and Reserved Instance savings
potential (1yr and 3yr).
📦 Namespaces Tab
The only view that cross-references cost + network policy + waste
per namespace. See exactly which namespaces are unprotected,
how much they cost, and how many waste items they contain.
💡 Optimizations Tab
- Reserved Instance opportunities with projected savings
- Waste by category: orphaned PVCs, zombie pods, zero-replica
workloads, abandoned namespaces - Right-sizing candidates (namespaces with <0.5 CPU cores)
⚔️ War Room Full Page
Real-time critical issues with per-card kubectl commands:
- Critical: CrashLoopBackOff, OOMKilled, ImagePullBackOff pods
- Warnings: unprotected namespaces, orphaned PVCs, zero-replica workloads
- One-click copy kubectl commands for immediate investigation
🔧 Bug Fixes
- Fixed War Room silently returning empty results (limit=0 bug)
- Fixed pods in
defaultnamespace being skipped by waste detector - Zombie pods now bypass minAgeDays filter — a crashing pod is
a crashing pod regardless of age - Optimizations tab now reads correct waste data from WasteAudit
Deploy in 60 Seconds
kubectl apply -f https://raw.githubusercontent.com/opscart/opscart-k8s-watcher/main/deploy/dashboard.yaml
kubectl port-forward -n opscart-system svc/opscart-dashboard 8080:80
open http://localhost:8080What Each Tab Shows
| Tab | Data Source | Key Insight |
|---|---|---|
| Cost Overview | Azure pricing catalog | Real $/mo from node labels |
| Infrastructure | NodePoolCosts | VM SKU, utilization, RI savings |
| Namespaces | Cost + NetPol + Waste | Cross-referenced per namespace |
| Optimizations | All analyzers | Actionable savings opportunities |
| War Room | Waste + Network audits | Critical issues needing action now |
Tested On
- Azure AKS multi-node-pool clusters
- Minikube (local development)
What's Next (v1.0)
- SQLite 30-day cost history + trend charts
- Helm chart (
helm install opscart-dashboard) - GitHub Actions auto-build on release tag
- AWS/GCP pricing catalog
Docker image: ghcr.io/opscart/opscart-dashboard:v0.9.0
Full changelog: Compare v0.8.0...v0.9.0
v0.7.0 — Cloud Cost Analysis
Accurate cloud cost estimation from real AKS node pool VM pricing.
No external API calls — embedded Azure retail price catalog.
Highlights:
• Detects VM SKUs from node labels automatically
• 40+ Azure VM SKUs with PAYG/RI-1yr/RI-3yr/Spot pricing
• Region-aware multipliers (15+ regions)
• Namespace + deployment cost allocation
• Enterprise HTML dashboard (dark theme, SVG charts)
• Optimization scenarios with projected savings
• Multi-cluster support
FinOps grade cost analysis v0.6.0
- Add --breakdown deployment flag: per-Deployment/StatefulSet/DaemonSet cost drill-down in CLI
- Add HTML cost dashboard (--format html): KPI cards, share bars, waste, score bars, optimization scenario cards, assumptions footnotes
- Remove spot instance scenarios; replace with right-sizing, idle workload, and namespace consolidation scenarios
- Exclude system namespaces (kube-system, cert-manager, istio-system, monitoring, flux-system, etc.) from optimization recommendations and deployment breakdown
- Make --monthly-cost optional: resource-share mode when no billing data
- Add unallocated row reconciling namespace allocations vs cluster total
- Fix idle pod detection: allow up to 5 restarts (was 0, broke all
production pods); require 7+ day age threshold - Fix confidence scoring: 3-signal model (share size + pod count +
waste); replaces share-size-only logic that returned Medium for ~95% of namespaces - Add wasteColor, mul template FuncMap helpers in costs_html.go
- Bump version to 0.6.0; update README with all changes
What's Changed
Full Changelog: v0.5.3...v0.6.0