Skip to content
Dudude-bitPublic

About

Modern cross-platform Kubernetes GUI client built with Tauri and Rust

Topics

Resources

Contributing

Security policy

Stars

99 stars

Watchers

2 watching

Forks

Latest commit

 

History

625 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rubick

A desktop Kubernetes client that tries not to lie to you.

Like Lens, k9s or Headlamp, it reads your kubeconfig and shows your clusters.
Unlike them, it treats "I don't know" as an answer worth giving.

Download

rubick.tech — the website, with honest comparisons to Lens, k9s and Headlamp.

CI Release Downloads License

Free and GPLv3. No account, no telemetry.

Rubick on a workload page

Why another one

It shows the failure, not the field. A pod whose container is crash-looping reports Running, because that is what .status.phase holds. A Service with healthy pods and a mistyped port name publishes nothing and still draws green. Rubick derives status the way kubectl does and reads the endpoints the cluster actually publishes, so those two stop being invisible.

It says where the path stops. Ingress → Service → pods is drawn on the workload's own page, and when nothing is behind an address it names the reason: a backend that does not exist, a selector matching nothing, or pods running but not ready.

It warns before it obeys. Scale, Restart, Delete and Edit YAML tell you who will undo the change and how fast — an autoscaler in seconds, Argo CD or Flux in minutes. Then it does what you asked, because a hand edit during an incident is legitimate.

It says what it cannot see. A desktop app does not inherit your shell's environment, so at startup Rubick asks your login shell for it, .zshrc and .bashrc included, and adopts what comes back: PATH, AWS_PROFILE, KUBECONFIG and the rest. Settings → Diagnostics says whether that worked, names the directories it actually searches, which plugins resolve in them, and what each context needs, and copies the lot, redacted, for when the machine with the problem is not yours.

A path that stops, and why

What you get

Area What Rubick shows
Workloads Pods, Deployments, StatefulSets, DaemonSets, ReplicaSets, Jobs, CronJobs — with init containers as an ordered sequence, sidecars told apart from them, and CPU/memory over time
Logs Virtualised, multi-container, server-side filtering, repeat collapsing — and they open where the answer is: on a pod stuck in init, that means the failing container's previous run
Shell A real tab per pod whose session survives you looking elsewhere
Network Services, Ingresses, Endpoints and EndpointSlices, with the traffic chain above
Gateway API Gateways, all five route kinds, ListenerSets, classes and policies. A route says whether it is serving, and where it is not, which of the eight links between a listener and a pod broke — with the controller's own words. A route that attaches to a ListenerSet belongs to that set's Gateway and is judged there. A map draws the whole road; a probe from your machine answers what the cluster cannot
Storage & config PVs, PVCs, StorageClasses, ConfigMaps, Secrets — binary values shown as binary, private keys never revealed
Custom resources Every CRD, with YAML editing and validation
Helm Releases, revisions, rollback, uninstall

Logs open on the container that failed

Integrations

Detected ones need nothing from you — their CRDs are in the cluster or they are not. Configured ones need an address, and Rubick never goes looking for one.

Integration What it gives you
Routing Traefik, ingress-nginx, Istio — hosts, rules and middleware read as routing. nginx annotations become sentences with the raw key beside each; a configuration-snippet is shown verbatim and never paraphrased
Certificates cert-manager — expiry wherever TLS is named, and the issuance chain when renewal fails
Delivery Argo CD and Flux — every object says whether it is delivered, from which revision, and whether your edit will survive
Metrics Prometheus — real history, disk fullness and network traffic, none of which metrics.k8s.io can answer. VictoriaMetrics speaks the same API and is asked for the subpath it serves it under, /prometheus or /select/<tenant>/prometheus
Logs Loki — so a crashed pod's logs outlive the pod
Clouds GKE, EKS, AKS node pools, machine types, zones and spot status, read from labels with no cloud account
Cloud ingress GKE Ingress, the AWS Load Balancer Controller and AGIC — the certificate none of them keeps in spec.tls, and one row per ALB rather than per Ingress, because group.name puts several namespaces on one
Local & nodes k3s, k3d and minikube — a local cluster reads as local rather than as the cloud its name imitates. Karpenter — nodes reported under the pool that made them, and no pool called spot on the strength of one node

Adding one costs a folder and a line — see CONTRIBUTING.

Prometheus and Loki live in your cluster, and Rubick asks from your machine. So http://prometheus.monitoring:9090 — the address every chart's README gives you — resolves to nothing here: it is a name only the cluster answers. Press Find it in this cluster in the connect dialog and Rubick forwards a local port to the Service and fills the address in for you. It picks the component that can answer a query, not the write path, and moves the forward to a new pod when the old one is rolled. An Ingress hostname or a LoadBalancer address works too, if you have one.

