Architecture
How the collector, control plane, operator, advisor and dashboard fit together — data flow, stores, retention and the guarded action loop.
KubeHero is a collector on every node, a control plane that stores and serves everything, an operator that is the only thing allowed to change workloads, and an advisor that can read everything and change nothing.
┌──────────────────── every cluster (K8s ≥ 1.28 · AKS · GKE · EKS) ────────────────────┐
│ collector (DaemonSet — reports only its own node) operator (Deployment) │
│ cost + usage · logs · pprof scrape · eBPF flows + CPU RightsizingPolicy │
│ profiles · events (leader: unschedulable, Warning events) CeilingPolicy · Budget │
└──────────────┬───────────────────────────────────────────────────────▲────────────────┘
│ Connect-RPC (protobuf, gzip, per-cluster token) │ burn rate, recommendations
▼ │
┌──────────────────────────────────── control plane ─────────────────────┴──────────────┐
│ ingest: IngestPodCost + TelemetryService · compat: Loki push/query · OTLP · Pyroscope │
│ engines: LogQL · Drain · allocation · FOCUS · rightsizing · flamegraphs · service map │
│ anomalies · alert evaluator auth: API keys, cluster tokens, OIDC │
│ ClickHouse — every time series (TTLs + rollups) Postgres — clusters, policies, │
│ alerts, silences, audit │
└──────▲─────────────────▲────────────────────▲────────────────────────▲────────────────┘
│ read RPCs │ │ │ Loki / OpenCost APIs
dashboard advisor (read-only) CLI · MCP server Grafana · OpenCost clients
│ optional, your key
▼
Claude APIComponents
| Component | License | Runs as | Responsibility |
|---|---|---|---|
| collector | Apache 2.0 | DaemonSet | Everything node-local: pod cost and usage, container logs, pprof scraping, eBPF flows and CPU profiles, events. |
| control-plane | BSL 1.1 | Deployment (2 replicas) | Ingest, storage, query engines, compatibility APIs, alert evaluation, auth, audit. |
| operator | BSL 1.1 | Deployment | Reconciles BudgetPolicy, CeilingPolicy, RightsizingPolicy; the only writer to workloads. |
| advisor | BSL 1.1 | Deployment | Briefings and investigations over read RPCs; no Kubernetes credentials. |
| pricing-engine | BSL 1.1 | Deployment | Quote over cache → live cloud price list → built-in table. |
| dashboard | BSL 1.1 | Deployment | Next.js UI; token sign-in with per-user roles. |
| CLI + MCP | Apache 2.0 | your laptop / CI | Every surface from a terminal; kubehero mcp for agents. |
The collector
Each collector reports only the node it runs on (NODE_NAME from the downward API). Cluster-scoped scans — unschedulable pods and Kubernetes Warning events — run on one leader elected through a coordination.k8s.io Lease named kubehero-collector.
- Cost — pods are priced from their node:
max(requests, measured usage)share of allocatable × the node's hourly price, split into CPU / memory / GPU. Each sample carries its interval, so spend israte × interval. See Cost allocation. - Usage history — per-container CPU and working-set memory from the kubelet Summary API with requests, limits, restarts and the last termination reason — the input to rightsizing.
- Logs — tails
/var/log/pods(CRI and json-file), checkpointed and rate-limited. See Logs. - Profiles — pprof scraping of annotated pods, and eBPF
perf_eventCPU sampling of every container. See Profiling. - Flows — eBPF
cgroup_skbbyte accounting and TCP retransmits. See Network. - Events — OOM kills, crash loops, image pull failures, restarts, evictions, node pressure, unschedulable pods.
Its Kubernetes RBAC is read-only. eBPF requires a privileged container — see Security.
The collector ships to the control plane with generated Connect clients (protobuf + gzip), per-call timeouts, jittered retries and a bounded queue: a control-plane outage drops the oldest items (counted) rather than growing memory.
The control plane
- Transport — Connect-RPC: the same
.protocontracts serve Go, TypeScript, the CLI and plaincurl. The services:ControlPlaneService,TelemetryService,CostService,LogsService,ProfilesService,NetworkService,AlertsService(andAdvisorServiceon the advisor). See the API reference. - Ingest — batched writers per table with backpressure (
ResourceExhaustedwhen a queue is full) and validation limits: at most 10,000 log entries, 5,000 flows, 2,000 profiles per request; log lines truncated at 64 KiB; timestamps more than 10 minutes in the future rejected. - Stores — ClickHouse for every time series, Postgres for metadata. The ClickHouse schema is versioned (
kubehero_schema_migrations); Postgres uses golang-migrate.control-plane migrateapplies both; on start the control plane waits for configured stores (KUBEHERO_STORE_WAIT, default 2m) instead of silently falling back to demo data. - Demo mode — RPCs whose store isn't configured serve clearly-labelled fixtures (
source: "demo").KUBEHERO_DEMO_MODE=false(controlPlane.demoMode: "false") turns them off; those RPCs then fail withFailedPrecondition.
Retention
| Table | Holds | TTL |
|---|---|---|
workload_cost_1h, node_cost_1h | hourly spend rollups | 400 days |
node_cost_1s | per-sample node cost and idle | 90 days |
logs | log lines | 14 days |
log_volume_1m | per-minute log volume | 90 days |
profile_samples / profile_stacks | profiles / content-addressed stacks | 14 / 30 days |
net_flows / net_flows_1h | flows / hourly rollups | 30 / 400 days |
container_usage / container_usage_5m | usage samples / 5-minute digests | 35 / 180 days |
cluster_events | Kubernetes health events | 90 days |
The operator and the guarded loop
The operator watches three CRDs — see the CRD reference:
- Propose — an agent (or you) drafts a policy manifest. It is inert.
- Arm — a human sets the arming annotation from the dashboard or
kubehero cap --arm. - Execute — the operator acts in bounded steps: rightsizing patches requests only when every guard passes; ceilings escalate
alert → hpa.cap → pod.evict → nodepool.cordon, dry-run by default. - Audit — every change writes an HMAC-signed, append-only row.
- Reverse —
kubehero undorestores the previous spec.
The operator reads burn rates and rightsizing recommendations from the control plane. If it can't reach the control plane it runs observe-only: ceilings never trip and rightsizing never applies.
The advisor
Read-only by construction: its only inputs are the control plane's read RPCs, it holds no Kubernetes credentials, and every proposal is validated against a CRD whitelist. Claude (your key) or a deterministic rules brain. See Agents & MCP.
Deployment topologies
- Single cluster — everything in one namespace, embedded stores. Quickstart.
- Federated — one control plane in a hub; collector + operator in each workload cluster. Deploy.
- Air-gapped — images mirrored, rules brain only. Deploy.
Agents & MCP
Advisor briefings (text and voice), Ask KubeHero investigations with cited evidence, the kubehero mcp server for Claude and other agents, bring-your-own Anthropic key — and why none of it can change your cluster.
Concepts
Attribution, signals, rightsizing, ceilings and guarded automation — the ideas the rest of KubeHero is built from.