Tools: K9s — The Terminal UI That Changes How You Do Kubernetes

Tools: K9s — The Terminal UI That Changes How You Do Kubernetes

Table of Contents

Why kubectl Alone Isn't Enough

kubectl vs K9s Side by Side

What is K9s?

Installation

macOS — Homebrew

Windows

Docker

Verify Installation

Launch Flags

Core Features

🔴 Real-Time Cluster State

⌨️ Fully Keyboard Driven

📊 CPU & Memory Metrics

🔍 Fuzzy Search & Filter

🎨 Skins & Plugins

🔐 RBAC-Aware

📦 Multi-Context / Multi-Cluster

🔖 Built-in Benchmarking

🔭 X-Ray View

🧹 Popeye Integration

Complete Shortcut Reference

Global Navigation

Pod Management

Log Viewer

Services & Networking

Deployments, ReplicaSets & StatefulSets

Nodes & Cluster Management

ConfigMaps, Secrets & Storage

RBAC & Access Control

Jobs & CronJobs

Workloads

Networking

Cluster

Config & Storage

Auto-scaling

Advanced Views

5 Workflows That Will Save You Hours

🔥 1. Debug a CrashLoopBackOff Pod

📈 2. Investigate a Memory Spike

🔁 3. Rolling Restart a Deployment

🌍 4. Test a Service Locally with Port-Forward

⚠️ 5. Drain a Node for Maintenance

Pro Tips & Power User Tricks

🎨 Custom Skins / Themes

🔌 Custom Plugins

🔭 X-Ray View — Dependency Trees

🧹 Popeye — Cluster Sanitizer

⚙️ K9s Configuration File

Conclusion

Why K9s belongs in every engineer's toolkit: Stop memorizing endless kubectl commands. K9s gives you a real-time, interactive terminal dashboard for managing every resource in your cluster — with keyboard shortcuts for everything. Anyone who has spent serious time with Kubernetes knows the pain: debugging a crashing pod means running four or five different commands just to understand what's happening. You're constantly context-switching between terminal windows, squinting at JSON blobs, and copy-pasting pod names. That's five commands, three copy-pastes, and a lot of cognitive overhead — just for one pod. K9s is an open-source, terminal-based UI built by Fernand Galiana that wraps the entire Kubernetes API in a fast, keyboard-driven interface. It's not a GUI — it lives in your terminal, it's blazing fast, and once you learn the shortcuts, you'll never want to go back to plain kubectl. 💡 Think of K9s as htop for Kubernetes — it continuously watches your cluster state and updates in real time. K9s runs on Linux, macOS, and Windows. Pick your method: K9s auto-detects your ~/.kube/config on launch. ⚠️ Production Safety Tip: Always use k9s --readonly when connecting to production clusters. This disables all mutating operations and prevents accidental deletes or edits. K9s continuously polls your cluster and refreshes the view automatically. Watch pods crash and recover without hitting a single key. Every action — logs, exec, describe, delete, port-forward — is one or two keystrokes away. Zero mouse needed. Type :pod, :svc, :deploy, :node or any CRD name. K9s handles every Kubernetes resource type including custom ones. Built-in pulse view shows live resource usage per pod and node. Color-coded thresholds alert you before things go down. Press / to filter any resource list instantly. Supports regex patterns for precise searching across thousands of resources. Customize colors, create your own keyboard shortcuts, and extend K9s with community or custom plugins. K9s respects your cluster's RBAC configuration. Users only see what they're permitted to see — no special access needed. Switch between clusters and contexts instantly without restarting. Perfect for managing dev, staging, and production clusters. Load test a service endpoint directly from the K9s interface using Ctrl+B on any service. No external tool needed. Renders the full dependency tree of any resource — deployments → replicasets → pods → containers — all in one view. Type :popeye to run a live cluster sanitizer that scans for misconfigurations, deprecated APIs, and security risks. 💡 Vim users: K9s supports j/k for navigation, g/G for top/bottom, and / to search. You're already home. These shortcuts work from any view in K9s. Enter :pod or :po to access this view. Press l on any pod to enter the log viewer. Type these with : from anywhere in K9s to jump to any resource view instantly. All without leaving K9s, all without remembering a single pod name. No more copy-pasting: kubectl rollout restart deployment/my-app -n production K9s supports fully custom color themes. Place a skin YAML in ~/.config/k9s/skins/. Popular community themes: All available in the K9s skins repo. Create ~/.config/k9s/plugins.yaml to add custom commands to any resource view. Example — tail logs with stern: Example — open resource in VS Code: One of K9s's most powerful hidden features: This renders the full dependency tree of all deployments in the default namespace: Perfect for understanding resource relationships and ownership chains. Popeye scans your cluster for: It gives each resource a grade (A–F) so you know exactly what to fix. K9s config lives at ~/.config/k9s/config.yaml: Add custom aliases in ~/.config/k9s/aliases.yaml: K9s isn't just a nice-to-have — it's the kind of tool that makes you genuinely faster at your job. Whether you're debugging a production incident at 2am or iterating on a local cluster, K9s cuts through the ceremony and gets you to the information you need instantly. Install it today. The first time you press l to tail logs and then s to shell in — without typing a single pod name — you'll understand why 30,000+ engineers consider K9s essential. If this helped you, drop a ❤️ and share it with your team. Found a shortcut I missed? Drop it in the comments below! 👇 Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

# The old way — just to debug ONE crashing pod -weight: 500;">kubectl get pods -n production -weight: 500;">kubectl describe pod api-gateway-7d9f8b-xkp2q -n production -weight: 500;">kubectl logs api-gateway-7d9f8b-xkp2q -n production --previous -weight: 500;">kubectl exec -it api-gateway-7d9f8b-xkp2q -n production -- /bin/sh -weight: 500;">kubectl port-forward api-gateway-7d9f8b-xkp2q 8080:80 -n production # The old way — just to debug ONE crashing pod -weight: 500;">kubectl get pods -n production -weight: 500;">kubectl describe pod api-gateway-7d9f8b-xkp2q -n production -weight: 500;">kubectl logs api-gateway-7d9f8b-xkp2q -n production --previous -weight: 500;">kubectl exec -it api-gateway-7d9f8b-xkp2q -n production -- /bin/sh -weight: 500;">kubectl port-forward api-gateway-7d9f8b-xkp2q 8080:80 -n production # The old way — just to debug ONE crashing pod -weight: 500;">kubectl get pods -n production -weight: 500;">kubectl describe pod api-gateway-7d9f8b-xkp2q -n production -weight: 500;">kubectl logs api-gateway-7d9f8b-xkp2q -n production --previous -weight: 500;">kubectl exec -it api-gateway-7d9f8b-xkp2q -n production -- /bin/sh -weight: 500;">kubectl port-forward api-gateway-7d9f8b-xkp2q 8080:80 -n production ____ __.________ | |/ _/ __ \______ | < \____ / ___/ | | \ / /\___ \ |____|__ \ /____//____ > \/ \/ K9s — Kubernetes CLI To Manage Your Clusters In Style! ____ __.________ | |/ _/ __ \______ | < \____ / ___/ | | \ / /\___ \ |____|__ \ /____//____ > \/ \/ K9s — Kubernetes CLI To Manage Your Clusters In Style! ____ __.________ | |/ _/ __ \______ | < \____ / ___/ | | \ / /\___ \ |____|__ \ /____//____ > \/ \/ K9s — Kubernetes CLI To Manage Your Clusters In Style! -weight: 500;">brew -weight: 500;">install derailed/k9s/k9s -weight: 500;">brew -weight: 500;">install derailed/k9s/k9s -weight: 500;">brew -weight: 500;">install derailed/k9s/k9s # Via webinstall -weight: 500;">curl -sS https://webinstall.dev/k9s | bash # Via Snap -weight: 600;">sudo snap -weight: 500;">install k9s # Via -weight: 500;">apt (Ubuntu/Debian) -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install k9s # Via binary — download from GitHub releases -weight: 500;">wget https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_amd64.tar.gz tar -xzf k9s_Linux_amd64.tar.gz -weight: 600;">sudo mv k9s /usr/local/bin/ # Via webinstall -weight: 500;">curl -sS https://webinstall.dev/k9s | bash # Via Snap -weight: 600;">sudo snap -weight: 500;">install k9s # Via -weight: 500;">apt (Ubuntu/Debian) -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install k9s # Via binary — download from GitHub releases -weight: 500;">wget https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_amd64.tar.gz tar -xzf k9s_Linux_amd64.tar.gz -weight: 600;">sudo mv k9s /usr/local/bin/ # Via webinstall -weight: 500;">curl -sS https://webinstall.dev/k9s | bash # Via Snap -weight: 600;">sudo snap -weight: 500;">install k9s # Via -weight: 500;">apt (Ubuntu/Debian) -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install k9s # Via binary — download from GitHub releases -weight: 500;">wget https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_amd64.tar.gz tar -xzf k9s_Linux_amd64.tar.gz -weight: 600;">sudo mv k9s /usr/local/bin/ # Chocolatey choco -weight: 500;">install k9s # Scoop scoop -weight: 500;">install k9s # Chocolatey choco -weight: 500;">install k9s # Scoop scoop -weight: 500;">install k9s # Chocolatey choco -weight: 500;">install k9s # Scoop scoop -weight: 500;">install k9s -weight: 500;">docker run --rm -it \ -v ~/.kube/config:/root/.kube/config \ quay.io/derailed/k9s -weight: 500;">docker run --rm -it \ -v ~/.kube/config:/root/.kube/config \ quay.io/derailed/k9s -weight: 500;">docker run --rm -it \ -v ~/.kube/config:/root/.kube/config \ quay.io/derailed/k9s k9s version k9s # Launch! k9s version k9s # Launch! k9s version k9s # Launch! 1. :pod → open pod view 2. /api-gateway → filter by name 3. l → stream current logs 4. p → view previous container logs (before crash) 5. d → describe pod, check Events section 6. s → shell in if the pod is running 1. :pod → open pod view 2. /api-gateway → filter by name 3. l → stream current logs 4. p → view previous container logs (before crash) 5. d → describe pod, check Events section 6. s → shell in if the pod is running 1. :pod → open pod view 2. /api-gateway → filter by name 3. l → stream current logs 4. p → view previous container logs (before crash) 5. d → describe pod, check Events section 6. s → shell in if the pod is running 1. Ctrl+P → open the pulse metrics panel 2. :pod → go to pod view 3. Shift+M → sort by memory usage (highest first) 4. Select offender → Enter → select container 5. s → shell in and run `top` or `ps aux` 1. Ctrl+P → open the pulse metrics panel 2. :pod → go to pod view 3. Shift+M → sort by memory usage (highest first) 4. Select offender → Enter → select container 5. s → shell in and run `top` or `ps aux` 1. Ctrl+P → open the pulse metrics panel 2. :pod → go to pod view 3. Shift+M → sort by memory usage (highest first) 4. Select offender → Enter → select container 5. s → shell in and run `top` or `ps aux` 1. :deploy → open deployments view 2. Navigate to deployment 3. Ctrl+L → triggers rolling -weight: 500;">restart instantly 4. Enter → drill into pods and watch new ones come up live 1. :deploy → open deployments view 2. Navigate to deployment 3. Ctrl+L → triggers rolling -weight: 500;">restart instantly 4. Enter → drill into pods and watch new ones come up live 1. :deploy → open deployments view 2. Navigate to deployment 3. Ctrl+L → triggers rolling -weight: 500;">restart instantly 4. Enter → drill into pods and watch new ones come up live 1. :svc → open services view 2. Select -weight: 500;">service 3. Shift+F → port-forward dialog opens 4. Enter local port (e.g., 8080) 5. Access at localhost:8080 in your browser 6. :pf → manage or -weight: 500;">stop active port-forwards anytime 1. :svc → open services view 2. Select -weight: 500;">service 3. Shift+F → port-forward dialog opens 4. Enter local port (e.g., 8080) 5. Access at localhost:8080 in your browser 6. :pf → manage or -weight: 500;">stop active port-forwards anytime 1. :svc → open services view 2. Select -weight: 500;">service 3. Shift+F → port-forward dialog opens 4. Enter local port (e.g., 8080) 5. Access at localhost:8080 in your browser 6. :pf → manage or -weight: 500;">stop active port-forwards anytime 1. :node → open nodes view 2. Select the node to maintain 3. Ctrl+U → cordon it (no new pods scheduled) 4. Watch pods reschedule to other nodes in real time 5. Ctrl+D → drain the node (evict remaining pods) 6. Do your maintenance work 7. Ctrl+N → uncordon to bring it back 1. :node → open nodes view 2. Select the node to maintain 3. Ctrl+U → cordon it (no new pods scheduled) 4. Watch pods reschedule to other nodes in real time 5. Ctrl+D → drain the node (evict remaining pods) 6. Do your maintenance work 7. Ctrl+N → uncordon to bring it back 1. :node → open nodes view 2. Select the node to maintain 3. Ctrl+U → cordon it (no new pods scheduled) 4. Watch pods reschedule to other nodes in real time 5. Ctrl+D → drain the node (evict remaining pods) 6. Do your maintenance work 7. Ctrl+N → uncordon to bring it back plugin: stern: shortCut: Shift-S description: "Stern multi-pod tail" scopes: - pods command: stern background: false args: - $NAME - -n - $NAMESPACE plugin: stern: shortCut: Shift-S description: "Stern multi-pod tail" scopes: - pods command: stern background: false args: - $NAME - -n - $NAMESPACE plugin: stern: shortCut: Shift-S description: "Stern multi-pod tail" scopes: - pods command: stern background: false args: - $NAME - -n - $NAMESPACE plugin: vscode: shortCut: Shift-V description: "Open YAML in VSCode" scopes: - all command: bash background: false args: - -c - "-weight: 500;">kubectl get $RESOURCE_NAME $NAME -n $NAMESPACE -o yaml | code -" plugin: vscode: shortCut: Shift-V description: "Open YAML in VSCode" scopes: - all command: bash background: false args: - -c - "-weight: 500;">kubectl get $RESOURCE_NAME $NAME -n $NAMESPACE -o yaml | code -" plugin: vscode: shortCut: Shift-V description: "Open YAML in VSCode" scopes: - all command: bash background: false args: - -c - "-weight: 500;">kubectl get $RESOURCE_NAME $NAME -n $NAMESPACE -o yaml | code -" :xray deploy default :xray deploy default :xray deploy default Deployment/api-gateway └── ReplicaSet/api-gateway-7d9f8b ├── Pod/api-gateway-7d9f8b-xkp2q │ ├── Container/api-gateway (Running) │ └── Container/sidecar (Running) └── Pod/api-gateway-7d9f8b-r9pmk └── Container/api-gateway (Running) Deployment/api-gateway └── ReplicaSet/api-gateway-7d9f8b ├── Pod/api-gateway-7d9f8b-xkp2q │ ├── Container/api-gateway (Running) │ └── Container/sidecar (Running) └── Pod/api-gateway-7d9f8b-r9pmk └── Container/api-gateway (Running) Deployment/api-gateway └── ReplicaSet/api-gateway-7d9f8b ├── Pod/api-gateway-7d9f8b-xkp2q │ ├── Container/api-gateway (Running) │ └── Container/sidecar (Running) └── Pod/api-gateway-7d9f8b-r9pmk └── Container/api-gateway (Running) k9s: refreshRate: 2 # seconds between refreshes maxConnRetry: 5 readOnly: false # set true to make read-only globally noExitOnCtrlC: false ui: enableMouse: false headless: false logoless: false crumbsless: false reactive: false noIcons: false skipLatestRevCheck: false disablePodCounting: false shellPod: image: busybox namespace: default limits: cpu: 100m memory: 100Mi k9s: refreshRate: 2 # seconds between refreshes maxConnRetry: 5 readOnly: false # set true to make read-only globally noExitOnCtrlC: false ui: enableMouse: false headless: false logoless: false crumbsless: false reactive: false noIcons: false skipLatestRevCheck: false disablePodCounting: false shellPod: image: busybox namespace: default limits: cpu: 100m memory: 100Mi k9s: refreshRate: 2 # seconds between refreshes maxConnRetry: 5 readOnly: false # set true to make read-only globally noExitOnCtrlC: false ui: enableMouse: false headless: false logoless: false crumbsless: false reactive: false noIcons: false skipLatestRevCheck: false disablePodCounting: false shellPod: image: busybox namespace: default limits: cpu: 100m memory: 100Mi aliases: dp: deployments ing: ingresses sts: statefulsets pp: v1/pods crds: apiextensions.k8s.io/v1/customresourcedefinitions aliases: dp: deployments ing: ingresses sts: statefulsets pp: v1/pods crds: apiextensions.k8s.io/v1/customresourcedefinitions aliases: dp: deployments ing: ingresses sts: statefulsets pp: v1/pods crds: apiextensions.k8s.io/v1/customresourcedefinitions -weight: 500;">brew -weight: 500;">install derailed/k9s/k9s && k9s -weight: 500;">brew -weight: 500;">install derailed/k9s/k9s && k9s -weight: 500;">brew -weight: 500;">install derailed/k9s/k9s && k9s - Why -weight: 500;">kubectl Alone Isn't Enough - What is K9s? - Installation - Core Features - Complete Shortcut Reference Global Navigation Pod Management Log Viewer Services & Networking Deployments, ReplicaSets & StatefulSets Nodes & Cluster Management ConfigMaps, Secrets & Storage RBAC & Access Control Jobs & CronJobs Custom Resources (CRDs) - Global Navigation - Pod Management - Services & Networking - Deployments, ReplicaSets & StatefulSets - Nodes & Cluster Management - ConfigMaps, Secrets & Storage - RBAC & Access Control - Jobs & CronJobs - Custom Resources (CRDs) - All Resource Commands at a Glance - 5 Workflows That Will Save You Hours - Pro Tips & Power User Tricks - Global Navigation - Pod Management - Services & Networking - Deployments, ReplicaSets & StatefulSets - Nodes & Cluster Management - ConfigMaps, Secrets & Storage - RBAC & Access Control - Jobs & CronJobs - Custom Resources (CRDs) - ⭐ 30,000+ GitHub stars - 🐕 Named after the "canine" unit — it "watches" your cluster - 🔄 Real-time polling — no manual refresh needed - 🔐 Fully RBAC-aware — respects your cluster permissions - 🧩 Supports every Kubernetes resource including CRDs - Dracula — dark purple theme - Tokyo Night — muted dark blues - Catppuccin — soft pastel palette - Monokai — classic terminal colors - 🔴 Misconfigured resources - 🟡 Over-provisioned CPU/memory requests - 🟠 Deprecated API versions in use - 🔵 Missing resource limits - 🔐 Security risks (privileged containers, host mounts) - ⚡ Speed — keyboard shortcuts beat -weight: 500;">kubectl commands every time - 👁️ Visibility — real-time view of your entire cluster in one screen - 🔍 Debugging — logs, shell, describe, events — all in two keystrokes - 🛡️ Safety — --readonly mode for production, RBAC-aware by default - 🧩 Extensible — plugins, skins, aliases, custom shortcuts - 🆓 Free & Open Source — Apache 2.0 license, actively maintained - 🌐 K9s Official Website - ⭐ K9s GitHub Repository - 🎨 Community Skins - 🔌 Community Plugins - 📖 K9s Documentation