AWS and Azure are the least exercised paths here, and issues are very welcome. Rubick is developed against a GKE cluster running Traefik and cert-manager, so those are the ones that get looked at every day. The EKS and AKS halves — ALB groups, IngressClassParams, ACM certificates, AGIC annotations, Workload ID — were built from the controllers' documented behaviour and covered with unit tests, not against a live cluster of either kind. If something reads wrong on yours, that is worth an issue even without a diagnosis: paste the objects and say what you expected. Being wrong about your cluster is the one thing this app is not allowed to be.

Integrations, with what each is doing

Getting around

Every name you can go to is a link, with the gestures you expect: click to peek, middle-click for a background tab, shift for a foreground one. Tabs carry a route and a scope, so several clusters stay open side by side. Search reaches across clusters — !cluster-name aims it. Light and dark, and identity colouring that still works in greyscale or with colour blindness.

English and Russian, switched in Settings. What gets translated is the app's own words; what the cluster wrote does not. A kind is called Pods in both, a status stays CrashLoopBackOff because its colour is looked up by that string, and a controller's message is quoted rather than paraphrased — a translated error is the app putting words in your cluster's mouth.

More screenshots
Connections, grouped by question
Connections — grouped by the question you are asking
Scaling something an autoscaler owns
Before you act — who will undo this, and how fast
Usage with real history
Usage — the watched window, or real ranges with Prometheus
Search, from anywhere
Search — across clusters, aimed with !cluster-name

The same page in the light theme

Light theme — the same page, the same tokens.

What it deliberately does not do

  • No cost estimates. Committed use, sustained use, spot pricing and negotiated rates make them wrong more often than right, and a wrong number about money poisons the right ones.
  • No whole-cluster topology graph. Routing is a chain in fixed order, not a general graph; a force-directed blob looks like insight and answers nothing.
  • No editing routes or renewing certificates. Reading them well is a feature; writing them is a different one with a different blast radius — an ACME rate limit is five failures an hour.
  • No guessing. If a name in a log line might be an object, it stays text. If an integration was never asked, the app says not looked at rather than leaving a gap that reads as nothing there.

Install

brew install --cask Dudude-bit/tap/rubick   # macOS

Or grab the build for your platform from Releases. On Arch, rubick-kubernetes-bin is in the AUR, maintained by @Prototik from the same .deb published here — thanks to him for it. There is no winget package: the Windows installers are unsigned, and winget installs are meant to run without a dialog in the way.

  • macOS — signed with a Developer ID certificate and notarised by Apple, so it opens on a double-click.
  • Windows — not signed, so SmartScreen will warn on the first launch. More info → Run anyway.
  • Linux — .deb, .rpm and an .AppImage that needs nothing installed.

What it talks to. Your clusters, and GitHub for update checks. Nothing else: there is no analytics, no account and no crash reporting, and any integration you connect is an address you typed yourself.

Requirements. Kubernetes 1.21+ (EndpointSlices). Cloud login (EKS, GKE, AKS, OIDC, exec plugins) uses the same credentials kubectl does; Settings → Clusters shows each context, how it authenticates, and what is missing if it cannot.

Development

mise install   # Bun, Node, Rust
bun install    # the Tauri CLI comes with it
make dev       # run it
make build     # package it

Needs Bun 1.3+, Rust 1.91+, and the Tauri prerequisites for your platform.

bunx tsc --noEmit                                     # types
bun run lint                                          # eslint, zero warnings
bun run test                                          # frontend tests
cargo test --workspace                                # Rust tests

A block of lint rules keeps the codebase from drifting back, and each fails the commit: colours must be role tokens and no component may branch on the theme; nothing outside src/integrations/ may name a vendor; polling rates go through useLiveQuery rather than a hand-written interval; a StatusBadge keeps the untranslated status, because its colour is a table lookup; and <select> comes from components/ui, because the native one is painted by the OS and ignores the theme. CONTRIBUTING says why each exists.

Idle polling was measured and cut 77% — from ~895 to ~205 API requests a minute — so leaving the window open does not tax the cluster. A query that has slowed down says so rather than showing a stale number under a live badge.

Built with Tauri 2, Rust and kube-rs; React 19, TypeScript, TanStack Query, CodeMirror, xterm.js and Recharts.

Asking something

Discussions is the place for a question, for carrying on after an issue is closed, and for an idea that has not taken shape yet. Answers there stay searchable for whoever hits the same thing next. A bug or a feature with a clear shape is still an issue.

License

GPL-3.0-or-later — see LICENSE.

Fork it, change it; ship the source with it. Running the app is not distribution, so using it — at home or across a company — carries no obligation at all. Releases up to 3.1.0 were MIT and stay MIT: LICENSE-HISTORY.md has the details.

About

Modern cross-platform Kubernetes GUI client built with Tauri and Rust

Topics

Resources

Contributing

Security policy

Stars

99 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages