# Radar - Full Documentation > Radar is open-source Kubernetes visibility for platform engineering teams. One Helm chart for self-host (Apache 2.0), or Radar Cloud for fleet aggregation, persistent retention, SSO, and routed alerts. ## About Radar Radar gives engineers a unified view of every Kubernetes cluster they run - topology, event timeline (past the 1-hour TTL), Helm releases, image filesystem inspection, cluster audits, and an MCP server for AI agents. The full engine is Apache 2.0 and runs from a single binary or Helm chart. Radar Cloud is the hosted control plane that adds multi-cluster fleet view, retention up to 1 year, SAML/OIDC SSO, scoped RBAC, and routed alerts. ### Core capabilities (open source, Apache 2.0) - **Topology graph**: Live Kubernetes resource graph laid out by ELK.js, updated via SSE. Group by namespace, app label, or ungrouped. - **Event timeline**: Every K8s event and resource delta, persisted past the kube-apiserver's 1-hour TTL. In-memory or SQLite. - **Image filesystem viewer**: Browse container image filesystems without pulling locally or running kubectl exec. Works with private registries. - **Cluster audit**: 31 best-practice checks across security, reliability, and efficiency. Runs against cached cluster state. - **Helm release manager**: Every release, every revision, every value file. Rollbacks from the UI. - **MCP server for AI agents**: 13 read tools and 5 annotated write tools. Token-optimized output, RBAC-aware, secrets never exposed. ### Radar Cloud (hosted) - **Multi-cluster fleet view**: Search across every connected cluster from one bar. Compare workload versions side by side. - **Long-term retention**: 30-day audit log retention on Team, up to 1 year on Enterprise. - **SSO and scoped RBAC**: SAML/OIDC SSO, SCIM provisioning, per-cluster or per-namespace scoped roles. - **Routed alerts**: Slack, PagerDuty, MS Teams, webhooks. Per-cluster routing, in-app inbox, suppression windows. - **GitOps visibility**: Native ArgoCD and Flux support. See sync state next to live resource state. ### Pricing - **Cloud Free**: 3 clusters included, full fleet UI, multi-user org. Free forever. - **Team**: $99 per cluster per month. Unlimited clusters, SSO, 30-day retention, paid integrations, email support. - **Enterprise**: Custom pricing for regulated orgs, BYOC/on-prem, SCIM, 1-year retention, 99.9% uptime SLA, dedicated CSM. ## Blog Posts ### Introducing Radar Cloud: Multi-Cluster Kubernetes Visibility for Teams - **URL**: https://radarhq.io/blog/introducing-radar-cloud - **Date**: 2026-05-28 - **Author**: Nadav Erell, CEO, Skyhook - **Category**: Announcements - **Tags**: radar-cloud, kubernetes, multi-cluster, observability, launch A platform engineer we talk to runs staging, two prod regions, and a handful of ephemeral preview clusters. She loves Radar OSS - she has it aliased to `r` on her laptop and uses it every day. But when her on-call teammate pings her in Slack at 1am asking "what does the topology look like right now in prod-us?", she has to either screenshot her own view or walk him through `kubectl` for the next twenty minutes. The OSS tool works exactly as designed. One engineer, one cluster, one laptop. That's the product. But teams need something else: a shared view that doesn't vanish when someone closes their terminal, access controls that aren't "whoever has the kubeconfig wins", and a timeline that survives past the last restart. That's what Radar Cloud is. ![Radar Cloud hero](/images/blog/radar-hero.png) ## TL;DR Radar Cloud is the hosted extension of Radar OSS. Radar runs in each cluster, connects outbound-only over TLS to `api.radarhq.io`, and Cloud reverse-proxies browser requests through to it on demand. You get fleet views across every connected cluster, SSO on every plan (including Free), Kubernetes-native scoped RBAC via impersonation, an org-scoped audit log, hub-side notifications for connection and billing events, and shareable deep links. The control plane never caches your cluster state. Live Kubernetes state is the source of truth. Credentials stay in the cluster. Logs and exec stream on demand and are never stored at rest. Free tier for up to 3 clusters. $99 per cluster per month on Team. Custom on Enterprise. ## What OSS can't do for a team Radar OSS is a single Go binary that runs locally against your kubeconfig or in-cluster via Helm. That architecture is a feature: nothing leaves your machine, instant startup, no account required. It's the right shape for individual debugging, regulated environments, and air-gapped clusters. It's the wrong shape for a team of eight engineers running twelve clusters. Five things break once you scale past one engineer and one cluster: - **No fleet view.** OSS talks to whatever kubeconfig context is active. Switching contexts is manual. There's no single screen that says "across all my clusters, what's unhealthy right now?" - **No shared links.** If you spot a broken pod and want to point a teammate at it, the best you can do is a screenshot. There's no URL that opens the same view on their machine. - **Whoever has the kubeconfig can do anything.** OSS respects your cluster RBAC, but it doesn't layer anything on top. There's no group-to-role mapping out of the box, no audit log of who did what. - **No SSO.** Access is a kubeconfig file passed around however your team passes around kubeconfig files. - **No connection-state notifications.** OSS shows you what's happening when you're looking. It doesn't tell you when a cluster has gone dark while you weren't watching. Every one of those gaps is a thing we kept hearing from OSS users. Radar Cloud closes them without changing the OSS architecture or pulling features behind a paywall. ## A concrete before and after Last month one of our early-access teams hit a cascading DNS failure that took out two services across their prod-eu cluster. Three engineers ended up debugging together across a two-hour window. With OSS alone, every engineer was on a different laptop with a different kubeconfig context. Coordination was someone screenshotting their view into Slack, then someone else asking "is that prod-eu or prod-us?", then a fourth engineer joining and asking the same question. With Radar Cloud, they all opened the same fleet view, picked prod-eu, and were inside the in-cluster Radar's live state - same Pods, same events, same topology. They sent a deep link to the cluster view to the SRE who joined forty minutes late, who clicked through and was looking at the right cluster's CoreDNS pods in two seconds, not asking "which cluster are we on?" again. No heroics. Just: one URL, scoped access, and everyone looking at the same source of truth. ## What Cloud adds ### Fleet views One dashboard across every connected cluster. Today's fleet views answer the questions that are painful one cluster at a time: which clusters have critical problems, where is a resource named `payments-api` running, which clusters still fail a specific audit check, which package versions are drifting. The views fan out to connected clusters over the tunnel and render progressively for large fleets. Drill into any cluster and you're inside the same resource, topology, timeline, Helm, GitOps, and audit views you already know from OSS. ### Cross-cluster compare Pick two clusters and diff the same resource side by side as YAML - the fastest way to catch the staging-vs-prod drift behind "but it works on the other cluster." It's wired into fleet search, so you can jump from a match straight into compare mode. ### Live timeline Resource changes, Kubernetes events, Helm operations, and observed state transitions, served live from the in-cluster Radar pod when you open the view. In-cluster Radar can persist its timeline to SQLite when configured with a PVC, so it survives pod restarts; the soft retention budget is tunable. ### SSO on every plan WorkOS-backed SAML and OIDC. Okta, Entra ID, Google Workspace, OneLogin, and any spec-compliant SAML / OIDC provider. Self-serve setup through the WorkOS Admin Portal. **Available on every plan, including Free** - we don't gate identity behind a tier. ### Kubernetes-native RBAC via impersonation Three Cloud roles (`owner`, `member`, `viewer`) map to standard Kubernetes ClusterRoleBindings (`admin`, `edit`, `view`) by default. The Cloud control plane injects `X-Forwarded-User` and `X-Forwarded-Groups`, and the in-cluster Radar pod impersonates the user when it talks to the K8s API. Whatever K8s RBAC permits, the user can do. Whatever it doesn't, they can't. You override the defaults via two lines in `cloud.defaultRbac.*` in the Helm values. Per-user namespace-scoped RoleBindings work too, via the `cloud:user:` group. There's no parallel permission system to maintain - it's K8s RBAC the whole way down. ### Audit log Every authentication event, role change, scope change, cluster registration, and write operation through Cloud lands in an audit log. Tier-based retention: 7 days on Free, 30 days on Team, 365 days on Enterprise. ### Agent and MCP governance Radar speaks the Model Context Protocol, so AI agents - Claude, Cursor, your own in-house bots - can read live cluster state through the same backend the UI and CLI use. Cloud adds the governance layer on top: a dedicated **Agents page** that inventories every agent and personal access token across the org, with activity status, so you can see exactly what has access and revoke anything stale. Because an agent runs with a user's token, it inherits that user's Kubernetes RBAC - the same impersonation model as a human, no separate permission plane. And every tool an agent can call is marked **read-only or write** (apply, scale, exec are write), so a read-only assistant is never quietly confused with one that can mutate prod. ### Notifications Hub-side notifications cover connection-state events (`cluster.disconnected`, `cluster.reconnected`), org membership events (`org.member.invited`, `org.member.joined`), and billing events. Configurable destinations are Slack and webhooks; there's also an always-on in-app inbox and per-user email preferences. We're deliberately conservative on what gets pushed. The value is in the dashboard you already use, not a chatty Slack channel. ### Shareable deep links Every view has a URL. Resource detail, filtered timeline slice, topology view, cluster view. Paste it into Slack, link it from an incident doc, bookmark it. The URL preserves filters and the cluster scope. ## Architecture Radar Cloud is split in two: in-cluster Radar and a multi-tenant control plane. ![Radar Cloud architecture](/images/blog/radar-agent-architecture.png) In-cluster Radar is the same Go binary as Radar OSS, deployed as a Deployment via Helm. It uses the `client-go` SharedInformer pattern - list once per resource type, then watch deltas. No polling, no periodic full scans. **The connection is outbound-only.** Radar dials `api.radarhq.io:443`, negotiates TLS, upgrades to a WebSocket, authenticates with a cluster-scoped bearer token, and runs yamux for stream multiplexing on top. The cluster doesn't need a LoadBalancer, Ingress, NodePort, or inbound firewall rule. If your cluster can make an outbound HTTPS call to one FQDN, Radar works. This is the property that makes Radar tolerable to security teams. Radar runs with a **scoped Kubernetes ServiceAccount**. Read-only by default. You opt into write features (logs, exec, Helm management, scale, restart) per-feature if you want to drive operations from the Radar UI. **The control plane is a reverse proxy.** When a browser asks for cluster data, Cloud authenticates the user, opens a fresh yamux stream over the existing WebSocket, and forwards the HTTP request through to the in-cluster Radar pod, which serves it live from its SharedInformer cache. The Hub does not store your cluster state. There is no server-side replica, no event ingest pipeline, no "stale at 5s intervals" cache. Live K8s state is the source of truth. **What the control plane does store:** org membership, roles, cluster registry metadata, audit log entries, PAT hashes, billing state, and a small set of hub-native events (cluster.disconnected, member invitations, billing). That's it. **What stays in the cluster:** all cluster resources, including Secret and ConfigMap values. Logs, exec sessions, and port-forwards are streamed through the tunnel on demand only when a user opens them, and **are never stored at rest** on the Cloud side. Each cluster is enrolled with a bearer token issued from the Radar dashboard. The raw token is shown exactly once at creation and stored only as a SHA-256 hash bound to the cluster record. An owner can rotate it at any time, which invalidates the previous hash and forces Radar to reconnect with the new value. ### Install ```bash helm repo add skyhook https://skyhook-io.github.io/helm-charts helm repo update helm install radar skyhook/radar -n radar --create-namespace \ --set cloud.enabled=true \ --set cloud.url=wss://api.radarhq.io/agent \ --set cloud.clusterName=prod-us \ --set cloud.token=$RADAR_CLOUD_TOKEN ``` The dashboard hands you this command with the token and cluster name already filled in when you enroll a cluster. One minute from `helm install` to a cluster tile lighting up green in the fleet view. After that, you don't go back to Helm to stay current: when a cluster's in-cluster Radar falls behind, the dashboard flags it and upgrades the agent in place over the existing tunnel - one click, no second `helm upgrade`. ## A tour in five views ### Fleet The landing page. Cards for every cluster you've enrolled, grouped however you want, with health, recent warnings, and drill-in. The view OSS users have been asking for since week one. ### Topology The same structured-DAG topology from OSS, running at cluster scope. Ownership chains, Service routing, Ingress paths, ConfigMap and Secret references, HPA targets. Problem resources light up yellow or red. One honest note: **topology in v1 is single-cluster.** You pick a cluster, you get its graph. Cross-cluster topology edges are on the roadmap but not in GA. We'd rather ship single-cluster topology that's correct than cross-cluster topology that fakes the edges. ### Timeline The cross-source event view from in-cluster Radar - K8s events, resource diffs, pod lifecycle, GitOps reconciles, Helm operations - served live from the in-cluster pod. Filter by cluster, namespace, resource kind, or severity. Persists across pod restarts when the in-cluster timeline is configured with SQLite storage. ### Helm and GitOps All Helm releases and Argo CD or Flux resources across every cluster. Status, chart version, app version, sync state, owned-resource health. Install, upgrade, rollback, uninstall, sync, reconcile - if Radar's ServiceAccount has write permissions in that namespace. ### Notifications Hub-side notifications cover the events the control plane actually owns: cluster disconnect and reconnect, org member invites and joins, billing failures, free-tier cap. Destinations: in-app inbox, Slack, email preferences, generic webhook. Per-user toggles for which kinds you want to hear about. This is deliberately a small surface. Routing every K8s event into chat is the way you end up muting the channel. ## What it costs | Plan | Clusters | Audit log retention | Users | Auth | Notifications | SLA | Price | |------|----------|---------------------|-------|------|---------------|-----|-------| | **Free** | 3 included | 7 days | Unlimited | SSO (SAML / OIDC) | Slack, webhook, in-app | Best-effort | $0 | | **Team** | Unlimited | 30 days | Unlimited | SSO (SAML / OIDC) | Slack, webhook, in-app | 99.5% | $99 / cluster / month | | **Enterprise** | Unlimited | 365 days | Unlimited | SSO + SCIM | Slack, webhook, in-app | 99.9% | Contact us | Enterprise adds 365-day audit retention, BYOC / on-prem deployment of the control plane, US or EU data residency, SCIM 2.0 directory sync, and a dedicated CSM. Annual contracts get 20% off the Team list rate. Billing is per connected cluster, not per node or per pod. A 3-node dev cluster and a 300-node prod cluster cost the same on Team. That's deliberate - we don't want to penalize you for running bigger workloads, and the per-cluster cost to us doesn't scale linearly with cluster size. ## OSS vs Radar Cloud | | Radar OSS | Radar Cloud | |---|---|---| | Install location | Your laptop or in-cluster Helm | Radar per cluster + hosted control plane | | Clusters | One at a time | Aggregated fleet view across all connected | | Timeline | In-memory or SQLite, in-cluster | Same in-cluster timeline, served live through reverse proxy | | Auth | Local kubeconfig | SSO (Okta, Google, Entra ID, SAML / OIDC) on every plan | | RBAC | Inherits kubeconfig | K8s impersonation - 3 default roles + per-user RoleBindings | | Audit log | - | 7 / 30 / 365 days by tier | | Notifications | None | Slack, webhook, in-app inbox (hub events) | | Shareable views | No | Deep links per resource and view | | Agent / MCP access | MCP server, single cluster | Same MCP, plus org-wide agent + token inventory and read-only/write tool labels | | Price | Free forever | Free for 3 clusters, $99 / cluster / month Team, Enterprise custom | | SLA | None | 99.9% on Enterprise | ## What we are not shipping in v1 This is the honest list. Some of these will land in the next two quarters, some we're still debating. - **Cross-cluster topology edges.** Single-cluster topology only in v1. Cross-cluster topology and cross-cluster timeline are on the roadmap, not shipping today. - **Custom dashboards.** The views are the views. You can filter and deep-link, but you can't build your own tiles or drag widgets around. In the design queue. - **Long-term cluster-event archive.** We don't store your cluster events on the control plane at all - they live in the cluster, with optional SQLite persistence in-cluster. If you need a seven-year regulatory archive, ship events to your SIEM; we're not that system. - **Self-hosted control plane below Enterprise.** The BYOC / on-prem deployment path is an Enterprise feature. If you need the Radar experience inside your own infra without an Enterprise contract, the path today is Radar OSS plus the in-cluster Helm deployment. Radar Cloud is also not a metrics platform, not an APM, and not a log aggregator. It's a Kubernetes visibility plane. Prometheus, Grafana, Datadog, and your existing log backend keep their jobs. ## Why hosted when OSS exists The obvious question: if Radar OSS is free and good, why build a paid hosted thing? Because some things can't live on one laptop. SSO needs an identity layer. Org-scoped audit logs need a database. Notifications about a cluster going dark need a system that's awake when you're not. Cross-cluster aggregation needs a fan-in point. None of those belong in a local Go binary, and bolting them on would ruin the thing that makes OSS good. So we drew the line cleanly. **Radar OSS stays free, stays fully featured for single-cluster work, and keeps all the views it launched with.** We're not pulling topology behind a paywall. We're not crippling the Helm view. We're not adding a "cloud login required" nag screen. **Radar Cloud is the thing you reach for when one laptop isn't enough.** The hosted backend is different code, the value is different. If that value is worth $99 per cluster per month to your team, great. If it isn't, OSS is still there. That's the split. No bait-and-switch, no "community edition" with missing features, no mandatory sign-up to make OSS work. The two products serve different jobs. ## Getting started Sign up at [radarhq.io](https://radarhq.io) and you get the Free tier immediately - 3 clusters, full SSO, unlimited teammates in your workspace. Enroll your first cluster with the Helm install above. Full docs live at [radarhq.io/docs](https://radarhq.io/docs). The OSS source is linked from the docs site. If you're already running Radar OSS and want to try Cloud on a single non-critical cluster, the install is drop-in. You don't have to choose. --- ### Migrating from Lens and OpenLens in 2026 - **URL**: https://radarhq.io/blog/migrating-from-lens - **Date**: 2026-07-07 - **Author**: Nadav Erell, CEO, Skyhook - **Category**: Open source - **Tags**: kubernetes, lens, openlens, freelens, migration If you're still running Lens, you've probably noticed the ground shifting under you. The open-source repo no longer matches the commercial desktop product. Lens now requires an account, and organizations above the revenue or funding threshold need a paid plan - [currently starting at $25 per user per month](https://app.k8slens.dev/subscribe). The tool you adopted because it was a free, open desktop UI for Kubernetes is a different product now. Nobody did anything wrong by picking Lens. It was the right call for years. But if you're reading this, you're probably deciding where to go next, and most "Lens alternatives" articles are written by vendors who conclude, surprisingly, that the answer is their product. We make one of the alternatives, so discount accordingly - but here's the map as we honestly see it. Lens's licensing shift is the trigger for this decision, not the whole decision. Replacing Lens with another resource browser fixes the account and pricing problem, but not necessarily the operational gaps that made Kubernetes hard in the first place: understanding what connects to what, what changed before an incident, and where traffic is actually flowing. ## TL;DR - Want exactly the Lens desktop experience, still free? **Freelens.** - Want a CNCF-governed, plugin-extensible dashboard? **Headlamp.** - Live in the terminal? **k9s**, and you probably already know it. - Want the capabilities we couldn't get from Lens forks or plugin-first dashboards - topology, persistent history, live traffic, GitOps, audit, and agent-ready context - in one no-login tool? That's why we built **Radar**. Weighing every option line by line? We keep a [full comparison of Lens alternatives](/lens-alternative) and a [detailed Radar vs Lens breakdown](/vs/lens) up to date separately. This post is the decision framework. ## What actually happened to Lens A quick timeline, because the fork situation confuses everyone: - **Mid-2022:** Lens 6.0 introduces paid subscription requirements for commercial use. - **January 2023:** Mirantis moves exec, logs, and shell into proprietary code in Lens 6.3. OpenLens builds lose core features, and community energy starts shifting to forks. - **June 2023:** OpenLens publishes its [last release](https://github.com/MuhammedKalkan/OpenLens/releases). Its repository now says to expect no more updates because Lens closed its source code. - **Freelens** emerges as the actively maintained community fork and becomes the real successor for people who want the Lens desktop experience. - **January 2024:** the original lensapp/lens repo publishes its [last GitHub release](https://github.com/lensapp/lens/releases). Since then, the commercial Lens product and the OSS repo have diverged. - **Today:** Lens is a commercial desktop product with mandatory login and per-seat pricing for organizations above the revenue threshold. ### On OpenLens? Migrate now OpenLens is unmaintained software running with powerful credentials against clusters whose API surfaces keep moving. That's the most urgent migration in this article. You do not need to move workloads or change cluster configuration - pick a replacement, point it at the same kubeconfig, and verify the workflows you used in OpenLens. ## Option 1: Freelens - the "I just want my Lens back" path [Freelens](/vs/freelens) is the actively developed fork, and it's good. Same desktop paradigm, same mental model, no login, no paywall. If your team's muscle memory is Lens-shaped and you want the smallest possible migration, this is the honest recommendation. Point it at your kubeconfig and you're done in minutes. The tradeoff: it inherits Lens's architecture - an Electron desktop app doing client-side work against the API server, one kubeconfig per laptop. That was Lens's ceiling too. It browses resources well; it doesn't explain a cluster to you. ## Option 2: Headlamp - the CNCF path [Headlamp](/vs/headlamp) is a CNCF Sandbox project under SIG UI, extensible through plugins, and shipping fast. If your organization weights foundation governance heavily, or you want to assemble a dashboard from plugins to your exact taste, it's a solid choice - and it runs in-cluster as a web app, not only on the desktop. The tradeoff is the assembly itself: much of the depth arrives via plugins you select, install, and maintain, and the out-of-box experience is a resource browser. We ranked it honestly against everything else in [our 2026 dashboard comparison](/blog/best-kubernetes-dashboards-2026). ## Option 3: k9s - the terminal path If you're a k9s person, you're not reading a migration guide. [k9s](/vs/k9s) is excellent - it's just answering a different question: fast keyboard-driven resource operations, not visual cluster understanding. Plenty of Radar users keep k9s open in the next pane. Coexist. ## Option 4: Radar - the "understand the cluster" path Radar exists because neither the Lens family nor plugin-first dashboards gave us the operational view we needed at Skyhook. We wanted one tool that understood the cluster as a connected system, covered the ecosystem we actually ran, and worked equally well for an engineer in the UI and an agent over MCP. The result is a single Go binary, Apache 2.0, with no login, no account, and no agents to install. Run it locally against your kubeconfig, as a desktop app, or in-cluster as a web UI. Where Lens-style tools show you lists of resources, Radar's core is the relationships: a live topology with ownership chains (Deployment to ReplicaSet to Pods), an event timeline for "what broke first", service traffic, Helm release forensics, and a built-in audit that runs the checks you forgot. It auto-detects 120+ ecosystem CRDs as typed views and topology edges - plus any other CRD in your cluster - instead of asking you to assemble plugins. Lens has MCP now, so the question is not "MCP or no MCP." It is whether the MCP is a thin kubectl-style bridge or a real cluster-understanding layer. Radar's [built-in MCP server](/blog/mcp-for-kubernetes-live-cluster-context-for-ai-tools) gives the agent topology, issues, timelines, relationships, scrubbed logs, and diagnosis tools instead of making it reconstruct the cluster from raw API output. ```bash curl -fsSL https://get.radarhq.io | sh && kubectl radar ``` Or Homebrew (`brew install skyhook-io/tap/radar`), a desktop app, or Helm for in-cluster - all four on [the homepage](/). **Radar's tradeoffs, honestly:** multi-cluster fleet views live in [Radar Cloud](/pricing), a separate per-cluster-priced product - OSS Radar is one cluster at a time. And it's the youngest project on this list: weekly releases mean fast fixes, but also a tool that's still growing into some corners. ## The migration itself Whatever you pick, the actual migration is undramatic. None requires moving workloads or changing cluster configuration, and the local options read your existing kubeconfig: 1. **Inventory what you actually used in Lens.** Most teams: resource browsing, logs, exec, port-forward, maybe metrics. Everything on this page covers those. 2. **Check your extensions.** Lens extensions don't port anywhere. List what you depended on and find the equivalent - a Headlamp plugin, a Radar integration, or a standalone tool. 3. **Run the new tool alongside Lens for a week.** Nothing about this is one-way. 4. **If you're on OpenLens, don't wait.** Unmaintained software with cluster-admin credentials is not a neutral state. ## Where this leaves you The Lens story is a reminder to inspect a Kubernetes tool's governance, license, and escape hatches before you standardize on it. It is also a useful moment to decide whether you want continuity or a more capable operating model: Freelens if you want the familiar desktop workflow, Headlamp if you want foundation governance, k9s if you want the terminal, Radar if you want the cluster explained rather than listed. Radar is open source and takes about two minutes to try against a real cluster: [github.com/skyhook-io/radar](https://github.com/skyhook-io/radar). If it doesn't answer a question kubectl couldn't, delete the binary and keep the two minutes as a story. --- ### Radar MCP vs kubectl: A Kubernetes Agent Benchmark on 52 Faults - **URL**: https://radarhq.io/blog/radar-mcp-vs-kubectl-benchmark - **Date**: 2026-06-16 - **Author**: Nadav Erell, CEO, Skyhook - **Category**: Engineering - **Tags**: radar, mcp, ai-agents, kubernetes, kubectl, benchmark I wanted to know one thing: when an AI agent debugs a broken Kubernetes cluster, does it matter what tools we hand it? Most vendors hand-wave this - "our MCP makes your agent smarter." That is not the bar. If you're giving Claude, Cursor, or an in-house agent access to Kubernetes, the tool surface has to beat raw `kubectl` on accuracy, cost, and safety. I didn't want to ship a claim I couldn't defend, so I ran the same 52-scenario Kubernetes benchmark with the same model on two tool surfaces. One arm drove raw `kubectl` through a shell. The other drove [Radar's Kubernetes MCP server](/blog/mcp-for-kubernetes-live-cluster-context-for-ai-tools). Radar won - and not only the way I expected. The agent landed a better diagnosis, and it got there doing a fraction of the work. ## TL;DR On 52 real Kubernetes fault-injection scenarios, an agent driving Radar's Kubernetes MCP server was **more accurate** than the same agent on raw `kubectl` (80.8% vs 77.6% pass rate, 0.862 vs 0.765 avg score) while using **~76% fewer tool calls, ~53% fewer input tokens, ~66% fewer output tokens, and about half the time**. The story isn't that MCP makes the agent smarter - it's that a structured visibility layer is far cheaper to reason over than raw YAML, while landing a better answer. It's the same reason humans don't debug clusters by reading `kubectl get -o yaml` all day. ## What I tested The setup was deliberately simple: same benchmark suite, same model, same goal, two tool surfaces. - **Scenarios:** SREGym - 52 real fault-injection scenarios on a live cluster. Bad DNS policies, wrong selectors, missing env vars, broken probes, auth disruptions, CPU floods, slow image pulls. Real faults, not puzzles. - **Cluster:** EKS, 3x m5.xlarge, us-east-1. - **Model:** claude-sonnet-4-6 on both arms. - **Tool surfaces:** Arm A got raw `kubectl` via Bash. Arm B got Radar's MCP. Each trial ends with the agent producing a diagnosis, scored against the known injected fault. I tracked whether it got the right answer - and how much it spent getting there. ## The numbers | Metric | kubectl | Radar MCP | Delta | |---|---|---|---| | Pass rate | 77.6% | 80.8% | +3.2 pp | | Avg diagnostic score (0-1) | 0.765 | 0.862 | +0.097 | | Avg agent time | 334s | 169s | **-49%** | | Avg tool calls / trial | 45.8 | 11.1 | **-76% (4x fewer)** | | Avg input tokens / trial | 4.9M | 2.3M | **-53%** | | Avg output tokens / trial | 3,040 | 1,039 | **-66%** | The top two rows are the diagnostic result: Radar landed the better answer. The bottom four rows are the operational result: the MCP arm got there with a quarter of the tool calls, a much smaller context bill, and half the wall-clock time. If you're paying per token or waiting on an AI-assisted Kubernetes debugging workflow mid-incident, that is the part that matters. ## Why a Kubernetes MCP server beats raw kubectl This is the part that explains the numbers instead of just reporting them. Radar's MCP is not a `kubectl` wrapper - that distinction is the whole mechanism. Give an agent raw `kubectl` and a single `kubectl get pod -o yaml` hands back hundreds of lines: `managedFields`, full status blocks, annotations, the entire object as the API server stores it. The one useful signal - an `OOMKilled` condition, a failing readiness probe - is buried in the wall of text. And the agent re-reads its accumulated context every turn, so by call 30 it's dragging a huge transcript of YAML it already parsed. That's the giant input-token count in the `kubectl` column: the same noise re-ingested turn after turn. To trace a cross-cutting fault - "this Service can't reach its pods" - a `kubectl` agent has to reconstruct the graph by hand: list the Service, read its selector, list pods, check labels, read endpoints, check the network policy, pull events, cross-reference timestamps. That's where ~46 tool calls come from. Radar hands over the already-computed answer instead. The MCP returns **minified, enriched, secret-redacted** data: pre-built topology graphs, problem-correlated timelines, deduplicated events, error-filtered logs. The agent calls `get_topology` once and gets the ownership and routing chain as a structured object; it calls the issues API and gets the causal chain - what broke, what it's connected to, what changed - instead of the raw materials to derive it. Four times fewer calls, because each call answers a bigger question, and half the context, because what comes back is signal. This is exactly the argument Roy made in ["Agents, UIs, and CLIs: The False Choice in Kubernetes Operations"](/blog/agent-or-ui-false-choice-kubernetes-operations) - a cluster is a live graph, and raw YAML is a poor way for *anything* to make sense of it, human or LLM. This benchmark is that argument with a number attached. ## Where Radar pulls ahead The averages hide a pattern. Radar's biggest wins are the faults where the symptom is far from the cause - a wrong DNS policy, a service that can't resolve, a misconfigured selector, a missing env var, a dependency failing three hops away. Radar's issues API, topology, and change feed hand the agent the causal chain already assembled; the `kubectl` agent has to trace it across dozens of calls, and often runs out of budget and guesses. Those indirect, cross-cutting faults are most of what real incident response actually is. Raw `kubectl` happened to edge ahead on a few needle-in-one-log faults. I would not over-read that as a durable advantage. Those are high-variance cases where success can come down to whether the agent opens the one right log line early. Radar also does not have to be the only tool in the agent's toolbox: if you expose shell or `kubectl` alongside Radar, the agent can still run any plain `kubectl` command when that is the right move. The difference is that it no longer has to reconstruct the cluster from raw YAML by default. ## You don't want an agent loose on raw kubectl Speed and accuracy aside, raw `kubectl` through a shell is the *ungoverned* option. The agent inherits whatever that shell can do, every call is a potential mutation, and you get no record of what it touched. Radar's MCP is the opposite by design: read tools are read-only and secret-redacted, writes are RBAC-enforced and gated so the client can prompt before anything changes, and [Radar Cloud](/blog/introducing-radar-cloud) adds the governance layer on top - an inventory of every agent and token with cluster access, the same Kubernetes impersonation a human gets, and audited tool activity for agent actions. "Cheaper and more accurate" is the benchmark result. "And you can actually let it near production" is why teams route the agent through Radar in the first place. ## Why this is the argument for an agent surface Step back and the result isn't really about AI - it's about data shape. Agents reason over Kubernetes far more cheaply, and a little more accurately, when the data is structured for them. It's the same reason we build dashboards instead of reading raw YAML: eyes need the graph rendered, and it turns out agents need the same graph modeled. So Radar is one engine that watches your clusters, with two surfaces over it. Humans consume it as a UI - still the surface most of our users live in. Agents consume it as MCP. Both need the same thing: the cluster made sense of, not just dumped. This benchmark was about the second surface, but the human-first one is still the point - we build Radar for the person staring at a cluster at 2am, and increasingly some of that work is done by an agent on their behalf. ## Run a Kubernetes MCP server against your own cluster Don't take my word for it. Radar is open source and the MCP server is on by default, so you can point your own agent at it and break something on purpose to see how it reasons. ```bash curl -fsSL https://get.radarhq.io | sh && kubectl radar ``` That gets you the UI and the MCP server in one go. Aim your agent at the MCP endpoint and watch it work a fault on a cluster you trust. --- ### The Best Kubernetes Dashboards in 2026 (Including Our Competitors) - **URL**: https://radarhq.io/blog/best-kubernetes-dashboards-2026 - **Date**: 2026-06-13 - **Author**: Nadav Erell, CEO, Skyhook - **Category**: Open source - **Tags**: kubernetes, dashboard, comparison, open-source, tools Let's get the disclosure out of the way: we build Radar, one of the tools on this list. You should weigh everything below accordingly. We've tried to make this the list we wish existed when we were evaluating - including being clear about where the other tools beat ours. Some context for why this list looks different from the 2024 version of every "best Kubernetes dashboard" post: the official **Kubernetes Dashboard was retired in January 2026** - archived, unmaintained, no more security patches. Thousands of clusters are quietly running an EOL web UI right now. If that's you, the question isn't *whether* to move, it's where. Here's the field, organized by what you're trying to do. ## TL;DR - pick by use case | You want... | Pick | |---|---| | The fastest tool for terminal people | **k9s** | | A semi-official, vendor-neutral project (governance over features) | **Headlamp** | | One shared web view with topology, history, and GitOps in core | **Radar** (ours) | | Lens, but without the subscription | **Freelens** | | Docker + Swarm + K8s in one platform | **Portainer** | | A commercial desktop IDE anyway | **Aptakube**, or **Lens** if you want its team-collaboration layer | ## 1. k9s - the terminal standard **Apache 2.0 · ~34k stars** If everyone who needs cluster visibility at your org is comfortable in a terminal, install k9s and stop reading. It's keyboard-first, instant, and has earned every one of its stars. Resource browsing, logs, exec, port-forwards - all faster than any web UI on this list, ours included. What it isn't: a dashboard you can hand to someone who expects a URL. No topology, no shared views, no history. Most teams we talk to run k9s *and* a web UI - they solve different moments. ## 2. Headlamp - the semi-official option **Apache 2.0 · ~6.6k stars · Kubernetes SIG UI** Headlamp's real selling point is governance. SIG UI named it the recommended Dashboard replacement, it's vendor-neutral, and it'll outlive any single company's roadmap. If a semi-official project is a hard requirement for your org, that's a legitimate reason to pick it, and the only one we'd lean on. As a tool, it's a resource browser with a basic built-in resource map, extended by a plugin catalog. The official plugins are real and growing - Flux, OpenCost, Prometheus, Helm (app catalog), cert-manager, KEDA, Karpenter, and an alpha AI assistant (BYO model key) - but you install and version each one yourself, and the catalog has real gaps. GitOps is Flux-only: there's an official Flux plugin but no Argo CD plugin in the headlamp-k8s catalog. There's nothing for service-traffic flow, and nothing for a persistent event timeline. It replaces what Dashboard was; it doesn't change what Dashboard wasn't. ## 3. Radar - ours, so judge accordingly **Apache 2.0 · ~2.4k stars · single Go binary** Radar is what we wanted during incidents: one tool with the resource browser *plus* the things you reach for when something's on fire - live topology, an event timeline that persists past the API server's ~1 hour memory, log streaming, exec, Helm management, GitOps status for ArgoCD and Flux, traffic visibility, and a 31-check best-practices audit. In core, not as plugins. The coverage also runs unusually wide: it renders 120+ ecosystem CRDs as typed views and topology edges - Argo CD, Flux, Istio, Karpenter, cert-manager, KEDA, Prometheus, Trivy, Crossplane, Velero and more - all compiled into the binary, not bolted on as plugins. The generic browsers here just show you the raw object; Headlamp covers a chunk of this, but only after you install and version each plugin yourself. On AI, Radar skipped the bundled chatbot and bet on agents instead: it ships [an MCP server](/blog/mcp-for-kubernetes-live-cluster-context-for-ai-tools) - free, on by default, with read tools purpose-built for cluster context - so the agent you already use (Claude, Cursor, your own) reasons over live cluster state directly. Lens and Headlamp are adding AI of their own, but we deferred an in-app chat on purpose. The numbers back the bet: in our SREGym benchmark, the same model diagnosed 52 broken-cluster scenarios through Radar's MCP instead of kubectl - about half the agent time, a quarter of the tool calls, two-thirds fewer output tokens, and slightly higher diagnostic accuracy. The mechanics: `brew install skyhook-io/tap/radar`, then `kubectl radar` - a single compiled binary that reads your kubeconfig and opens a browser, zero cluster-side install. Run it locally, as the desktop app, or as a shared in-cluster instance with SSO and RBAC that respects each viewer's real cluster permissions - not the per-laptop-kubeconfig world the desktop clients live in. The one tool on this list we recommend without reservation alongside Radar: k9s. If you live in the terminal, it's faster, and plenty of our own users run both. ## 4. Freelens - Lens without the license **MIT · ~5.1k stars** Lens moved exec, logs, and shell into proprietary code in 2023 and requires a paid per-user subscription for commercial use. Freelens is the actively maintained community fork that restored what the open builds lost. You get the familiar Lens layout - multi-cluster switching, resource views, live metrics (with metrics-server installed), and the exec/logs/shell OpenLens dropped - and most Lens extensions still load. If your team likes the desktop-IDE model and your only problem is the subscription, this is the shortest move: same Electron architecture, same per-laptop kubeconfig world. (Weighing the whole Lens-exit decision? We compared [every Lens alternative](/lens-alternative) in one place.) ## 5. Portainer - when Kubernetes is only part of the estate **Open-core · ~38k stars** Portainer is broader than everything else here: Docker, Swarm, and Kubernetes under one roof, with its own RBAC, teams, app templates, and git-based deployments - plus an edge agent that reaches remote or air-gapped clusters. The free Community Edition covers most of that; the Business Edition adds org-scale access controls. For mixed container estates - especially ones with a hosting/homelab flavor - that breadth is the point; for a Kubernetes-only platform team it's more platform than you need, and the K8s-native views are shallower than the focused tools here. ## 6. Lens - the incumbent **Proprietary (MIT core repo) · ~$22-35/user/mo for commercial use** Lens's strengths: it's stable, it's been around since 2016, and a lot of engineers have muscle memory in it. It also bundles two things the open desktop clients here don't - Lens Teamwork, a cloud layer for shared team spaces and access control, and Prism, a built-in AI chat panel for natural-language troubleshooting. The AI piece is no longer a differentiator, though - Headlamp ships an assistant plugin too, and Radar's MCP route (above) skips the in-app bot entirely. That's where the credit ends. You're paying per seat, per month, for a per-laptop Electron app whose open-source story collapsed in 2023 when exec, logs, and shell moved into proprietary code - and everything you're paying for, minus Lens Teamwork, is available free elsewhere on this list. If muscle memory is the tie-breaker, Freelens keeps it without the invoice. [Detailed comparison](/vs/lens) if you want it line by line. ## 7. Aptakube - the indie desktop client **Closed source · paid per seat** Credit first: it's a real native app rather than an Electron bundle, it starts fast, and the side-by-side multi-cluster tabs are excellent UX - impressive for a solo-developer project. If you specifically want a paid native desktop client, it's the better-executed version of that idea than Lens. The limits are structural rather than quality: closed source, per seat, per laptop, single user - nothing shared, no history. Whether that matters depends entirely on whether you're tooling up yourself or a team. ## What about the old Kubernetes Dashboard? Don't start there in 2026 - it's archived and unpatched. If you're migrating off it, we wrote a [dedicated migration guide](/kubernetes-dashboard-alternative) covering all the successor options, including the official one. ## How to actually decide Three questions settle it faster than any feature matrix: 1. **Who consumes it?** Terminal people → k9s. Engineers plus everyone else → a web UI (Radar, or Headlamp if vendor-neutral governance outranks features for you). Desktop-IDE devotees → Freelens. 2. **Do you need memory?** If "what happened at 3am?" is a question you ask, you need persisted event history - that's Radar's core bet, and largely unaddressed elsewhere on this list. 3. **Assembled or assembly kit?** Headlamp gives you governance and a plugin kit you assemble; Radar ships the integrated set in one binary. Both are Apache 2.0 - trying both takes one afternoon. If we've misrepresented any tool here, [email us](mailto:radar@skyhook.io) and we'll fix it. --- ### SSO and RBAC Without Passing Around Kubeconfigs - **URL**: https://radarhq.io/blog/sso-and-rbac-without-passing-around-kubeconfigs - **Date**: 2026-06-11 - **Author**: Roy Libman, CPO, Skyhook - **Category**: Platform - **Tags**: radar-cloud, sso, rbac, platform-engineering, identity A contractor starts Monday. They need read-only access to your staging cluster for a four-week engagement. Nothing more. Without something better than kubeconfigs, this is a ticket that bounces between you, IT, and security for a week. Someone generates a kubeconfig. Someone else argues about whether to create a dedicated ServiceAccount or reuse one. Security asks how you'll revoke when the contract ends. Nobody has a clean answer. The contractor spends their first three days reading docs. Radar Cloud's access model is built around a different split: - **Cloud authenticates the human** and decides which org they belong to. - **The in-cluster Radar pod impersonates** that human's Cloud role against the Kubernetes API. - **Kubernetes RBAC decides** what the request can actually do. No shared kubeconfig to pass around. ![Radar RBAC](/images/blog/radar-rbac-hero.png) ## Why kubeconfig falls apart at team scale Kubeconfig wasn't designed for this. It was designed for an operator with a laptop talking to a cluster. Everything that's awkward about it for teams is a consequence of using it past that point. - **Client certificates are long-lived by default.** Once minted, they sit in someone's `~/.kube/config` until they expire. Revoking a leaked cert means rotating the cluster CA, which nobody does. - **Scoping is a RoleBinding exercise.** You can do it, but you end up with a matrix of ServiceAccounts, Roles, and RoleBindings across clusters. For a fleet of ten clusters, that's ten places to update when someone changes teams. - **No native link to your IdP.** Your company already has Okta or Entra ID. Kubeconfig doesn't know anything about it. You can wire OIDC into the API server, but that's per-cluster plumbing, and it still doesn't give you group-to-role mapping for free. - **Audit trails are thin.** API server audit logs tell you that `kubernetes-admin` did a thing. They don't tell you which human that was, unless you've done the OIDC work above. This isn't a criticism of Kubernetes. Kubeconfig is fine for what it is. It's just that "onboard a contractor in an hour with scoped, revocable, auditable access" isn't what it's for. ## How Radar Cloud handles it Two ideas, both boring on purpose. **SSO is the front door.** Radar Cloud uses WorkOS as its identity-provider abstraction. SAML and OIDC, including Okta, Entra ID, Google Workspace, OneLogin, and any spec-compliant SAML / OIDC provider. The setup is self-serve: an owner clicks **Set up SSO** in the dashboard, lands in the WorkOS Admin Portal, configures the IdP there, and saves. We don't sit between you and your IdP for setup. SSO is available on every plan, including Free - it's not an "enterprise upsell" gate. **Cloud roles map to standard Kubernetes RBAC via impersonation.** This is the part that surprised some early users in a good way. Radar Cloud doesn't invent a parallel permission system. It maps each user's Cloud role (`owner`, `member`, `viewer`) to a Kubernetes group and lets the in-cluster Radar pod impersonate the user when it talks to the API server. The Helm chart ships three default ClusterRoleBindings out of the box: | Cloud role | Group | Bound to ClusterRole | |---|---|---| | Owner | `cloud:owner` | `admin` | | Member | `cloud:member` | `edit` | | Viewer | `cloud:viewer` | `view` | Standard K8s built-in ClusterRoles. Nothing custom. If you trust `view`, you trust Viewer. If `edit` is too broad for your members, swap the binding to a custom ClusterRole - it's two lines in `values.yaml`. ```yaml cloud: defaultRbac: create: true # emit the default bindings member: true # keep the cloud:member binding memberClusterRole: my-edit # but map it to your custom ClusterRole ``` To disable a tier entirely (e.g. owners only, no members or viewers), set the flag to `false`: ```yaml cloud: defaultRbac: member: false viewer: false ``` ## What the request actually looks like When a Cloud user clicks into a cluster, the control plane strips inbound `X-Forwarded-*` headers (so they can't be spoofed) and injects: ``` X-Forwarded-User: user_01HF... X-Forwarded-Groups: cloud:viewer,cloud:org:org_01H...,cloud:user:user_01HF... ``` The in-cluster Radar pod runs in proxy auth mode, sees those headers, and impersonates the user against the K8s API. Whatever permissions you've granted the `cloud:viewer` group (or that specific user via the `cloud:user:...` group) is exactly what they can do. K8s does the gatekeeping. We don't. If you need finer control - say, "Alice can edit Deployments only in the `apps-prod` namespace" - you bind directly to her per-user group: ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: alice-apps-edit namespace: apps-prod subjects: - kind: Group name: cloud:user:user_01HF... apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: edit apiGroup: rbac.authorization.k8s.io ``` That's a regular K8s RoleBinding. `kubectl get rolebindings` works, your existing RBAC tooling works, audit policies on the apiserver capture impersonated calls with the user ID and groups intact. The blast radius is also easy to reason about: the Radar pod's ServiceAccount is the upper bound, and Kubernetes impersonation narrows each request to the user or role that made it. ## The contractor, end to end Monday morning: 1. **IT adds the contractor to your Okta tenant.** They get JIT-provisioned into your Radar org on first SSO sign-in - that's WorkOS doing the work. 2. **Owner sets their role to Viewer.** That's one click in **Settings → Members**, or automatic via domain auto-join + default role. 3. **The contractor signs in.** They land on the cluster list, see the staging cluster you've granted them access to, and can read - resources, topology, events, audit findings, Helm releases. They cannot exec, cannot edit, cannot delete. K8s says no, because `cloud:viewer` is bound to `view`. 4. **Four weeks later, IT removes them from Okta.** Their next sign-in attempt 403s. Existing sessions die at cookie expiry; if you need an immediate cut, **Settings → Members → Remove** kills the server-side session right away. Total Radar work for this onboarding: zero, after the initial setup. Everything else is an IdP operation IT already knows how to run. ## SCIM and time-bounded access Two things worth being explicit on. **SCIM 2.0 directory sync** ships on Enterprise. JIT provisioning works on every plan - the first SSO sign-in creates the Cloud user and adds them to the org if domain auto-join is configured. For teams that need directory-driven user and group lifecycle from their IdP (often for compliance or procurement), SCIM is the upgrade path. **Time-bounded access** ("Admin for the next four hours, then auto-revert") isn't shipped natively yet. The workaround is the IdP one - add to a group, remove when done. It works. It's just not as clean as a one-click ephemeral grant. On the roadmap. ## Audit Every authentication event, scope change, and write operation lands in the Cloud audit log. Retention scales with plan: 7 days on Free, 30 days on Team, 1 year on Enterprise. K8s audit policies capture the impersonated calls separately, so you can correlate "user X did Y in Cloud" against "user X impersonation hit endpoint Z in the apiserver" if you need full provenance. What's not in the audit log: every read click. We log write operations, scope changes, sign-ins, and SSO config changes. We don't log "Alice opened the Pods view and scrolled." ## The shape of it Onboarding a teammate to a Kubernetes cluster should be an IdP operation, not a kubeconfig-distribution project. The reason it usually isn't is that most teams layered their access tooling on top of `~/.kube/config` and never went back to reconsider. Radar Cloud moves the decision to where your identity already lives - your IdP - and lets standard K8s RBAC do the gatekeeping in the cluster, not a parallel permission system in the dashboard. Less novel infrastructure, fewer places for things to drift, and a cleaner answer when someone asks "who has access to prod, and how do you revoke it?" If you want to try it, the Free tier covers up to three clusters and includes SSO. Set it up in **Settings → Organization → SSO** - the WorkOS portal walks you through your IdP from there. --- ### Why We Priced Radar Per Cluster, Not Per Seat - **URL**: https://radarhq.io/blog/why-per-cluster-pricing - **Date**: 2026-06-09 - **Author**: Roy Libman, CPO, Skyhook - **Category**: Platform - **Tags**: radar-cloud, pricing, saas, go-to-market, platform-engineering A platform lead we talked to last month runs a fleet of nine clusters with a team of twelve. Their incumbent "Kubernetes management" vendor quoted her $1,500 per seat per year. Twelve seats. $18,000. But that number only covers the twelve people on her team today. The on-call engineer from the partner team who gets paged once a quarter? Another seat. The security reviewer who wants to audit the cluster once a year? Another seat. The CFO who wanted to see what they were paying for? You can imagine. She did the thing every sensible engineering leader does: bought six seats, shared logins with the rest of the team, and disabled audit logs so it wouldn't show up in reviews. That's the outcome per-seat pricing creates. Not "more revenue per customer." Shared logins, broken audit trails, and a vendor that's quietly hostile to the job it's sold to do. When we priced Radar Cloud, we ruled out per-seat on day one. Here's the rest of the thinking. ## TL;DR Radar Cloud is priced per cluster, not per seat. Free for up to three clusters. $99 per cluster per month on Team. Custom on Enterprise. A visibility tool gets more valuable the more people look at it, so pricing that punishes adoption is pricing at war with the product. Per-cluster aligns with our actual costs (we run one tunnel and one cluster's worth of registry / audit / billing state per connected cluster) and with the thing you care about (how much infrastructure you're monitoring). It's not the right model for every customer - we'll be honest about that below. ## The five models we compared Every pricing decision is a choice between bad options. We sketched five on a whiteboard. | Model | Scales with | Predictable? | Fair at growth? | Hostile to adoption? | |-------|-------------|--------------|-----------------|----------------------| | Per seat | Team size | Yes | No | Yes | | Per cluster | Fleet size | Yes | Mostly | No | | Per node | Node count | Sometimes | No | No | | Per event / per GB | Cluster chaos | No | No | No | | Flat tiers by feature | Whatever we pick | Yes | Depends | Neutral | Each has a real argument for it. Here's why we landed where we did. ## Why not per seat The pitch for per-seat is simple: it's how most SaaS is priced, buyers understand it, and your revenue scales with the customer's team. The problem is that it scales against what Radar is actually for. A visibility tool is worth more when more people can look at it. The on-call engineer who didn't deploy the thing that broke at 3am needs the dashboard more than the engineer who did. The security reviewer running a quarterly check. The manager who wants to see cluster health before a steering committee. The new hire trying to build a mental model of prod. Per-seat pricing turns every one of those people into a line item someone has to justify. The outcomes we saw in the wild: - **Shared logins.** We've interviewed teams who share a `devops@company.com` credential across ten people because the seat math doesn't work otherwise. Audit logs turn into "devops@ did it." - **Procurement friction for new hires.** Onboarding a new engineer should be a `helm install` and a Slack invite. Not a purchase order. - **The "we forgot about bob" bill.** Someone leaves, nobody remembers to deprovision, and the renewal has line items for people who haven't logged in for a year. The worst part: per-seat incentivizes us to make the tool harder to use without an account. The opposite of the thing we want. ## Why not per node Per-node sounds like it tracks infrastructure scale. It doesn't. We ran the numbers on a hundred real clusters from our beta cohort. The 90th-percentile cluster had 47 nodes. The 99th had 340. Meanwhile the p50 cluster had 9 nodes. Under per-node pricing, a customer with one beefy 200-node cluster running a correctly-tuned HPA would pay the same as one running ten small-and-wasteful 20-node clusters. That's backwards. The HPA team is doing the right thing. Our cost of running Radar Cloud doesn't scale linearly with node count either. Radar watches the Kubernetes API server, not the nodes. Watching a 50-node cluster and a 500-node cluster costs us roughly the same in tunnel bandwidth and control-plane state - the object count grows sublinearly with nodes for most workloads. Per-node would punish customers for infrastructure they don't care about. ## Why not per event or per GB This is the Datadog model and it's the one that produces the worst end-of-quarter conversations in our industry. The whole point of Radar is to surface the events you didn't know about. If those events cost you money, you're incentivized to drop your retention, mute your alerts, and generally let less signal through. We want exactly the opposite behavior. A pod in CrashLoopBackOff should get *more* eyes on it, not less, and the billing department shouldn't be the reason your incident got harder to debug. Per-event pricing also makes bills impossible to predict. A bad deploy that generates 40,000 events in an hour is already a bad day. It shouldn't also be an invoice shock next month. ## Why not flat feature tiers "Radar Starter, Radar Pro, Radar Enterprise, $x / $y / $z" is the path of least resistance. We have tiers - Free, Team, Enterprise - but the axis we price on inside those tiers is still per-cluster. Flat-fee tiering has two failure modes. The first is that a two-cluster customer and a forty-cluster customer pay the same, which is absurd on both ends: the small customer overpays for capacity they don't use, the large customer gets a windfall we can't afford. The second is that sales conversations devolve into negotiating what's in each tier. We'd rather the conversation be "how many clusters?" than "can we add SAML to Team for $50 extra?" ## Why per cluster won Three reasons, in decreasing order of importance. **It aligns with our costs.** For every cluster connected to Radar Cloud, we hold open one long-lived WebSocket tunnel, route browser requests through it, and store one cluster's worth of registry, audit, and billing state in our control plane. When a customer adds a cluster, our cost goes up roughly linearly. When they add an engineer, our cost goes up by zero. Pricing that matches cost isn't greedy - it's how we avoid a subsidy war between small customers and large ones. **It aligns with customer value.** Ask a platform lead "what does Radar save you?" and the answer is usually something like "we catch bad deploys in staging before they hit prod." That value doesn't scale with team size. It scales with how much infrastructure is under observation. One cluster = one production surface where something can break. That's the thing we should charge for. **It rewards broad adoption.** A $99 monthly bill that lets your entire team (and the on-call rotation, and the security reviewer, and the skeptical manager) into the dashboard produces dramatically better outcomes than a $99 bill that gets shared across two seats. The tool works when more people look at it. Our pricing should pay for that, not tax it. ## Where per-cluster is a worse deal I'd rather tell you this than have you discover it. **If you run one giant cluster.** A single 400-node cluster with 30 tenants feels under-priced at $99/month on Team, because per-cluster pricing doesn't care how big the cluster is. That's a legitimate "we're getting a great deal" for the customer - and fine by us, because our cost is still the per-cluster cost. **If you run many tiny dev clusters.** The flip side. A team with ten short-lived `kind` clusters for CI runners pays as much as a team with ten prod clusters. We're watching this and considering a "dev cluster" discount if the usage data says to, but we haven't landed on clean criteria that couldn't be gamed. For now: if you have a fleet of ephemeral CI clusters, pin them through one long-lived Radar-connected cluster or talk to us. **If you need SCIM but have one cluster.** SCIM 2.0 provisioning ships on Enterprise, which is custom-priced. For a single-cluster team that happens to need SCIM for IT-automation reasons (SAML / OIDC SSO itself is on every plan at published pricing), that's a painful jump from Team. We know. If this is you, talk to us - we've been doing one-off custom plans on a case-by-case basis while we figure out whether it's the tier or the price that needs to flex. ## What will change the pricing We're not precious about any of this. We'll revisit per-cluster if the data shows it misallocates cost - if one customer's cluster is consistently ten times more expensive to run than the average, or if the "dev cluster" complaint turns into a real pattern instead of an edge case. We'll revisit the tier prices if our infrastructure costs shift materially. We'll grandfather existing customers when we do. We'll announce changes in the blog, not in an email nobody reads. One thing we won't change: visibility tools get better when more people look at them. That's the whole product. It's also why per-seat was off the table before we had a pricing meeting. If you're evaluating Radar Cloud and the pricing math feels off for your specific fleet shape, tell us. We'd rather know. --- ### Why Radar Cloud Doesn't Cache Your Cluster State - **URL**: https://radarhq.io/blog/why-radar-cloud-doesnt-cache-your-cluster-state - **Date**: 2026-06-06 - **Author**: Eyal Dulberg, CTO, Skyhook - **Category**: Engineering - **Tags**: radar-cloud, kubernetes, architecture, security, multi-cluster The default architecture for a multi-cluster Kubernetes dashboard is: agent in every cluster, agents push state to a backend, backend stores a replica per cluster, UI reads from the backend. That's the shape of most products in this category. We picked the opposite shape. ## The rule Radar Cloud does not maintain a hosted copy of your Kubernetes resource state. The Radar binary runs in each connected cluster. When you open a cluster in the Cloud UI, the browser talks to the Radar Cloud control plane, the control plane authenticates you, and the request is reverse-proxied over that cluster's existing outbound WebSocket to the in-cluster Radar pod. The in-cluster Radar answers from the same live engine the OSS binary uses: informers, topology builders, timeline storage, Helm readers, GitOps integrations, audit checks, and MCP handlers. **Cloud owns the team layer. The cluster owns the cluster data.** ![Radar Cloud architecture - reverse proxy, no server-side cache](/images/blog/radar-agent-architecture.png) ## The shape of the connection In-cluster Radar opens one outbound TCP connection to `api.radarhq.io:443`, negotiates TLS, upgrades to a WebSocket, authenticates with a cluster-scoped bearer token, and runs [yamux](https://github.com/hashicorp/yamux) for stream multiplexing on top. When a browser asks Radar Cloud for "Pods in namespace `prod`": 1. The control plane authenticates the user against the org and cluster. 2. It strips inbound `X-Forwarded-*` headers (anti-spoof). 3. Injects `X-Forwarded-User` and `X-Forwarded-Groups: cloud:,cloud:user:,...`. 4. Opens a fresh yamux stream over the existing WebSocket. 5. Forwards the HTTP request through that stream to the in-cluster Radar pod. 6. The pod runs the request against its local SharedInformer cache, with the user impersonated on the K8s API. 7. The response flows back through the same stream. Logs, exec sessions, MCP tool calls, port-forwards - all the same machinery. Different streams, same WebSocket. Nothing is written to disk on the control plane side. Nothing is mirrored into a database for "fast queries later." Live K8s state is the answer; the control plane just brokers access to it. ## What lives in Cloud, what stays in the cluster The control plane does have a database. It stores things that genuinely belong on the SaaS side. | Cloud data | Cluster data | | --- | --- | | Users, orgs, members, roles, invitations | Resources and CRDs | | Cluster registry metadata (id, name, env, labels, status) | Topology and traffic views | | Cluster token hashes | Kubernetes events and the Radar timeline | | Billing and subscription state | Helm releases and GitOps state | | Org-scoped audit log | Logs, exec sessions, port-forward streams | | Personal access tokens, notification preferences | Cluster audit findings | | Slack and webhook destinations | MCP tool responses | When Cloud needs anything in the right column, it asks the connected Radar pod. The pod reads the cluster and responds over the tunnel. Disconnected cluster? The Cloud UI shows it as not reporting. We do not serve a stale hosted snapshot and pretend it is fresh. ## Why we picked this shape Three reasons, in decreasing order of importance. ### Live state is more correct than cached state A backend that mirrors your cluster is always racing the source of truth. Radar (the in-cluster pod) already maintains a SharedInformer cache fed by the K8s Watch API - that's the right tier to cache at. Mirroring it again on the SaaS side gives you a copy that's always 200ms (or 5s, or 30s) older than the cluster's own cache. Most of the time you don't notice. The times you do notice are during incidents, when a stale view actively misleads you. We'd rather pay the millisecond round-trip through the WebSocket and serve you what the API server believes right now. ### The blast radius if we're compromised is bounded The control plane never holds your cluster contents. If someone gets into our backend, they get: org metadata, audit history, billing records. They don't get a database-shaped snapshot of every customer's pods, ConfigMaps, and resource state. The auth boundary is also clean. The cluster-scoped bearer token validates the WebSocket once at handshake time. Per-request, the control plane injects user identity into the request headers, but the K8s API decides what's allowed - we don't have a parallel permission system that could leak access. A compromised control plane can't exceed what the cluster's own RBAC permits, because every read and write goes through K8s impersonation. ### Multi-tenant cost is sane If we held a server-side replica per connected cluster, our backend cost would scale with the cumulative object count across the entire fleet. A handful of customers with chatty CRDs (or accidental ConfigMap regeneration loops) would dominate our hosting bill, and we'd end up either rate-limiting noisy clusters or eating the cost. Reverse-proxy cost scales with active browser sessions, not with cluster size. A 5,000-pod cluster sitting idle costs us roughly the same as an empty one. That's why we can charge per-cluster instead of per-node or per-event - our cost model and yours line up. ## What we give up This isn't free. There are real tradeoffs. **The dashboard depends on the in-cluster pod being reachable.** If the WebSocket drops, the cluster card goes "disconnected" in the UI and you can't drill into it until the pod reconnects. We send a notification when this happens (`cluster.disconnected`). For a hosted dashboard built on a server-side cache, you'd at least see stale data; with us, you see nothing for that cluster until it's back. This is a tradeoff we accepted because (a) Radar reconnects with exponential backoff and the typical disconnect is brief, and (b) "stale data that looks fine" is actively dangerous during an incident. Honest unavailability beats deceptive freshness. **Some queries that would be cheap against a server-side cache aren't free here.** "Show me everything across the fleet that's failing" goes wide-fan-out: the Hub opens a stream to each connected cluster, each pod answers from its local cache, the Hub aggregates. That works fine for tens of clusters and is sub-second; for a hundred or more clusters, the initial fleet-view load takes a few seconds with progressive rendering. It's slower than a pre-aggregated dashboard would be. We'd rather be a few seconds slower and tell you the truth. **Cross-cluster topology and cross-cluster timeline don't exist yet.** The architecture doesn't preclude them - the data is reachable through the same multiplex - but they're meaningful product surface to build, and we've explicitly listed them under "what's NOT here today" in the docs. They're on the roadmap. We're not pretending they ship. ## Where the persistent timeline lives In-cluster Radar can persist its event timeline to SQLite at `~/.radar/timeline.db`, backed by a soft retention budget set with `--history-limit`. With SQLite and a PVC, events survive pod restarts and can give you a multi-day local history. That's where event history "outlives the process restart" actually happens - in the cluster, not in our backend. If you need longer or organization-wide timeline retention than that, the right answer today is to ship events to a SIEM or your existing log / event backend. We're not going to be a system of record for cluster events. We're a UI plane that gives you the right view of the live thing. ## What this does not mean It does not mean Cloud has no audit log. Cloud keeps an org-scoped activity log for Cloud actions: cluster registration, token rotation, member changes, invitations, SSO setup, PAT lifecycle, billing changes, and sign-ins. That audit log is stored in Postgres with plan-based retention. It does mean Cloud audit logs are not Kubernetes audit logs. If someone scales a Deployment inside a cluster, Kubernetes remains the system of record for that API call. Radar Cloud records the Cloud-side action boundaries; the apiserver records in-cluster impersonated operations if you have Kubernetes audit logging enabled. ## The short version The boring pitch for this architecture is: the K8s API server is the source of truth, the in-cluster Radar pod is the cache that's already correct, and the control plane's job is to authenticate humans and route their requests. Adding a third copy on the SaaS side would either be wrong (stale) or expensive (kept fresh at scale) or both. If you're evaluating Radar Cloud against tools that ship a server-side replica, the questions worth asking are: **how stale can the replica get during an incident, what happens to my data if the vendor is breached, and whose budget pays when one of the clusters gets noisy?** Those answers are why we picked the shape we did. --- ### Agents, UIs, and CLIs: The False Choice in Kubernetes Operations - **URL**: https://radarhq.io/blog/agent-or-ui-false-choice-kubernetes-operations - **Date**: 2026-06-05 - **Author**: Roy Libman, CPO, Skyhook - **Category**: Platform - **Tags**: radar, radar-cloud, mcp, ai-agents, kubernetes Several active debates in Kubernetes operations all sound binary. The loudest one right now is agent-vs-UI. Do you go agent-first, with an AI assistant in Slack handling most of what humans used to do in a dashboard? Or stay UI-first, because production debugging is a job for eyes-and-cursor and you don't trust an agent to drive it? The older debates haven't gone away either. Plain `kubectl` versus a TUI like `k9s` - one camp loves the scriptability, the other refuses to give up the live interactive view. Terminal-first versus dashboard-first - is a web UI a luxury or a necessity? Each of these arguments has long-standing camps with strong opinions, and each one quietly asks you to pick a side. The common thread: all of these debates assume you have to pick one surface. For almost every team we work with, the honest answer is "all of them, depending on the moment" - and the right question to ask of a tool is whether the surfaces you reach for, the visual one and the agent one, are actually good at making sense of the cluster, not just at displaying it. **TL;DR.** Kubernetes operators work across three surfaces - CLI, UI, and AI agent - and each wins at a different job. `kubectl` already owns the CLI; nobody needs a second one. The catch: a cluster is a large, constantly changing graph of related objects, sprawling across a huge third-party ecosystem - and raw YAML from the terminal is a poor way to make sense of it, whether you're a human or an LLM. The two higher-level surfaces, a visual UI and a structured agent layer, are where that sense-making should happen, and most tools do them badly. That's what Radar set out to fix, while leaving `kubectl` exactly where it is. ## Each surface earns its place The first step is to stop ranking the surfaces. Each one has a legitimate, durable reason to exist. **The CLI is for speed and muscle memory.** When you know exactly what you want, `kubectl get pods -n checkout-prod -o wide | grep CrashLoop` is faster than any UI. CLIs are scriptable, pipeable, automatable, and replayable - the foundation of everything from break-glass procedures to CI pipelines. They reward expertise. Serious operators live in a terminal for a meaningful fraction of their day. **The UI is for navigation and pattern recognition.** Kubernetes state is dense, hierarchical, and fast-changing. A good UI lets you scan a topology, spot an outlier pod, drill into its logs, and flip back to the timeline in three keystrokes. The bandwidth of eyes-on-a-screen for "what is going on across this cluster?" is hard to beat - especially at 2am, when you do not yet know what you are looking for. **The agent is for summarization and natural-language access.** A meaningful slice of Kubernetes operations is not pattern recognition; it is "summarize what changed in the last 20 minutes," "tell me which of these alerts are related," "explain why this deployment is failing readiness." That work is genuinely a fit for LLMs. Teams that have moved routine triage into Slack-resident agents have gotten real leverage out of it. These three pictures are not in conflict. They describe different jobs: | Surface | Best at | Weakest at | |---|---|---| | CLI | Speed, scripting, automation, deep familiarity | Discovery, cross-cutting views, onboarding | | UI | Visual scanning, navigation, deep-linking, "what is happening?" | Repetition, batch operations, automation | | Agent | Summarization, natural language, correlation across noisy state | Precision, trust at the sharp end, repeatability | ## The pattern we see in the field Across the teams we work with, three archetypes show up repeatedly, and all three are reasonable. **CLI-anchored teams** are often infra-leaning and deeply experienced - they have been operating Kubernetes from a terminal since before there were good dashboards, and the muscle memory is real. The stance has become a bit old-school, though: a UI gets installed grudgingly and rarely opened, an agent is dismissed as autocomplete for people who do not know `kubectl`. The risk is staying there by default and missing what the other surfaces are actually good at. Teams from this camp that give the UI and the agent an honest try almost always end up using all three, because cross-cutting views and natural-language summarization do not compete with terminal expertise - they compound with it. **UI-anchored teams** are often platform or developer-experience focused. They want a single pane that is easy to onboard a new engineer into. They rely on dashboards for incident response and for self-serve developer workflows. **Agent-leaning teams** have an internal AI assistant wired into Slack, docs, metrics, the IDP, and the cluster. Developers stop touching clusters directly; most everyday questions get asked in natural language. These teams move fast and the assistant absorbs a lot of toil. Most real organizations are a mix of all three. The infra side keeps the CLI. The SRE side reaches for the UI during incidents. Some subset of the team is increasingly conversational with an AI assistant. People reach for what is convenient for the task in front of them, and that should be fine. ## The hard part is making sense of the graph A Kubernetes cluster isn't a list of objects; it's a live, interconnected graph. A Deployment owns a ReplicaSet owns Pods. A Service selects some of those Pods, an Ingress routes to the Service, ConfigMaps and Secrets feed the containers, an HPA scales the workload, and a GitOps controller owns the whole thing. Then the third-party ecosystem piles its own CRDs and operators on top - Argo, cert-manager, Cilium, KEDA, half the CNCF landscape - each with its own objects and relationships. And all of it changes by the second. Watch someone debug a 2am incident and what they are really doing is reconstructing a slice of that graph in their head. They want: - Pod state now, and pod state three minutes ago, before the bad thing happened. - Events for the namespace, filtered to the last 20 minutes. - Recent Deployment changes from the GitOps controller. - The last 200 lines from the three pods that crashed. - Topology - what talks to what. - Cluster context: nodes, capacity, the network policies in front of the failing service. The CLI hands all of this back as raw YAML and flat text and leaves the reassembly to you. That is a fine trade when you know the one object you want. It is a bad trade when you are trying to understand how a dozen related objects are interacting - which is most of incident response, and most of onboarding. That is the gap the higher-level surfaces exist to close. A human needs the graph rendered - topology, timelines, ownership chains, health rolled up - so the eye can do the pattern-matching it is good at. An agent needs it structured and enriched - not the same noisy YAML dumped into a context window, but a model of the graph it can actually reason over. The argument was never "agent or UI." It is which of those two does less to fight you on the task in front of you - and whether either is actually better than squinting at `kubectl` output. ## What we built, and why `kubectl` is the CLI. It is excellent, it is not going anywhere, and we had no interest in shipping a worse one. What teams were missing was the other two surfaces done well, on the same foundation. So when we open-sourced Radar, we shipped two front ends on a single backend: - **A web UI** - topology, event timeline, service traffic, resource browsing, logs, exec, Helm and GitOps - served by the single Radar binary you launch with `kubectl radar` (or the desktop app, no terminal at all). - **A Model Context Protocol (MCP) server**, so any compliant agent (Claude, Cursor, in-house bots) reads the same cluster state through tool calls - deliberately *not* raw `kubectl`. Radar's MCP returns token-optimized, enriched data (topology graphs, health assessments, deduplicated events, scrubbed logs), is read-only by default with write tools gated behind RBAC, and never exposes Secret values. That is the layer agents actually need and raw `kubectl` can't give them. Both are built on the same SharedInformer-backed model of the cluster graph, with the same access controls, and both sit alongside the `kubectl` you already use. We did not build the UI and the MCP server to settle the agent-vs-UI debate. We built them because the existing options on both surfaces were thin - dashboards that list resources without showing how they connect, and "AI integrations" that just pipe raw `kubectl` into a model - and a graph this tangled deserves better than that on either surface. The reaction has been the most informative part. The teams that have responded most to Radar are not the people who care most about any single surface. They are the people who refuse to pick - the platform leads who were tired of dashboards that barely beat `kubectl get` and agents that choke trying to reason over raw YAML. ## What this looks like on a real incident Imagine the 2am page. A user-facing API is returning intermittent 503s. Here is how the incident plays out when no surface has been pre-empted: 1. **CLI.** The on-call engineer hits the terminal first, the way everyone does: `kubectl get pods -n checkout-prod`. Three pods in CrashLoopBackOff. That is all kubectl needs to tell them - it is fast and it is right there. 2. **UI.** To see *why*, they open Radar, deep-linked to that pod, and scroll the timeline. There it is: a Deployment 12 minutes ago. The topology shows a downstream dependency in degraded state. They start reading logs - the kind of cross-cutting picture a terminal can't draw. 3. **Agent.** In parallel, they ask Claude (via Radar's MCP server) to "summarize the last 20 minutes of events in `checkout-prod` and tell me what changed." Claude reads the same enriched backend the UI is reading - not raw `kubectl` output. It returns: "Deployment `checkout-api` rolled out at 02:14:32; three pods CrashLoopBackOff; new image `checkout-api:v2.41.7` failing readiness on `/health`." 4. **Back to the UI for the action.** The engineer decides to roll back. One click, from the dashboard - or they ask the agent to call the MCP rollback tool. Same backend, same action, same RBAC. 5. **Async.** Five minutes later, an SRE pulled in via PagerDuty opens the incident's deep link. They see the same view. They ask the agent for "anything similar in the last 90 days." It finds two prior incidents and links the timelines back into the UI. Nothing about that flow privileges a single surface. kubectl answers the fast, precise question. The UI draws the picture from the graph - what owns what, what routes where, what changed when. The agent turns "what happened here" into a paragraph. Each does the part it is best at, and none of them makes you reassemble the cluster from raw YAML by hand. If the team had been forced to pick "UI-first" or "agent-first" at the start of the year - and to give up one of them to get the other - at least half the moves above would be slower or impossible. ## The takeaway It is fine to lean toward any one modality. Most teams will have a primary surface, and that is healthy - it is how culture and muscle memory build. CLI-anchored teams stay CLI-anchored. UI-anchored teams stay UI-anchored. Agent-leaning teams keep extracting leverage from their assistant. What is worth pushing back on is the implicit assumption in a lot of current tooling positioning: that the modality you lean toward dictates the tool you buy, and that picking the "wrong" tool locks you out of the other two. That is only true if the tool has one front end and treats the others as roadmap items. If you are evaluating tools for your team, the right question to ask is not "do you have an AI mode?" or "is the dashboard nice?" Either is easy to bolt on. The real question is whether the tool's UI and its agent actually make sense of the cluster graph - rendering the relationships for a human, modeling them for an agent - or whether they just dress up the same flat output you would get from `kubectl`. If yes, you do not have to pick. Your engineers keep kubectl for the precise, scriptable questions, work in the dashboard when they need to see how things connect, and lean on the agent when they want it explained - each surface pulling its weight. If no, you have bought a second and third way to read flat output, and your team will still be reassembling the cluster in their heads at 2am. That is the bet we made with Radar. One engine that watches your clusters - the same SharedInformer foundation across [Radar OSS and Cloud](/blog/radar-oss-or-radar-cloud-an-honest-take), running at [fleet scale](/blog/the-fleet-visibility-gap) when you need it - that turns live cluster state into something both surfaces can actually use: a UI that renders the graph for humans and an MCP server that models it for agents. `kubectl` stays in your terminal for when raw and precise is exactly what you want. Keep your CLI. Reach for the dashboard or the agent when the cluster is too tangled for raw YAML. Making those two genuinely good is on us. --- ### Radar's In-Cluster Architecture: Outbound-Only, Scoped, Live by Default - **URL**: https://radarhq.io/blog/the-radar-cloud-agent-architecture - **Date**: 2026-06-04 - **Author**: Eyal Dulberg, CTO, Skyhook - **Category**: Engineering - **Tags**: radar-cloud, kubernetes, architecture, security Every platform team we've talked to about Radar Cloud asks the same five questions before they'll install anything in their cluster: 1. Does it need inbound network access? 2. What Kubernetes permissions does it need? 3. What data leaves the cluster? 4. How are credentials handled? 5. What's the blast radius if Radar gets compromised? These are the right questions. If you're responsible for a cluster that handles real workloads, "just install our Helm chart and give it cluster-admin" is not an acceptable answer. The rest of this post is how we answer each one, with the actual design choices we made and the tradeoffs that came with them. ![Radar in-cluster architecture](/images/blog/radar-agent-architecture.png) ## 1. No inbound access. Ever. The simplest question first. Radar never opens a port. Not a NodePort, not a LoadBalancer, not an Ingress. It doesn't sit behind a Service that your cluster exposes to the internet, and it doesn't need you to punch holes in your firewall for a vendor CIDR range. We rejected the inbound model early. The typical pitch goes: "just expose our controller on an Ingress and we'll call it when we need to." For most platform teams we've worked with, that's a non-starter. Every inbound path is a new attack surface, a new TLS cert to manage, a new firewall rule to audit, and a new thing your security team has to sign off on. Doing that for a vendor tool is a lot of ceremony for visibility. So Radar dials out. On startup, it opens a single TCP connection to `api.radarhq.io:443`, negotiates TLS, upgrades to a WebSocket, and authenticates with a cluster-scoped bearer token it got at install time. On top of that one WebSocket we run [yamux](https://github.com/hashicorp/yamux) for stream multiplexing, so every Cloud-initiated request (topology fetch, log tail, exec session, MCP tool call) opens a fresh stream on the same connection instead of a new TCP dial. That connection stays open for the lifetime of the pod. What this looks like from your side: - One egress rule: allow `api.radarhq.io:443` (or the EU endpoint, depending on region). - No inbound rules. No public IPs. No load balancers. - TLS on the wire. Radar verifies the server cert against public CAs; the server authenticates Radar by SHA-256-hashing the presented bearer token and comparing it against the hash it stored when the cluster was onboarded. The honest concession: if you run a cluster with zero egress to the public internet, Radar requires you to allowlist one FQDN. That's the minimum. We can't do visibility-as-a-service without a network path. For air-gapped environments, the open-source Radar is the right answer. ## 2. Read-only by default. Read-write is opt-in per feature. The Helm chart installs one Deployment running one container, with one ServiceAccount bound to one ClusterRole. The default ClusterRole is read-only. ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: radar rules: # Core resources - apiGroups: [""] resources: - pods - services - endpoints - configmaps - namespaces - nodes - persistentvolumes - persistentvolumeclaims - events - serviceaccounts verbs: [get, list, watch] # Workload controllers - apiGroups: ["apps"] resources: [deployments, statefulsets, daemonsets, replicasets] verbs: [get, list, watch] # Batch - apiGroups: ["batch"] resources: [jobs, cronjobs] verbs: [get, list, watch] # Networking - apiGroups: ["networking.k8s.io"] resources: [ingresses, networkpolicies] verbs: [get, list, watch] # Autoscaling - apiGroups: ["autoscaling"] resources: [horizontalpodautoscalers] verbs: [get, list, watch] # RBAC (metadata only) - apiGroups: ["rbac.authorization.k8s.io"] resources: [roles, rolebindings, clusterroles, clusterrolebindings] verbs: [get, list, watch] # Metrics (if metrics-server is installed) - apiGroups: ["metrics.k8s.io"] resources: [pods, nodes] verbs: [get, list] # CRDs - discovery only, so Radar can find Argo, Flux, Istio, etc. - apiGroups: ["apiextensions.k8s.io"] resources: [customresourcedefinitions] verbs: [get, list, watch] # Secrets - metadata only (names, types, timestamps), NOT values. - apiGroups: [""] resources: [secrets] verbs: [get, list, watch] ``` That's the baseline. It lets Radar watch resources, build the topology, correlate events, and show you Helm releases. It does not let it mutate anything, exec into pods, or read log content. If you want specific features that need more, you opt in. Each feature maps to a named set of rules: - `features.logs=true` adds `pods/log` get. - `features.exec=true` adds `pods/exec` create. This is also gated per-user by Cloud RBAC, so Viewers never get a terminal. - `features.helm=true` adds get/list/watch/create/update/patch/delete on Helm-managed resources (scoped via labels). - `features.scale=true` adds update on `deployments/scale`, `statefulsets/scale`. - `features.restart=true` adds patch on workloads. You enable them in `values.yaml`. Nothing else flips on automatically. ## 3. The data contract The question I always want asked and rarely get: what actually leaves the cluster, and when? The short answer: **cluster state isn't pushed.** The control plane doesn't run an event ingest pipeline, doesn't keep a server-side replica of your resources, and doesn't store a "last known cluster snapshot" anywhere. When a browser asks Radar Cloud for a Pod, the Hub authenticates the user, opens a fresh stream over the existing WebSocket, and forwards the HTTP request through to the in-cluster Radar pod, which serves it live from its SharedInformer cache. The bytes go from cluster to browser via the Hub, on demand, and nothing in the middle is written to disk. | Data that crosses the tunnel (on demand, in response to a user request) | Data that never crosses | | --- | --- | | The specific resources a user is currently looking at (with managedFields stripped) | Secret `data` values. Ever. | | Filtered K8s events for the view the user has open | ConfigMap values annotated `radarhq.io/redact: "true"` | | Helm release metadata when a user opens a Helm view | Logs, exec, port-forward at rest (all streamed; nothing persisted) | | Topology relationships when a user opens topology | Raw kube-apiserver audit logs | | Logs, exec, port-forward bytes (streamed live; closed when the tab closes) | Background telemetry - nothing ships you didn't ask for | | MCP tool responses when an authorized AI client calls them | Anything that wasn't requested by an authenticated browser or PAT | A few things worth being explicit about. **Secret values never leave.** Radar lists Secrets so it can show you that a Secret named `db-credentials` exists and is mounted into a pod, but it does not read the `data` field. At the informer level, we strip the data before it enters the in-memory cache. If you "view" a Secret in the Radar UI, we show you the keys and type. We do not show the values. **Logs, exec, and port-forward are streamed, not stored.** When a user in the UI asks to tail a pod's logs, the Hub opens a stream through the WebSocket to in-cluster Radar, Radar opens a streaming read against `pods/log`, and the bytes flow back to the user's browser through that same stream. Nothing is written to disk on our side. When the user closes the tab, the stream closes. Same pattern for `kubectl exec` and `kubectl port-forward` equivalents. **managedFields gets stripped.** If you've ever looked at the raw JSON of a Kubernetes object, you know `managedFields` can be larger than the rest of the object combined. We strip it at informer callback time, before the object enters the in-cluster cache. That saves memory in-cluster and bytes on the wire when the resource flows out in response to a browser request. **ConfigMaps can opt out via annotation.** If you have ConfigMaps with sensitive content (which you shouldn't, but people do), annotate them with `radarhq.io/redact: "true"` and Radar treats them like Secrets - metadata only, values redacted at the boundary. **The control plane stores its own state, separately.** Org membership, roles, cluster registry metadata, audit log, PAT hashes, billing state, and a small set of hub-native event kinds (cluster.disconnected, member invitations, billing). That's what's in the control plane's database. Your cluster's resources aren't. ## 4. Credentials: cluster bearer tokens over TLS Each cluster connection is bootstrapped with a bearer token issued from the Radar dashboard by an Owner. The raw token is shown exactly once at creation and only ever stored as a SHA-256 hash server-side, bound to one cluster record. On every connection, Radar presents the token over TLS; the Radar Cloud server hashes the presented value and compares it against the stored hash before opening the tunnel. There's no separate enrollment handshake and no client-cert material to manage in-cluster: the token itself is the long-lived credential. An Owner can rotate the token at any time from the dashboard, which invalidates the previous hash and forces Radar to reconnect with the new value. We don't handle your kubeconfig, your cloud credentials, or your cluster CA. Radar authenticates to the Kubernetes API using the projected ServiceAccount token that the kubelet gives it, same as any in-cluster controller. ## 5. Blast radius: what happens if Radar is compromised The worst case: someone gets code execution inside the Radar pod. What can they do? With the default read-only ClusterRole, they can read cluster state. That's a disclosure problem, not a destruction problem. They cannot scale workloads to zero, they cannot delete your PVCs, they cannot exec into pods and pivot. The ClusterRole is the ceiling. With read-write features enabled, the ceiling rises to exactly what those features allow. If you enabled `features.scale=true`, an attacker can scale deployments. If you enabled `features.exec=true`, they can open a shell in any pod - the same pod an Admin user could exec into through the UI. This is why we make every read-write feature opt-in and surface the RBAC impact in the Helm chart's NOTES.txt when you install it. The other containment: Radar runs in its own namespace (`radar` by default), with a PodSecurityContext that drops all capabilities, runs as non-root, has a read-only root filesystem, and disables privilege escalation. A compromised Radar container can't write to disk or escalate to root without breaking out of the kernel's sandbox. ## Why SharedInformer In-cluster Radar uses the same `client-go` SharedInformer pattern as Radar OSS. A SharedInformer does one list call against the API server for a given resource kind, switches to a Watch stream for deltas, and maintains an in-memory cache that multiple consumers can read from. Why this matters: - **Low API server load.** One watch per kind, not N polls per second. On a cluster with 10,000 resources, we do 10k list reads at startup, then we're on watch streams. The kube-apiserver barely notices us. - **Deltas, not snapshots.** When a pod transitions from Pending to Running, we ship one delta. Not the entire pod object repeatedly. - **Memory efficiency.** On a cluster with a few hundred resources, Radar sits at ~32MB RSS. Memory grows roughly linearly with object count - a cluster with tens of thousands of pods will use more, but the constant factor is small because we strip `managedFields` and denormalize aggressively. ## The wire protocol The uplink is a WebSocket over TLS, with yamux as the multiplexer on top. A few properties worth calling out: - **One connection, many streams.** Every Cloud-initiated request (a browser loading topology, an MCP tool fetching resources, a log tail, a pod-exec session) is a fresh yamux stream on the same WebSocket. Streams are cheap (roughly 1KB of bookkeeping each); TCP dials are not. - **Plain HTTP inside.** Each stream carries a normal HTTP request to the in-cluster Radar binary's HTTP router, including SSE for live updates and WebSocket upgrades for `kubectl exec`. There's no custom binary protocol to reverse-engineer; `helm template` the chart and read the manifests if you want to audit the surface area. - **Keepalives.** yamux sends lightweight pings on idle connections so NATs and load balancers don't silently reap the tunnel, and so dead ends are detected quickly on both sides. - **Back-pressure.** yamux's per-stream flow control keeps one slow consumer (say, a user tailing noisy logs) from starving every other stream on the same connection. ## Failure modes Networks fail. Our backend sometimes has outages. Here's what Radar does when things go wrong. **Uplink drops.** Radar reconnects with exponential backoff (1s, 2s, 4s, ..., capped at 60s). While disconnected, it keeps its informer caches warm so the moment the WebSocket reopens it can serve fresh requests immediately - there's no "rehydrate from a checkpoint" step because the cluster's API server is the source of truth and Radar's informers are already tracking it. The Hub fires a `cluster.disconnected` notification when the WebSocket drops past a grace period and `cluster.reconnected` when it comes back. **Radar Cloud has an outage.** Your cluster keeps running. Radar is not in the data path for your workloads. It doesn't mutate anything, it doesn't proxy traffic, it doesn't gate admission. If we're down, you lose visibility in the Radar UI for the duration. That's the worst thing that happens. **Radar crashes.** Kubernetes restarts it. On startup, it redials the tunnel with the bearer token from its Helm values, rebuilds its informer caches, and is back in the fleet view. Cold start to steady state is usually under 10 seconds on a small cluster, maybe 30 seconds on a big one. If you enabled SQLite-backed timeline persistence with a PVC, in-cluster event history survives across restarts. ## What we don't do This is the part I care about most, because a lot of in-cluster tools in this space have grown tentacles. - **No sidecar injection.** We don't mutate your pods. - **No mutating admission webhooks.** We don't sit in the admission path. If Radar is down, your deploys still work. - **No validating webhooks.** Same reason. - **No CRDs of our own.** We read your CRDs (Argo, Flux, Istio, your own). We don't install ours. - **No init containers.** Nothing piggybacks on your workloads. - **No cert-manager dependency.** Radar authenticates with a static bearer token you supply at install time. Nothing in the chart asks your cluster to issue certs for us. One Deployment. One ServiceAccount. One ClusterRole. One Secret. One namespace. That's it. ## Install ```bash helm repo add skyhook https://skyhook-io.github.io/helm-charts helm repo update helm install radar skyhook/radar -n radar --create-namespace \ --set cloud.token=$RADAR_CLOUD_TOKEN ``` The token comes from the Radar dashboard when you click "Add cluster." By the time `helm install` exits, Radar is connected and your cluster shows up in the fleet view. If you want to audit exactly what lands in your cluster before installing, `helm template` the chart and read the manifests. There are no surprises. That's the whole point. ## The short version In-cluster Radar is a small Go binary that dials out to one FQDN over TLS, authenticates with a cluster-scoped bearer token, runs with a read-only ClusterRole unless you opt into more, serves on-demand requests reverse-proxied from the Radar Cloud control plane over a yamux-multiplexed WebSocket, and never stores logs or exec sessions at rest. The control plane doesn't cache cluster state - everything you see in the dashboard is served live from the in-cluster pod. It's ~32MB RSS at steady state on a typical cluster. If it gets compromised, the ClusterRole is the ceiling on what an attacker can do. None of this is revolutionary. It's just the default every hosted Kubernetes tool should have been shipping for the last five years. Some do. Many don't. If you're evaluating one, these are the five questions to ask - ours or anyone else's. --- ### Radar OSS or Radar Cloud? An Honest Take on When to Use Each - **URL**: https://radarhq.io/blog/radar-oss-or-radar-cloud-an-honest-take - **Date**: 2026-06-02 - **Author**: Nadav Erell, CEO, Skyhook - **Category**: Open source - **Tags**: radar, radar-cloud, open-source, comparison, kubernetes The most common question in our GitHub issues is some variant of "do I need the Cloud version?" Here's the honest answer: most people don't. ![Radar OSS and Radar Cloud](/images/blog/radar-oss-vs-cloud-hero.png) Radar OSS launched in January. Radar Cloud launched a month later. Since then, we've watched people agonize over the choice in ways that don't match how we actually think about it internally. This post is our attempt to stop that agonizing. ## What they share Radar OSS and Radar Cloud are the same tool for most of what you do day to day. Same UI conventions, same keyboard shortcuts, same views: Resources, Topology, Timeline, Helm, GitOps, Traffic, Cluster audit, MCP. Same SharedInformer foundation under the hood. The React frontend is literally the same codebase, with fleet-scoped views layered on top for Cloud. If you've used one, you already know the other. There is no relearning tax. The thing that changes between them isn't the tool, it's the shape of your work. Are you one person poking at one cluster, or are you a team keeping an eye on many? That's the whole question. ## The five questions that decide it Forget feature matrices for a minute. These five questions predict the right answer better than anything else: 1. **Are you working alone, or with a team?** If two or more engineers need to look at the same cluster state during the same incident, something hosted starts to earn its keep. 2. **Do you need shared, persistent identity?** OSS auth is whatever your kubeconfig grants. If you want SSO, an audit log of who did what, and per-user RoleBindings managed centrally, that's Cloud. 3. **Do you want notifications when a cluster goes dark while nobody's looking?** OSS is a tool you open. Cloud sends you a Slack or webhook ping when a cluster disconnects, a payment fails, or a teammate joins your org. 4. **Do you need more than one person to have scoped access?** If "Alice can read prod, Bob can edit staging" matters, you want SSO-driven access mapped to standard K8s RBAC, not a pile of kubeconfigs. 5. **Are you running one cluster, or six?** Fleet views only start paying for themselves once "which cluster is that pod in?" becomes a real question you ask weekly. The more your answers trend toward team and multi-cluster, the more Cloud earns its place. If you're answering "alone, one cluster, I just want to look" to all five - stay on OSS. That's what it's for. ## When Radar OSS is the right answer OSS isn't a stepping stone. For a large slice of users, it's the final answer. - **Solo engineers** debugging a single cluster from their laptop. You don't need a fleet view of one thing. - **Air-gapped or regulated environments** where outbound traffic to a hosted vendor isn't allowed. OSS runs entirely on your machine with your kubeconfig. No data leaves. - **"I want to poke around for an hour"** moments. You inherited a cluster and want to understand it before touching anything. `radar` and you're in. No account, no token, no onboarding wizard. - **Contributors and developers** who want to read the source, fork it, or build on top of it. Apache 2.0, single Go binary, React UI embedded via `go:embed`. - **Teams deploying Radar in-cluster** as a read-only internal dashboard via the Helm chart. If you're fine with shared view and your own OIDC or proxy auth in front of it, that works. Where OSS is a bad fit: a 12-person team trying to coordinate during a production incident at 2am. Everyone running their own local Radar against their own kubeconfig is not incident response, it's a conference call. That's the point where you want one URL everyone shares. ## When Cloud earns its price Cloud starts making sense when your answers to the five questions flip. - **Teams of 3+ engineers** who all need shared context. One URL, one cluster everyone sees through the same RBAC, one place changes are audited. - **Fleets of 5+ clusters.** Fleet views exist because alt-tabbing between five browser tabs of Radar OSS is not a workflow. - **On-call rotations.** Cloud notifies on the events the control plane actually owns - cluster disconnect and reconnect, billing, member invites - over Slack, webhook, or in-app. Conservative on purpose. - **Compliance-driven audit needs.** If you need a record of who clicked what, when, against which cluster, audit logs ship on Free (7-day retention), Team (30 days), and Enterprise (365 days). SOC 2 Type II across the board. - **You're tired of kubeconfig-based access control.** Cloud roles map to standard K8s RBAC via impersonation; full SAML / OIDC SSO (Okta, Entra ID, Google Workspace, OneLogin, any spec-compliant provider) is on every plan, including Free. Where Cloud is a bad fit: an engineer who will use Radar twice a week to check one cluster. There's no reason to pay for that. Use OSS. ## The hybrid pattern A lot of teams end up using both, and we think that's correct. Local laptop debugging? OSS. You're on a train, you've got kubeconfig, you want to check why a pod is CrashLooping. `radar` is faster than opening a browser tab and loading a web app. Shared fleet oversight, alerts, audit trails, on-call? Cloud. Both have the same mental model. You don't flip between "oh, this is the OSS way of doing it" and "this is the Cloud way of doing it." It's one tool with two deployment shapes. Keep both. The OSS binary is free forever, and the Cloud Free tier covers three clusters for a small team. ## What Cloud doesn't try to do This is the part I want to be very clear about, because it's where trust in OSS tooling tends to break down. **Radar Cloud is not a replacement for Radar OSS.** OSS stays Apache 2.0. OSS stays single-binary. OSS stays fully featured for single-cluster work. Resources, Topology, Timeline, Helm, GitOps, Traffic, Cluster audit, MCP - all of it stays in OSS. We are not gating features in OSS to push people toward Cloud. Cloud adds things OSS can't meaningfully do on its own: multi-cluster aggregation, SSO mapped to standard K8s RBAC, an org-scoped audit log, hub-side notifications when a cluster disconnects, compliance certifications, BYOC for regulated environments. Those are genuinely different surface areas, not artificially withheld capabilities. **We'll never rug-pull OSS.** Specifically: - We won't move existing OSS features into a Cloud-only tier. - We won't add mandatory telemetry or cloud check-ins to the OSS binary. - We won't require an account to run `radar` locally. - If we ever need to fundamentally change the license, it'll be a visible, discussed fork, not a quiet bait-and-switch shipped in a minor version bump. We watched Lens do the mandatory-login dance in 2024. We're not doing that. It's why we open-sourced Radar in the first place. ## A word about pricing The Free tier of Radar Cloud exists precisely so a solo engineer at a small team can try the hosted version without pulling out a credit card. 3 clusters, unlimited nodes, unlimited teammates, full SAML / OIDC SSO, the full product UX. If that's enough for you, stay there forever. We're fine with it. Team is $99 per cluster per month with 30-day audit retention, unlimited nodes, unlimited teammates, full SSO, Slack and webhook notifications, K8s-native RBAC via impersonation, and shareable deep links. That's the tier most teams in the 3-50 engineer range land on. Enterprise is custom-priced and adds 365-day audit retention, SCIM 2.0 directory sync, BYOC / on-prem deployment of the control plane, US or EU data residency, a 99.9% SLA, and a dedicated CSM. Annual contracts get 20% off the Team list price. We're not going to push you to a plan you don't need. The Free tier is a real product, not a 14-day trial dressed up. ## The side-by-side | Capability | Radar OSS | Cloud Free | Cloud Team | Cloud Enterprise | |---|---|---|---|---| | Clusters | Unlimited (local) | 3 included | Unlimited ($99/cluster/mo) | Unlimited (custom) | | Timeline | In-memory or SQLite (in-cluster) | Live via reverse-proxy | Live via reverse-proxy | Live via reverse-proxy | | Audit logs | - | 7 days | 30 days | 365 days | | Auth | kubeconfig | SAML / OIDC SSO | SAML / OIDC SSO | SSO + SCIM | | Notifications | - | Slack, webhook, in-app | Slack, webhook, in-app | Slack, webhook, in-app | | RBAC | - | K8s impersonation, default roles | K8s impersonation, default roles | + custom ClusterRole bindings, per-user RoleBindings | | SLA | - | - | 99.5% | 99.9% | | BYOC / on-prem | - | - | - | Yes | | Fleet views | Single cluster | 3 clusters aggregate | All connected | All connected | | Data residency | Your laptop | US | US | US, EU, or BYOC | | Price | Free (Apache 2.0) | Free | $99 / cluster / month | Contact us | ## A short decision flow If you want the three-second version: - **One cluster, one person, ephemeral use?** Radar OSS. Done. - **One cluster, small team, want a shared URL and SSO?** Cloud Free. - **2-50 clusters, team of 3+, want notifications and proper access control?** Cloud Team. - **Need 365-day audit retention, SCIM, BYOC / on-prem, or a 99.9% SLA?** Cloud Enterprise. - **Air-gapped, or allergic to hosted vendors?** Radar OSS, deployed in-cluster via Helm. - **Already on OSS and it works?** Stay there. Seriously. The honest summary: if you're happy with Radar OSS, you don't need anything else from us. If you hit one of the walls above - multi-cluster, team coordination, retention, alerting, compliance - Cloud is the tool you should reach for, not because it's more powerful, but because it's shaped for that job. Both tools are linked from [radarhq.io](https://radarhq.io). Pick the one that fits. We'd rather you use the right one than the expensive one. --- ### Five Questions You Can't Answer With kubectl - **URL**: https://radarhq.io/blog/five-questions-you-cant-answer-with-kubectl - **Date**: 2026-05-01 - **Author**: Nadav Erell, CEO, Skyhook - **Category**: Engineering - **Tags**: kubernetes, kubectl, topology, observability, for-devops kubectl is the right tool for almost everything. It is also, by design, a way to fetch one object at a time, as raw YAML, exactly as it exists right now. Often that is precisely what you want. You are debugging one pod, in one namespace, checking its current state. kubectl is fast, scriptable, and built into every engineer's brain. Nothing is going to replace it. But a Kubernetes cluster is not a list of objects - it is a living, interconnected graph, and a lot of the questions that matter are about the graph, not any single node of it. How do these objects relate? How do they actually behave, versus what their YAML declares? What is inside the artifacts they run? What did they look like an hour ago? Are they configured sensibly? kubectl can hand you the raw material for each, but it leaves the assembly to you. Here are five questions where that gap shows - all real ones our users brought us this year. ## 1. "What actually breaks if I change this?" You are about to edit a ConfigMap, retarget a Service selector, or delete what looks like an unused Secret. What depends on it? kubectl shows you the object: ```bash kubectl get configmap app-config -n payments -o yaml ``` What it will not show you is the blast radius. To find that you go spelunking: which Pods mount this ConfigMap as a volume or pull it via `envFrom`, which Deployments own those Pods, which Service selects them, which Ingress routes to that Service. Each hop is a separate query, and the references run in directions JSONPath makes you walk by hand: ```bash # which pods reference this ConfigMap? (volumes AND envFrom AND env valueFrom) kubectl get pods -n payments -o json | jq '.items[] | select( (.spec.volumes[]?.configMap.name == "app-config") or (.spec.containers[].envFrom[]?.configMapRef.name == "app-config") or (.spec.containers[].env[]?.valueFrom.configMapKeyRef.name == "app-config") ) | .metadata.name' ``` That is one level, one kind of reference, one ConfigMap. The actual question - "show me everything connected to this, and how" - is a graph traversal, and kubectl returns objects, not graphs. What you need is the cluster rendered as what it is: a graph of typed relationships. Radar's topology view models the edges between objects - which controller *manages* a workload, which Service *exposes* it, which ConfigMaps and Secrets *configure* it, which PDB or NetworkPolicy *protects* it, and the HPA it *uses* to scale - and lets you click any node to see everything wired to it. "What breaks if I touch this" becomes "look at the node and read its edges," instead of a dozen correlated `jq` queries you have to remember to keep in sync. ## 2. "Is this pod actually isolated, or wide open?" Security asks: is the `payments` workload locked down, or can things reach it that shouldn't? kubectl lists the policies: ```bash kubectl get networkpolicies -n payments -o yaml ``` Now read the `podSelector`s, intersect them with the labels on the workloads you care about, cross-reference the ingress and egress rules and their namespace/pod selectors, and hold the result in your head. The most dangerous case is the *absence* of a policy - a workload that nothing selects, so it is wide open - and "find me the Pods that no NetworkPolicy covers" is not a query kubectl offers. You would enumerate every Pod, enumerate every policy's selector, and compute the set difference yourself. And even then you have only checked declared intent, not what is actually talking to that pod right now. What you need is coverage plus reality. Radar flags which workloads have no NetworkPolicy selecting them - the wide-open ones - shows what each policy does cover, and, where you run Cilium's Hubble, Caretta, or Istio, overlays live traffic on top. "Nothing is protecting this destination, and here is what is currently reaching it anyway" becomes one view instead of a YAML reasoning exercise. ## 3. "What's actually inside this image?" Trivy flags a critical CVE in a library. Is the vulnerable file even present in the image you ship, or did it come from a base layer you stripped? And while you are in there - why is this image 1.4GB? kubectl's answer is exec, which only works if the container is running and ships a shell: ```bash kubectl exec -it payments-api-7d9c8b4f-xq2mn -n payments -- /bin/sh # sh: not found ``` Distroless image? No shell. Pod crash-looping? Nothing to exec into. Image not scheduled anywhere yet? Nothing to exec into at all. The thing you want to inspect is the image's filesystem, and kubectl operates on running containers, not image artifacts. What you need is to read the image itself. Radar's image filesystem viewer lets you click any container image in a Pod and browse its complete filesystem - the full tree, with file sizes, permissions, and symlink targets - without pulling it locally or execing into anything. "Is `libfoo.so.1.2.3` actually in here" and "what are the ten biggest paths" become point-and-click, on any image, running or not. ## 4. "What changed last night?" You walk in at 9am. Webhook delivery has been flaky since 2am. The on-call engineer has gone to bed. You want a timeline. ```bash kubectl --context=prod-us get events -n payments --sort-by=.lastTimestamp ``` You see about thirty events, all from the last hour. The 2am window is gone: Kubernetes events have a default TTL of one hour, and the kube-apiserver garbage-collects them. By the time you ask, the answer has been deleted. A live API server is not a database - it tracks current state and lets the past evaporate, which is part of what makes it fast. Your fallbacks are the usual three-you-have-one-of: audit logs (if enabled, shipped somewhere queryable, and retained), your metrics stack (which has the symptoms, rarely the cluster's narrative - "this Deployment rolled, that ConfigMap changed, that pod was OOMKilled"), and Argo's history (only for changes that came through Git). What you need is a persistent timeline that subscribes to events and resource changes as they happen and keeps them past the TTL, queryable by time, namespace, and kind. Radar records exactly that - a unified timeline of Kubernetes events and resource changes you can scroll back to the minute something broke (persisted to SQLite when you want it to outlive a restart). The real payoff is the question one step harder than "what changed." A pod restarted 17 times, twelve of them last Wednesday between 02:55 and 03:10. `kubectl describe` shows the latest termination reason; `kubectl logs --previous` gets you exactly one instance back, not twelve. The weekly pattern only exists in retained history. When we traced one of these for a team, the 3am Wednesday OOMKills turned out to be a CronJob in a *different* namespace whose memory spike was evicting the worker pods. Nobody spots that from live state - it was sitting in the timeline. ![Pod restart timeline showing weekly recurrence](/images/blog/pod-restart-timeline.png) ## 5. "What's quietly misconfigured before it pages me?" Not "what is broken right now" - what is latent. The Deployment with no memory limit that gets OOMKilled under load. The container running as root. The Ingress with no TLS. The PDB that allows zero disruptions. None of these page you today; they page you on the worst day. kubectl will show you each setting if you know to look: ```bash kubectl get deploy -n payments -o json \ | jq '.items[] | select(.spec.template.spec.containers[].resources.limits == null) | .metadata.name' ``` But that is one check, hand-written, for one antipattern, in one namespace. The real question - "scan everything here against the things experienced operators know to check, and tell me what is off" - is a judgment, and kubectl returns objects; it does not have an opinion about them. What you need is a scanner that encodes those opinions. Radar ships a cluster audit - 31 checks across security, reliability, and efficiency, drawn from Polaris, Kubescape, Trivy, and the NSA/CISA hardening guidance - that runs instantly against its cache with nothing installed in the cluster, groups findings so you fix a class at a time, and respects Kubernetes inheritance so a check on a Deployment does not double-fire on its Pods. ## What these questions have in common Look at them together and the pattern is not "kubectl is missing a flag." It is that each question is about something other than one object's current YAML: | Question | What kubectl returns | What the question is really about | | --- | --- | --- | | What breaks if I change this? | One object's spec | Relationships - the graph | | Is this pod isolated? | Policy YAML | Effective behavior + live traffic | | What's inside this image? | A shell in a running container | The artifact itself | | What changed last night? | Live state, 1h event TTL | History - the past | | What's misconfigured? | Objects | Judgment over those objects | kubectl is built to fetch one object, in one cluster, as it is right now, as text. That is the right primitive for an enormous amount of operational work. But comprehension - how things connect, how they behave, what is inside them, what they were, and whether they are sound - is not a fetch. It is the cluster rendered and assessed as the connected, living system it actually is. That is a different tool, sitting next to kubectl, not replacing it. ## Where kubectl is still right To be clear, none of this is an argument against kubectl. We use it constantly. "Is this pod running," "tail these logs," "scale this Deployment," "patch this ConfigMap to test something right now" - it is the right tool, and anything trying to be "the new kubectl" is solving the wrong problem. The framing is kubectl *plus* something that understands the graph, not kubectl versus anything. ## The Radar take Every one of those five is answered by [Radar](https://github.com/skyhook-io/radar) OSS - a single binary you launch with `kubectl radar` (or a desktop app), running locally against your kubeconfig with nothing installed in the cluster. Topology for the relationships, NetworkPolicy coverage and live traffic for isolation, the image filesystem viewer for what is inside, a persistent timeline for the past, and the [cluster audit](/blog/cluster-audit-the-31-checks-that-catch-what-you-forgot) for posture. All of it within one cluster, for free. The point where you need more is when the same five questions go fleet-wide. "Is this CVE image running anywhere across my fourteen clusters?" "What is *actually* different between the staging cluster and the prod cluster?" "Who can exec into a prod pod in *any* cluster?" Same questions, cross-cluster scope - and that is what Radar Cloud adds on top of the same engine: a fleet-wide image inventory, cross-cluster compare, and a fleet RBAC index. We did not set out to replace kubectl. We set out to render the cluster as the graph it already is, so the questions kubectl was never shaped for stop being afternoon-long shell-script projects. If any of the five above sound familiar, that is the gap we are aiming at. If you have already hit this wall, you are not the only one - we wrote about [the broader fleet visibility gap](/blog/the-fleet-visibility-gap) for teams already past two clusters. --- ### Cluster Audit: The 31 Checks That Catch What You Forgot - **URL**: https://radarhq.io/blog/cluster-audit-the-31-checks-that-catch-what-you-forgot - **Date**: 2026-04-23 - **Author**: Eyal Dulberg, CTO, Skyhook - **Category**: Engineering - **Tags**: radar, kubernetes, security, reliability, audit Every cluster I've ever audited has the same handful of issues. Pods running as root. Containers without resource limits. A service account that's bound to cluster-admin because someone needed it for "just one thing" eight months ago. A `latest` tag in a Deployment that hasn't been updated since. Each issue is small. The aggregate is the entire reason the security team is nervous about Kubernetes. Radar ships with a built-in cluster audit that runs 31 of these checks against your live state and surfaces failures inline on each affected resource. No CRDs to install, no separate controller to operate, no Polaris-style YAML pipeline to maintain. It's part of the Radar binary. ![Radar cluster audit](/images/blog/radar-resources.png) ## What "best practice" actually means here Let's be specific about the source. The check set is inspired by [Polaris](https://github.com/FairwindsOps/polaris) and the [NSA / CISA Kubernetes hardening guide](https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF). Both are good prior art - Polaris because it's the de-facto rule set for Kubernetes config validation, NSA / CISA because it's the standard most security teams point at when they want to argue for stricter defaults. The result is opinionated but defensible. Every check has a reason. We don't flag YAML style preferences ("use camelCase in your annotations"). We flag things that have an actual blast radius if they go wrong. The 31 checks split into three categories. ### Security (the ones the security team will ask about) - Containers running as root. - Privileged containers. - `allowPrivilegeEscalation: true`. - Writable root filesystems. - Dangerous or insecure Linux capabilities. - Host network, PID, or IPC namespaces. - Container runtime socket mounts. - Sensitive host path mounts. - Secrets accidentally placed in ConfigMaps. - Auto-mounted service account tokens. ### Reliability (the ones the SRE team will ask about) - Missing readiness or liveness probes. - Mutable image tags (e.g. `latest`). - Pull policy mismatches on digest-pinned images. - Single-replica Deployments or StatefulSets. - Missing PodDisruptionBudgets on replicated workloads. - Missing topology spread constraints. - All replicas scheduled on one node. - Services with no matching pods. - Ingresses pointing at missing Services. - Deprecated API versions. ### Efficiency (the ones the FinOps team will ask about) - Missing CPU or memory requests. - Missing CPU or memory limits. - Resource utilization far below or above requests. - Unused ConfigMaps or Secrets. The checks carry framework labels where they map cleanly to NSA / CISA or CIS guidance. The goal is not to replace a full compliance program. It is to make the obvious misses visible before they become incident or audit material. ## How findings show up The audit runs continuously. There's no "run scan" button - findings update as your resources change. The **Cluster audit** sidebar entry has three views: - **Summary** - findings broken down by category and severity. - **By resource** - rows of resources sorted by issue count. Useful for "fix the worst offenders first." - **By check** - rows of checks sorted by frequency. Useful for "we're going to standardize on `runAsNonRoot` across the fleet, what does that touch?" In the resource browser, every row that has an audit finding shows a small chip. Click in, the **Audit** tab shows the per-resource breakdown with the rule, the severity, and a remediation snippet. The useful moment is usually not "run a scanner once a quarter." It is "I'm already looking at this Deployment, and Radar tells me it has no readiness probe, one replica, and no PDB." ## Ignoring noise without disabling the check The first thing teams want to do after enabling a check set is silence the things that are correct-but-flagged. Polaris-style global disables work but lose the signal everywhere - usually you only want to suppress for a specific namespace or workload. Ignore patterns are configured in the Radar values: ```yaml audit: ignore: # exact resource match - kind: DaemonSet namespace: kube-system name: cilium checks: [host_network, privileged] # selector match - namespaceLabels: environment: dev checks: [latest_tag, missing_resource_limits] ``` Selectors compose. The pattern most teams land on: a "production has strict rules, dev is intentionally lenient" carve-out, plus a small allow-list for system DaemonSets that legitimately need elevated access (Cilium, kube-proxy, the storage CSI driver, etc.). For local Radar, the same shape lives in `~/.radar/audit-ignore.json`. Both formats round-trip; you can edit either. Ignores are configuration, not deletion: the check still exists, but the UI stops treating that known exception as work. ## Programmatic access Two surfaces beyond the UI. The HTTP API: ``` GET /api/audit # whole cluster GET /api/audit/resource/{kind}/{namespace}/{name} # single resource ``` JSON output, filterable by category and severity. Useful for wiring findings into CI - a PR that introduces a new high-severity finding should fail before it lands in main, and `curl /api/audit | jq '.findings | map(select(.severity == "high"))'` is the easy way to ask. The MCP tool `get_cluster_audit` is the same surface, packaged for AI tools. Filterable by category, severity, namespace. The use case we hear most is "ask Claude to explain this finding" or "have the AI propose a remediation patch and then dry-run-apply it." ## Cloud rolls it up across the fleet In Radar Cloud, fleet checks fan out to connected clusters and merge the results. That answers different questions: - Which clusters have critical audit findings right now? - Which check is failing across the most clusters? - Did our policy change land everywhere? - Which namespace owns most of the remaining hygiene debt? The data still comes from the in-cluster Radar instances. Cloud is the coordination layer, not a hosted copy of every finding forever. ## What it isn't Worth being explicit. **Not a runtime security tool.** Cluster audit catches misconfiguration. It doesn't replace Falco, Tetragon, or whatever your eBPF-based runtime detection layer is. A privileged container that gets compromised at runtime is its problem; a privileged container that shouldn't have been deployed in the first place is ours. **Not a CIS benchmark scanner.** kube-bench and Trivy do CIS benchmarks against the cluster control plane (etcd, kube-apiserver, kubelet config). Cluster audit runs against the workloads running on the cluster. Both are useful; they don't overlap. **Not deterministic across check versions.** We add checks as patterns emerge in the wild. A new high-severity check shipping in a Radar release will surface findings that didn't exist before. The mitigation is the ignore-pattern config above and the changelog, which calls out new and changed checks per release. ## Why bake it in instead of pointing at Polaris We considered shipping Radar as "use Polaris and we'll render its output." Two reasons we didn't. The first is the install cost. Polaris is good, but it's another Helm chart to deploy, another CRD set to track, and another upgrade cycle. For a tool that's supposed to give you visibility in five minutes, asking you to also deploy a separate audit controller is the wrong answer. The second is integration. The audit findings show up next to the resource that has them, in the same UI you're already using to debug. The MCP integration lets an AI tool fetch findings the same way it fetches resources. The Cloud fleet view aggregates findings across clusters because it already aggregates everything else. Bolting Polaris's output onto our UI would have been a constant integration tax; building the check engine in-process is one decision we make once. ## The shape of it Most clusters fail the same handful of checks. Most of those failures have boring fixes. The reason they don't get fixed is that nobody surfaces them in the same place where the engineers actually work. Cluster audit is the same idea as the rest of Radar - put the information where you'd already be looking, don't make people deploy another thing to get it. The 31 checks aren't novel. The fact that you can see them inline next to the broken resource, with an MCP endpoint for your AI tools and a fleet rollup in Cloud, mostly is. If you want to see what your cluster looks like under it, the open-source Radar is free for self-hosted and the audit is on by default - install instructions are at [radarhq.io/docs](https://radarhq.io/docs). --- ### MCP for Kubernetes: Live Cluster Context for AI Tools - **URL**: https://radarhq.io/blog/mcp-for-kubernetes-live-cluster-context-for-ai-tools - **Date**: 2026-04-09 - **Author**: Roy Libman, CPO, Skyhook - **Category**: Engineering - **Tags**: radar, kubernetes, mcp, ai, claude, cursor The first time I asked Claude to debug a CrashLoopBackOff via raw `kubectl` access, it spent 4,000 tokens parsing a single Pod's YAML before it noticed the OOMKilled status condition. The condition was the second-to-last field. Everything before it was `managedFields`, status I didn't ask for, and annotations that had nothing to do with the question. That's the failure mode of giving an AI raw cluster access. The tool works - it can read, it can run commands - but the signal-to-token ratio is terrible. You burn budget on noise before getting to the useful part, and even then the AI has no idea which events relate to which workload, what's owned by what, or which Secret values it must never read. Radar ships a built-in [MCP](https://modelcontextprotocol.io) server that fixes this. Same surface area as the UI, packaged for token efficiency and protected by your existing RBAC. ![Radar MCP for AI tools](/images/blog/radar-resources.png) ## What's wrong with raw kubectl Three things break when you point an AI at unfiltered cluster access. **Token waste.** A single `kubectl get pod -o yaml` is 2-3 KB of `managedFields`, internal annotations, and status fields nobody asked for. Across a namespace with 80 pods, you're spending ten thousand tokens before the AI has even seen one useful piece of state. **No correlation.** Raw output doesn't relate Pods to Services to Ingresses, doesn't dedupe events, doesn't know which logs are interesting. When you ask "why is the api Deployment unhealthy?", the AI has to fetch the Deployment, then the ReplicaSet, then the Pods, then the events, then the logs - five separate tool calls, each returning more raw YAML, each costing tokens. Most of the round-trips you can skip if the tool surface is shaped right. **Unrestricted writes.** kubectl can modify or delete anything the user behind the kubeconfig can. Giving an AI agent that level of authority makes you nervous, and it should. Even with `--dry-run=client` everywhere, one missed flag and you've nuked a production resource. ## What Radar's MCP server gives an AI instead Four properties that change the math. **Resources are minified.** `managedFields`, `last-applied-configuration`, redundant status fields, and internal annotations are stripped before they hit the wire. The meaningful spec and status are kept. A Pod that costs 3 KB through raw `kubectl` typically costs ~600 bytes through Radar's MCP. You can fit ten times more cluster into the same context window. **Resources are enriched.** `get_resource` accepts an `include` parameter (`events,relationships,metrics,logs`) that returns the related signals in one call. Topology relationships, deduped events, secret-safe logs, observed metrics. The AI doesn't have to build a mental model of how Kubernetes objects own each other - the tool answers correlation questions directly. **Writes are explicit, not shell access.** No raw `delete`. No force-uninstall. No arbitrary shell. The write tools are a bounded set: `apply_resource`, `patch_resource`, `manage_workload` (restart, scale, rollback), `manage_cronjob` (trigger, suspend, resume), `manage_gitops` (sync, reconcile, suspend, resume), and `manage_node` (cordon, uncordon, drain). They're annotated as mutating or destructive where appropriate so MCP clients can present confirmation UI, and most read-only AI workflows never touch them. **Secrets and tokens are scrubbed.** Secret `.data` and `.stringData` never leave the cluster. Env values get redacted by pattern. Log lines are scrubbed for known secret shapes (API keys, JWTs, base64 blocks of suspicious entropy). The AI literally cannot see a Secret value, even if you ask it to. ## The tool list Compact view of the OSS tools wired up today. Cloud adds org-level tools such as `list_clusters` and fleet-wide tools on `/mcp`. | Read tool | What it returns | | --- | --- | | `get_dashboard` | Cluster health overview - counts, problems, warnings, Helm status, recent changes | | `list_resources` | Resources of a kind, minified summaries | | `get_resource` | One resource, optionally with `events,relationships,metrics,logs` | | `get_topology` | Resource relationships graph (or text summary) | | `get_events` | Recent events, deduplicated, optionally scoped to a resource | | `get_pod_logs` | Filtered logs (errors / warnings prioritized, secrets scrubbed) | | `get_workload_logs` | Aggregated logs across pods of a workload | | `list_namespaces` | Namespaces with status | | `get_changes` | Recent resource changes from the timeline | | `list_helm_releases` | Helm releases with status | | `get_helm_release` | Detailed release info; optional `values,history,diff` | | `list_packages` | What's installed across Helm, workload labels, CRDs, Argo CD Applications, and Flux. Each row carries a `sources` array so you can see why a package was detected, plus per-source health and version | | `get_cluster_audit` | Cluster audit findings, filterable by category and severity | | `issues` | Ranked stream of what's broken right now | | `diagnose` | Root-cause a workload or GitOps reconciler with the causal chain assembled | | `get_neighborhood` | Focused topology around one resource | | `get_subject_permissions` | Effective RBAC for a user, group, or ServiceAccount | | `search` | Find resources by name, labels, env refs, images, config keys, or content | | `top_resources` | Live CPU and memory usage ranked with workload context | | `query_prometheus` | Run PromQL against the cluster's Prometheus | | `discover_metrics` | Discover metric names and metadata from Prometheus | | `get_prometheus_rules` | Prometheus alerting and recording rules with current state | | Write tool | What it does | | --- | --- | | `apply_resource` | Create / update from YAML, multi-doc, supports `dry_run` | | `manage_workload` | restart / scale / rollback Deployments, StatefulSets, DaemonSets | | `manage_cronjob` | trigger / suspend / resume | | `manage_gitops` | Argo or Flux: sync / reconcile / suspend / resume | | `manage_node` | cordon / uncordon / drain | | `patch_resource` | JSON Patch, merge patch, or strategic merge patch against one resource | There's also a `cluster://` URI scheme for the resource style: `cluster://health`, `cluster://topology`, `cluster://events`. Useful for MCP clients that prefer resources over tool calls. ## Setup OSS Radar exposes MCP on the same port as the UI (default `9280`), localhost-only. For Claude Code: ```bash claude mcp add radar --transport http http://localhost:9280/mcp ``` For Cursor (`~/.cursor/mcp.json`): ```json { "mcpServers": { "radar": { "url": "http://localhost:9280/mcp" } } } ``` For Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json`): ```json { "mcpServers": { "radar": { "type": "http", "url": "http://localhost:9280/mcp" } } } ``` Windsurf, VS Code Copilot, JetBrains AI, OpenAI Codex, Gemini CLI - same shape, different config file. The docs cover each in detail. For Cloud, the default is one org-level MCP endpoint gated by OAuth or a personal access token: ```json { "mcpServers": { "radar-cloud": { "type": "http", "url": "https://api.radarhq.io/mcp", "headers": { "Authorization": "Bearer rhp_..." } } } } ``` The dashboard's **Connect an AI client** wizard auto-fills the snippet for whichever tool you pick. Cloud exposes `list_clusters` on the org endpoint, so a multi-cluster AI workflow can ask "what clusters do I have access to?" without you hardcoding cluster IDs. You can also scope a token to one cluster; that snippet uses `https://api.radarhq.io/c//mcp`. ## RBAC: the part that surprised some early users Each MCP call goes through Kubernetes with the user's identity, not a shared agent identity. In OSS, that's whatever your kubeconfig grants. In Cloud, the in-cluster Radar pod impersonates the user (via `X-Forwarded-User` and `X-Forwarded-Groups` headers injected by Cloud), so a `cloud:viewer` user's MCP calls hit the cluster as a `view`-level identity. A 403 from K8s comes back as a 403 from MCP. This means an AI agent inherits the permissions of whoever's running it. A read-only engineer's AI can read. An admin's AI can write the things admins can write. Nobody has to maintain a "service account for AI" that's secretly more privileged than the humans using it. ## What this changes about debugging The honest answer is that it changes a workflow, not a productivity multiplier. A typical debugging session with this in place looks like: 1. Page fires, you open the AI chat. 2. "The api Deployment in prod is unhealthy. What changed in the last hour?" 3. AI calls `get_dashboard`, then `get_resource Deployment/api include=events,relationships`, then `get_changes since=1h kind=ConfigMap namespace=prod`. 4. AI reports back: "ConfigMap `api-config` was patched 47 minutes ago. The `cache.preload_on_startup` field flipped from `false` to `true`. The first OOMKill on the api pods was 3 minutes after that." 5. You decide whether to revert. It's not magic. The AI didn't fix anything. It just stitched the timeline together using tools that knew how Kubernetes objects relate to each other. Without MCP, that stitch takes the AI a lot of token-expensive raw YAML reads to figure out, and it's about a 50/50 shot whether it gets there before context runs out. With it, the stitch is the first three tool calls, and the answer is in the first response. ## What MCP isn't Two honest gaps. **Not a replacement for the UI.** I use both. MCP is for "I want to ask a question and get an answer." The UI is for "I want to see the shape of the cluster and decide what to do." They serve different jobs. **Not a replacement for runtime safety.** The write tools are explicit and narrower than a raw shell, but they still change real state. `apply_resource`, `patch_resource`, rollback, and drain deserve the same review you would give a human operating against prod - with a dry-run where available, a review, and a willingness to roll back. ## The shape of it The reason MCP-via-Radar works better than MCP-via-kubectl is that we'd already done the work of minifying, correlating, and securing cluster reads for the UI. Exposing the same surface area to AI tools is a small additional step on top of that, and the result is a context window that doesn't get burned on `managedFields` and a write surface that doesn't let the AI delete prod by accident. If you're already running Radar, MCP is on by default. If you're not, the open-source binary is the fastest way to point Claude or Cursor at one of your clusters and see what changes - install steps are at [radarhq.io/docs](https://radarhq.io/docs). --- ### The Fleet Visibility Gap: Why Teams With 5+ Clusters Hit a Wall - **URL**: https://radarhq.io/blog/the-fleet-visibility-gap - **Date**: 2026-02-27 - **Author**: Nadav Erell, CEO, Skyhook - **Category**: Platform - **Tags**: radar-cloud, kubernetes, multi-cluster, platform-engineering, for-devops It's the third time this week someone asked me which cluster our staging API actually runs in. Not "is staging healthy." Not "what's the error rate." Just: where does it live. The answer turned out to be `stg-eu-2`, a cluster spun up four months ago for a GDPR workload that quietly became the default for anything EU-adjacent. Nobody wrote that down. The person who knew left the company in September. ![Fleet visibility gap hero](/images/blog/fleet-visibility-gap-hero.png) One cluster is a debugging problem. Five clusters are an inventory problem, an access problem, and an incident coordination problem. If you're running one cluster, skip this post. If you're running two, bookmark it. If you're somewhere between five and fifty, you already know where this is going. ## How you end up with twelve clusters without planning to Nobody sits down and says "let's run twelve Kubernetes clusters." You start with one. Then you need a staging environment, because prod-shaped accidents are expensive. Two. Then someone points out that running staging and prod on the same control plane defeats the point, so you split the cloud accounts. Three, if you count dev. Then a customer in Frankfurt needs data residency. Four. Then your biggest customer wants a dedicated tenant for compliance. Five. Then the platform team decides per-team clusters are cleaner than shared namespaces for the new ML workloads. Eight. Then you acquire a company and inherit their GKE footprint. Eleven. That's a real trajectory. I spoke to a platform lead at a 60-person company last month who has 14 clusters across 3 regions - EKS in us-east-1 and eu-west-1, GKE in asia-southeast1 for latency reasons, plus four "temporary" clusters that have existed for over a year. They have two engineers on the platform team. The clusters aren't the problem. Kubernetes handles that part fine. The problem is that the tools you used to operate one cluster don't compose. ## The single-cluster assumption baked into every tool Walk through the standard debugging kit. Every single one of these - [k9s, Lens, Headlamp, and the rest](/blog/best-kubernetes-dashboards-2026) - assumes you're looking at one cluster at a time. **kubectl** has contexts. That's the official answer. In practice you end up with a `~/.kube/config` that's 400 lines long, a handful of `KUBECONFIG` env vars pointing at different files, and a shell alias wall that looks something like this: ```bash # ~/.zshrc, three months into the job alias kprod-us="kubectl --context=arn:aws:eks:us-east-1:1234:cluster/prod-us" alias kprod-eu="kubectl --context=arn:aws:eks:eu-west-1:1234:cluster/prod-eu" alias kstg-us="kubectl --context=arn:aws:eks:us-east-1:1234:cluster/stg-us" alias kstg-eu="kubectl --context=arn:aws:eks:eu-west-1:1234:cluster/stg-eu-2" alias kdev="kubectl --context=kind-dev" alias kacme="kubectl --context=gke_acme-prod_us-central1_acme" # ... and six more # the function everyone writes eventually kall() { for ctx in prod-us prod-eu stg-us stg-eu-2; do echo "=== $ctx ===" kubectl --context="$ctx" "$@" done } ``` That `kall` function is a tell. It's what you write the first time you need to check "are any of our clusters seeing the same CrashLoopBackOff?" It works for trivial commands. It falls apart the moment you need to correlate anything, or the moment one context hangs for 30 seconds because the VPN dropped. **k9s** is excellent. I use it daily. But it shows one cluster at a time. You switch contexts with `:ctx` and the whole UI reloads - events, pods, the lot. There's no "show me every failing pod across my fleet." Not k9s's job, and it's honest about that. **Lens and its forks** (OpenLens, Freelens) technically let you add multiple kubeconfigs to the sidebar. Each one opens in a separate workspace pane. You can't see them at once in any useful way, and switching between them triggers a full reload of the cluster state. On a machine with six clusters loaded, memory usage gets unpleasant. Lens itself has the mandatory cloud-login baggage that pushed a lot of us to look for an alternative in the first place. **Headlamp** supports multiple clusters better than most - it'll show them in the sidebar and you can click between them. But the views are per-cluster. There's no aggregated event feed, no cross-cluster search, no fleet dashboard. It's a competent single-cluster UI that tolerates being pointed at several kubeconfigs. **Per-cluster dashboards** (Grafana, Datadog cluster view, the EKS console) work well for what they show, but they're separate dashboards. You end up with a bookmark folder of twelve URLs and a habit of opening them in sequence every morning. ### The honest comparison | Tool | Multiple clusters supported | Aggregate view | Persistent cross-cluster history | Who it's for | |-------------------|-----------------------------|----------------|----------------------------------|------------------------------------| | kubectl | Via context switching | No | No | Everyone, always | | k9s | One at a time (fast switch) | No | No | Terminal natives debugging one cluster | | Lens / OpenLens | Multiple kubeconfigs loaded | No | No | GUI users on a single laptop | | Headlamp | Sidebar-style multi-cluster | Partial | No | Teams who want a browser-based UI | | Per-cluster dashboards | Yes, separately | No | Yes, per cluster | Ops teams with dedicated dashboards per env | None of these are bad. They're solving the single-cluster problem well. The fleet problem is a different problem. ## The hidden cost of not having fleet visibility You don't notice the gap all at once. It accumulates. **Longer incidents.** The on-call engineer pages in, opens their laptop, and spends the first four minutes figuring out which cluster the alert came from. Was it `prod-us` or `prod-eu-2`? The alert says `api-gateway` but there are three of those across the fleet. By the time they've switched context, opened logs, and cross-referenced the deploy history, the customer impact is already on Twitter. **Missed signal.** A ConfigMap change goes out to all production clusters via Argo CD. One of them rejects it because a CRD version is pinned to an older release. Nobody notices for six hours because the failure is buried in one cluster's events feed and nobody was looking at that tab. **Onboarding tax.** The new engineer joins. They need to know how to connect to every cluster, which ones are safe to click around in, which ones have stricter RBAC, which ones have the weird Istio setup from 2023. The only documentation is a Notion page that's been out of date since February. They spend their first two weeks building a mental map that the rest of the team carries in their heads. **Context reconstruction.** "What did we deploy to prod-eu on Tuesday?" is a question that should take five seconds. Without persistent cross-cluster history, it takes a Slack thread, a Git log, a CI run search, and someone eventually guessing. These costs don't show up on a dashboard. They show up as fatigue, as longer MTTR, as "we should rebuild our platform" conversations that don't lead anywhere. ## What a fleet tool needs to do If you were designing for the multi-cluster case from the start, a few properties fall out naturally: **Aggregate problems first, drill-down second.** The default landing page should show every cluster you operate, with health, recent events, and workload counts. Clicking into a cluster gets you the familiar single-cluster view. Most tools flip that - you pick a cluster, then see its state. **Search across clusters.** If you know a resource name, host, label, or package, you should not have to remember which cluster owns it. **Roll up checks.** A policy failure in one cluster is a ticket. The same failure across twenty clusters is a platform issue. **Show package drift.** Teams need to know which clusters are behind on cert-manager, Cilium, Argo CD, Karpenter, Linkerd, or any other package the tool can detect. **A shared context that isn't a kubeconfig.** Kubeconfigs were designed for one user on one machine. For a team, you want shared enrollment - a cluster gets connected once, everyone authorized can see it, access is managed centrally. No more Slack DMs with `kubeconfig.yaml` attached. **Outbound-only connectivity.** Nobody is opening an inbound port on their production cluster for a vendor dashboard. Any sane fleet tool dials out from the cluster, not the reverse. ## What Radar Cloud ships today Radar Cloud's fleet section answers four of those questions today: **Problems, Search, Checks, and Packages.** The views fan out to connected clusters over the tunnel and render progressively. For small fleets that is usually sub-second. For large fleets, expect the first load to take a few seconds as clusters answer. Two things are still evolving beyond that first set of fleet views: - **Cross-cluster topology** is not shipped. Radar topology is per-cluster today. Kubernetes does not have a native multi-cluster service graph, and pretending otherwise produces pretty diagrams that lie. - **Longer Cloud-backed timeline history.** Per-cluster timeline lives with the connected Radar instance: memory-backed by default, SQLite-backed if you configure it with a PVC. Cloud-backed retention as a hosted history layer is on the roadmap. That's the honest line. Cloud closes the practical fleet gap for current health, search, audit checks, and package drift, without making the hosted backend the live source of truth for every cluster object. ## The access problem Fleet visibility isn't only a UI problem. The team needs one enrollment path and one identity model. Otherwise every new engineer gets a zip file of kubeconfigs and a wiki page nobody trusts. Radar Cloud handles that through org membership, SSO, roles, and Kubernetes impersonation. Cloud decides who the user is. Kubernetes still decides what they can do in each cluster. That lets a platform team connect clusters once and manage humans centrally, without replacing Kubernetes RBAC. ## The honest state If what you need is one team URL that tells you where the problems are, where a resource lives, which checks are failing, and which packages are drifting - that is exactly the product. If you need a perfect service graph across meshes, regions, and DNS conventions, that is still hard. We're not pretending we shipped it. In the meantime, if this post describes your week, you're not alone. The tooling gap is real. Recognizing it is the first step toward not papering over it with another wall of shell aliases. --- ### What We're Building in 2026: Radar OSS and Radar Cloud - **URL**: https://radarhq.io/blog/what-were-building-in-2026-radar-oss-and-cloud - **Date**: 2026-01-28 - **Author**: Eyal Dulberg, CTO, Skyhook - **Category**: Announcements - **Tags**: radar, radar-cloud, kubernetes, open-source, roadmap Two shipping dates, one product line, and a clear split between what's free and what costs money. In January 2026 we're releasing **Radar** as open source under Apache 2.0. In February 2026 we're releasing **Radar Cloud**, the hosted multi-cluster version. This post is the engineering view of what lands in each, what doesn't, and why we drew the line where we did. ## Why two products instead of one We've spent the better part of a year talking to teams running Kubernetes at the messy middle of the curve: past the first production cluster, not yet big enough to have a platform team. The consistent pattern: they have three to twelve clusters, no good way to see them together, and a debugging experience that still leans on `kubectl` plus tabs. Radar (the OSS tool we built for ourselves) solves the single-cluster debugging problem. It's a Go binary with the React UI embedded via `go:embed`, runs against your kubeconfig, and shows you resources, topology, a timeline, Helm releases, GitOps state, and traffic - live, via SharedInformers on top of the Watch API. No in-cluster install. No cloud account. No data leaving your laptop. That covers one engineer debugging one cluster. It does not cover: - Multiple clusters visible in one place. - History that survives restarts and outlives your current kubeconfig session. - Alerts when something breaks at 3am and nobody's looking. - RBAC beyond whatever your kubeconfig already grants. - A shared URL to a specific resource at a specific time for your incident channel. Those are team problems. They need an identity layer, an org-scoped audit log, and a hub that's awake when you're not. Trying to solve them inside the OSS binary would make Radar slow, opinionated, and hard to run on a laptop. So we split. ## January 2026: Radar OSS Radar OSS ships as a single Go binary. The React frontend is compiled in. On startup it reads your kubeconfig, opens your browser, and connects directly to the API server. ```bash curl -fsSL https://get.radarhq.io | sh radar ``` Also available via Homebrew, Scoop, and an in-cluster Helm chart for teams that want a shared instance. What's in the v1 binary: - **Resources view** - browse every resource type, YAML edit, logs, events, exec, port-forward, image filesystem browsing. - **Topology view** - structured DAG of ownership, service routing, ingress paths, config dependencies. - **Timeline view** - live stream of Kubernetes events and resource changes, in-memory by default, SQLite-backed if you pass `--timeline-storage sqlite`. - **Helm view** - list, inspect, upgrade, rollback, uninstall; uses the Helm Go SDK directly, not shelling out. - **GitOps view** - Argo CD Applications and Flux Kustomizations / HelmReleases / GitRepositories show up in topology with sync status, and you can trigger sync / reconcile from the UI. - **Traffic view** - auto-detects Cilium / Hubble or Caretta and draws a live flow graph. - **Cluster audit** - 31 best-practice checks across security, reliability, and efficiency, surfaced inline on the affected resources. - **MCP server** - token-optimized, RBAC-aware cluster context for AI tools like Claude, Cursor, and Claude Code. CRDs are auto-discovered via dynamic informers, so Argo Rollouts, Istio VirtualServices, and your own CRDs appear without plugin work. Source goes public in January. Apache 2.0. We want PRs. ## February 2026: Radar Cloud Radar Cloud is a hosted control plane plus Radar deployed in each cluster. In-cluster Radar is the same Go binary as OSS (~32MB RSS steady state). Instead of serving a local UI, it dials out to `api.radarhq.io:443`, holds an outbound WebSocket open, and lets the control plane reverse-proxy authenticated browser requests through to it on demand. Cluster state stays in the cluster. The connection is **outbound-only**. No inbound ports. No NodePort, no LoadBalancer, no Ingress. If your cluster can reach the public internet, Radar works. If it can't, you stay on OSS. ```bash helm repo add skyhook https://skyhook-io.github.io/helm-charts helm repo update helm install radar skyhook/radar -n radar --create-namespace \ --set cloud.token=$RADAR_CLOUD_TOKEN ``` The enrollment token is issued from the Radar dashboard. Radar runs with a scoped Kubernetes ServiceAccount - read-only by default, read / write if you opt in for features like rollback from the UI. Logs, exec streams, and port-forwards all go through Radar on demand and are never stored at rest. In GA on February release: - **Fleet views** across every connected cluster: problems, cross-cluster search, audit-check rollups, package drift. - **Live timeline** served live through the reverse proxy from the in-cluster Radar pod. - **SSO on every plan**: Okta, Google Workspace, Entra ID, OneLogin, generic SAML / OIDC, via WorkOS. - **Kubernetes-native RBAC** via impersonation: three default roles (`owner`, `member`, `viewer`) bound to standard K8s ClusterRoles, plus per-user RoleBindings via `cloud:user:` groups. - **Audit log** with tier-based retention: 7 days on Free, 30 days on Team, 365 days on Enterprise. - **Notifications** for hub events (cluster connect / disconnect, billing, member invites) over Slack, webhook, and an in-app inbox. - **Shareable deep links** per resource and view. - **REST API** for automation. - **MCP server per cluster** for AI tools (Claude, Cursor, Claude Code, etc.). - **SOC 2 Type II** compliance. - **Data residency** in US (us-east-1) or EU (eu-west-1). SCIM 2.0 directory sync ships on Enterprise for teams that need directory-driven user and group lifecycle from their IdP. The control plane is Go microservices on PostgreSQL; it doesn't store cluster state - all cluster data is served live from the in-cluster Radar pod. ## The product boundary | Concern | Radar OSS | Radar Cloud | | --- | --- | --- | | Cluster resources | Yes | Served through in-cluster Radar | | Topology | Per-cluster | Per-cluster through tunnel | | Timeline | Local memory or SQLite | Per-cluster through tunnel | | Cluster audit | Yes | Per-cluster plus fleet rollups | | MCP | Local endpoint | Per-cluster Cloud endpoint via PAT | | Orgs and members | No | Yes | | SSO | Self-managed OIDC / proxy if you deploy it | WorkOS SAML / OIDC | | Audit log | Local / K8s context | Cloud control-plane activity | | Fleet views | No | Problems, search, checks, packages | | Billing | No | Stripe | No cluster feature is held back from OSS just because Cloud exists. ## What's not in v1 Being specific about gaps is more useful than listing features. - **No cross-cluster topology yet.** Fleet views give you the aggregate dashboard for problems, search, checks, and packages. A true cross-cluster topology graph (tracing a service mesh request from cluster A to cluster B) is on the roadmap, not a launch feature. - **No cross-cluster timeline yet.** Per-cluster timeline works through the reverse proxy. A unified timeline that joins events across clusters is on the roadmap. - **No long-term Cloud-backed event archive.** Cloud doesn't store your Kubernetes events; they live in the cluster with optional SQLite persistence in-cluster. If you need long retention, ship to a SIEM. - **No Windows node support.** Radar ships as a Linux container only. We don't have Windows nodes in our test matrix, and we'd rather not claim support we haven't exercised. - **No event-rule alerting on arbitrary K8s events.** Cloud notifications cover hub-side events only (connection, billing, invites). If you want pager-style alerting on K8s event streams, that's Prometheus / Alertmanager territory; we're not going to be that system. - **Self-hosted control plane below Enterprise.** More on this below. ## The self-hosted question We've been asked this enough that it deserves a paragraph. Radar Cloud is a multi-tenant hosted service by default. Packaging the control plane into a single-tenant BYOC / on-prem install is a real project, which is why we only support it on the **Enterprise** tier. Free and Team are SaaS-only. This matters for two groups: teams in air-gapped environments (defense, some finance, some regulated health workloads) and teams whose security policy prohibits outbound telemetry to a shared multi-tenant SaaS. If you need to keep data inside your own infrastructure, Enterprise BYOC is the path; if you don't need the Cloud backend at all, **Radar OSS is the right answer**, and it will stay the right answer. We are not going to cripple OSS to push you toward Cloud. ## When to use which **Use Radar OSS when you're a single engineer** debugging your own cluster, when you're working in an air-gapped environment, when you need a fast local tool for incident response without logging in to anything, or when you want to see what a cluster is doing in under ten seconds flat. It's a better `kubectl` for most day-to-day visibility work. **Use Radar Cloud when you're a team.** When you want a teammate's URL to land them on the same cluster you're looking at. When "who changed that ConfigMap" needs an audit log answer. When your engineers log in with Okta and you don't want to hand out kubeconfigs as the unit of access control. When a cluster going dark while nobody's watching needs to ping someone. | | Radar (OSS) | Radar Cloud | |---|---|---| | Install location | Your laptop or a shared in-cluster pod | Hosted control plane; Radar per cluster | | Multi-cluster | One context at a time | Fleet views across all connected clusters | | Event timeline | In-memory or SQLite (in-cluster) | Live, served via reverse-proxy from the in-cluster pod | | Audit log | - | 7 days Free / 30 days Team / 365 days Enterprise | | Auth | Your kubeconfig | SAML / OIDC SSO on every plan; SCIM on Enterprise | | RBAC | Whatever your kubeconfig grants | K8s impersonation - 3 default roles + per-user RoleBindings | | Notifications | None | Slack, webhook, in-app inbox (hub events: connection, billing, invites) | | Data residency | Your machine | US (us-east-1) or EU (eu-west-1); BYOC on Enterprise | | SLA | None - it's a binary you run | 99.5% on Team, 99.9% on Enterprise | | Pricing | Free, Apache 2.0 | Free (3 clusters), $99 / cluster / month Team, Enterprise custom | ## The rest of 2026 **Q2:** Cross-cluster topology, cross-cluster timeline, deeper provider-specific renderers, MCP tool expansion. **Q3:** Cloud-backed timeline retention, deeper GitOps workflows (drift detection history, rollback orchestration across clusters), expanded Windows support if the demand signal is there. **Q4:** The self-hosted control plane story for tiers below Enterprise, if customer signal warrants it. If you want to follow along, the OSS source goes public in January and the Radar Cloud waitlist is open at [radarhq.io](https://radarhq.io). We'll post install-day walkthroughs for both.