K9s: The Ultimate Kubernetes Terminal UI for Cluster Management
K9s is a terminal-based UI for managing Kubernetes clusters that provides a fast, efficient alternative to kubectl commands and web dashboards. This comprehensive guide covers everything you need to master K9s for daily Kubernetes operations.
What is K9s?
K9s is an open-source, terminal-based UI that provides:
Key Features
- Real-time Monitoring: Live view of cluster resources with auto-refresh
- Resource Navigation: Quick navigation between namespaces and resources
- Vim-style Shortcuts: Keyboard-driven workflow for power users
- Context Switching: Easy switching between clusters and contexts
- Built-in Shell: Execute commands directly in pods
- Log Streaming: Tail logs from multiple containers
- Resource Editing: Edit resources with your preferred editor
- Custom Views: Create custom resource views and aliases
- Plugins: Extend functionality with custom plugins
- Port Forwarding: Manage port forwards from the UI
K9s vs. Other Tools
| Feature | K9s | kubectl | Lens | Octant |
|---|---|---|---|---|
| Interface | Terminal | CLI | Desktop GUI | Web UI |
| Speed | Very Fast | Fast | Medium | Medium |
| Resource Usage | Minimal | Minimal | High | Medium |
| Offline Mode | ✅ Yes | ✅ Yes | ⚠️ Limited | ❌ No |
| Multi-cluster | ✅ Easy | ✅ Manual | ✅ Easy | ✅ Easy |
| Customization | ✅ Extensive | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited |
| Learning Curve | Moderate | Low | Low | Low |
Installation
macOS
# Using Homebrewbrew install derailed/k9s/k9s
# Upgradebrew upgrade k9s
# Using MacPortssudo port install k9sLinux
# Download latest releasewget https://github.com/derailed/k9s/releases/download/v0.31.9/k9s_Linux_amd64.tar.gz
# Extracttar -xzf k9s_Linux_amd64.tar.gz
# Move to PATHsudo mv k9s /usr/local/bin/
# Verify installationk9s version
# Using package managers# Arch Linuxyay -S k9s
# Ubuntu/Debian (via snap)sudo snap install k9s
# Using gogo install github.com/derailed/k9s@latestWindows
# Using Scoopscoop install k9s
# Using Chocolateychoco install k9s
# Manual installation# Download from GitHub releases# Extract and add to PATHDocker
# Run K9s in Dockerdocker run --rm -it \ -v ~/.kube/config:/root/.kube/config \ derailed/k9sGetting Started
First Launch
# Launch K9sk9s
# Launch with specific contextk9s --context production-cluster
# Launch with specific namespacek9s -n production
# Launch in read-only modek9s --readonly
# Launch with specific kubeconfigk9s --kubeconfig ~/.kube/custom-configBasic Navigation
Navigation Keys:- :pods → View pods- :deployments → View deployments- :services → View services- :namespaces → View namespaces- :nodes → View nodes- Ctrl-a → Show all available resources- / → Filter resources- Esc → Clear filter/go back- Ctrl-d → Delete resource- Enter → View resource details- l → View logs- s → Shell into container- Ctrl-c → Exit K9s
Resource Navigation:- j/k or ↓/↑ → Move down/up- g → Go to top- Shift-g → Go to bottom- Ctrl-f → Page down- Ctrl-b → Page up- Space → Mark resource- Ctrl-space → Mark all resourcesEssential Commands
Viewing Resources
# In K9s command mode (press :):pods # List pods:po # Short form:deploy # Deployments:svc # Services:ing # Ingresses:cm # ConfigMaps:secret # Secrets:pvc # PersistentVolumeClaims:nodes # Nodes:ns # Namespaces:events # Events:jobs # Jobs:cronjobs # CronJobs:hpa # Horizontal Pod Autoscalers:psp # Pod Security Policies
# View all resourcesCtrl-a
# View custom resources:certificates # cert-manager:issuers # cert-manager:virtualservices # IstioWorking with Pods
# In pod viewEnter # Describe podl # View logsCtrl-l # Toggle log auto-scrollp # Previous logs (from restarted containers)s # Shell into containera # Attach to containerf # Port-forwardCtrl-k # Kill pod (delete)y # View YAMLe # Edit pod (not common, usually edit deployment)Shift-f # Toggle show/hide failed pods
# Multi-container podsl → Tab # Switch between container logss → Select # Choose container for shellWorking with Logs
# Log viewingl # View logsCtrl-l # Toggle auto-scrollw # Toggle log wrapt # Toggle timestamp0-9 # Container selection (multi-container pods)f # Toggle fullscreenc # Clear logs/ # Search in logs (press n for next, N for previous)s # Save logs to file
# Advanced log optionsShift-l # View logs from previous container instanceCtrl-r # Toggle raw logs (no formatting)Filtering and Searching
# Filter current view/pattern # Filter by patternEsc # Clear filter
# Label filters/app=nginx # Filter by label/!app=nginx # Inverse filter
# Status filters/Running # Show only running pods/Pending # Show pending pods/Error # Show pods with errors
# Regex filters/^prod-.* # Pods starting with "prod-"/.*-db$ # Pods ending with "-db"
# Multiple filters/label1=value1,label2=value2Advanced Features
Context and Namespace Management
# Switch context:ctx # List contextsEnter # Switch to selected context
# Switch namespace:ns # List namespacesEnter # Switch to namespace0 # Switch to all namespaces
# Quick namespace switch:ns/production # Jump directly to namespaceResource Operations
# Describe resourced # Describe selected resourceEnter # Alternative to describe
# Edit resourcee # Edit with default editorv # Edit with vim explicitly
# Delete resourceCtrl-d # Delete selected resourceCtrl-k # Alternative delete
# Scale deployment:deploy → Select → s → Enter new count
# Restart deployment:deploy → Select → Ctrl-r
# Cordon/Drain nodes:nodes → Select → Ctrl-c # Cordon:nodes → Select → Ctrl-o # Uncordon:nodes → Select → Ctrl-d # DrainPort Forwarding
# From pod viewf # Port forward# Enter: local_port:container_port# Example: 8080:80
# List active port forwards:pf
# Stop port forward:pf → Select → Ctrl-d
# Port forward to service:svc → Select → fShell Access
# Shell into pods # Shell access# For multi-container pods, select container
# Common shell scenarios:deploy → Select → s → Select pod → Select container
# Execute commandCtrl-s # Run command in container
# Attach to containera # Attach (for debugging)Configuration
Config File Location
# K9s config location~/.config/k9s/config.yml # Linux/macOS%APPDATA%\k9s\config.yml # Windows
# View current configcat ~/.config/k9s/config.ymlCustom Configuration
k9s: # Refresh rate (milliseconds) refreshRate: 2000
# Max log buffer lines maxConnRetry: 5
# Enable mouse support enableMouse: false
# Headless mode headless: false
# Logo logoless: false
# Crumbsless crumbsless: false
# Read-only mode readOnly: false
# No exit on error noExitOnError: false
# UI settings ui: enableMouse: false headless: false logoless: false crumbsless: false noIcons: false
# Skip latest version check skipLatestRevCheck: false
# Disable pod counts disablePodCounting: false
# Shell pod settings shellPod: image: busybox:1.35.0 command: [] args: [] namespace: default limits: cpu: 100m memory: 100Mi
# Image scan settings imageScans: enable: true exclusions: namespaces: [] labels: {}
# Logger settings logger: tail: 100 buffer: 5000 sinceSeconds: -1 fullScreen: false textWrap: false showTime: false
# Thresholds thresholds: cpu: critical: 90 warn: 70 memory: critical: 90 warn: 70Skin/Theme Configuration
k9s: # General body: fgColor: dodgerblue bgColor: '#1e1e1e' logoColor: blue
# Frames frame: border: fgColor: dodgerblue focusColor: lightskyblue menu: fgColor: white keyColor: pink numKeyColor: fuchsia crumbs: fgColor: white bgColor: steelblue activeColor: skyblue status: newColor: lightskyblue modifyColor: greenyellow addColor: lightskyblue errorColor: red highlightColor: orange killColor: mediumpurple completedColor: gray title: fgColor: white bgColor: steelblue highlightColor: orange counterColor: slateblue filterColor: slategray
# Views views: table: fgColor: lightskyblue bgColor: default cursorColor: steelblue markColor: darkgoldenrod xray: fgColor: lightskyblue bgColor: default cursorColor: steelblue cursorTextColor: black graphicColor: darkgoldenrod yaml: keyColor: steelblue colonColor: white valueColor: lightskyblue logs: fgColor: lightskyblue bgColor: defaultAliases
alias: # Resource aliases dp: v1/deployments sec: v1/secrets ing: extensions/v1beta1/ingresses svc: v1/services
# Custom shortcuts pp: v1/pods pvc: v1/persistentvolumeclaims pv: v1/persistentvolumes
# Helm hr: helm.toolkit.fluxcd.io/v2beta1/helmreleases
# Cert-manager cert: cert-manager.io/v1/certificates issuer: cert-manager.io/v1/issuers
# Istio vs: networking.istio.io/v1beta1/virtualservices dr: networking.istio.io/v1beta1/destinationrules gw: networking.istio.io/v1beta1/gatewaysPlugins
Plugin Configuration
plugin: # Debug with ephemeral container debug: shortCut: Shift-D description: Debug scopes: - pods command: kubectl background: false args: - debug - -it - -n - $NAMESPACE - $NAME - --image=nicolaka/netshoot - --target=$NAME - -- bash
# Dive into container image dive: shortCut: d description: Dive image scopes: - containers command: dive background: false args: - $COL-IMAGE
# Stern for logs stern: shortCut: Ctrl-L description: Stern logs scopes: - pods command: stern background: false args: - --tail - 50 - -n - $NAMESPACE - $NAME
# Get pod logs since time logs-since: shortCut: Shift-L description: Logs 1h scopes: - pods command: kubectl background: false args: - logs - -n - $NAMESPACE - $NAME - --since=1h
# Top pod top: shortCut: Shift-T description: Top pod scopes: - pods command: kubectl background: false args: - top - pod - -n - $NAMESPACE - $NAME
# Restart deployment restart: shortCut: Shift-R description: Restart scopes: - deployments command: kubectl background: false confirm: true args: - rollout - restart - deployment - -n - $NAMESPACE - $NAME
# Describe node node-describe: shortCut: Shift-D description: Describe scopes: - nodes command: kubectl background: false args: - describe - node - $NAME
# Flux reconcile flux-reconcile: shortCut: Shift-R description: Flux reconcile scopes: - helmreleases command: flux background: false args: - reconcile - helmrelease - -n - $NAMESPACE - $NAMEHotkeys and Shortcuts
Global Shortcuts
? or Ctrl-h → Show helpCtrl-a → Show all resourcesCtrl-c → Exit K9s: → Command mode/ → Filter modeEsc → Back/ClearCtrl-r → RefreshCtrl-d → Delete resourceCtrl-k → Kill podu → Show UID columnView-Specific Shortcuts
Pods:l → Logsp → Previous logss → Shella → Attachf → Port forwardShift-f → Show/hide failed podsCtrl-k → Kill pody → View YAML
Deployments:s → ScaleCtrl-r → Restart rolloutr → Rollout status
Nodes:Ctrl-c → CordonCtrl-o → UncordonCtrl-d → Drainy → View YAML
Logs:w → Toggle wrapt → Toggle timestampf → Toggle fullscreenc → Clear logss → Save logs0-9 → Container selectionProductivity Tips
Quick Resource Access
# Use command mode for fast access:po # Pods:po -n production # Pods in namespace:deploy/nginx # Specific deployment:svc/api # Specific service
# Use context/namespace combo:ctx/prod → :ns/api → :poMonitoring Multiple Resources
# Open multiple K9s instances# Terminal 1: Monitor podsk9s -n production
# Terminal 2: Monitor nodesk9s:nodes
# Terminal 3: Monitor eventsk9s:events
# Use tmux/screen for split viewtmuxCtrl-b % # Split verticalk9s # First paneCtrl-b o # Switch panek9s -n production # Second paneCommon Workflows
# Debug failing pod:po → /status=Error → Enter → l → s
# Scale deployment:deploy → /app=api → s → Enter new count
# Check resource usage:nodes → Shift-t:po → Select → Shift-t
# Port forward to service:svc → /app=database → f → 5432:5432
# View all resources in namespace:ns/production → Ctrl-a
# Quick log search:po → l → /ERROR → n (next) → N (previous)Troubleshooting
Common Issues
# K9s won't startk9s --version # Check versionk9s info # Show diagnosticsrm -rf ~/.config/k9s/ # Reset configrm -rf ~/.k9s/ # Remove cache
# Performance issues# Edit config to increase refresh raterefreshRate: 5000 # 5 seconds instead of 2
# Disable pod countingdisablePodCounting: true
# Connection issueskubectl cluster-info # Verify cluster accessk9s --context different-context # Try different context
# RBAC issues# Check permissionskubectl auth can-i list pods --all-namespaces
# Use read-only mode if neededk9s --readonlyDebug Mode
# Enable debug loggingk9s --write --logLevel debug
# View logstail -f /tmp/k9s-*.logProduction Best Practices
Security
# Use read-only mode in productionk9s --readonly
# Limit access with RBAC# Create ServiceAccount with limited permissionskubectl create sa k9s-viewerkubectl create clusterrolebinding k9s-viewer \ --clusterrole=view \ --serviceaccount=default:k9s-viewer
# Use that context with K9sk9s --context k9s-viewer-contextConfiguration Management
# Version control K9s configcd ~/.config/k9sgit initgit add config.yml skin.yml alias.yml plugin.ymlgit commit -m "K9s configuration"
# Share config across teamgit remote add origin git@github.com:company/k9s-config.gitgit push -u origin mainTeam Standards
# Shared team configk9s: refreshRate: 2000 readOnly: false # Set to true for prod
# Consistent shell pod shellPod: image: company/debug-tools:latest namespace: default
# Standard thresholds thresholds: cpu: critical: 90 warn: 70 memory: critical: 90 warn: 70Comparison with kubectl
# kubectl commands → K9s equivalents
# List podskubectl get pods → :pokubectl get pods -n prod → :ns/prod → :pokubectl get pods -w → :po (auto-refresh)
# Describekubectl describe pod nginx → :po → /nginx → Enter
# Logskubectl logs nginx → :po → /nginx → lkubectl logs -f nginx → :po → /nginx → l (auto-tail)
# Deletekubectl delete pod nginx → :po → /nginx → Ctrl-d
# Shellkubectl exec -it nginx -- sh → :po → /nginx → s
# Port forwardkubectl port-forward svc/api → :svc → /api → f
# Editkubectl edit deploy nginx → :deploy → /nginx → e
# Scalekubectl scale deploy nginx --replicas=3 → :deploy → /nginx → sConclusion
K9s transforms Kubernetes cluster management with its efficient, keyboard-driven interface. By mastering K9s shortcuts, plugins, and configuration options, you can dramatically improve your productivity when working with Kubernetes clusters.
The tool’s real-time monitoring, intuitive navigation, and extensibility make it an essential tool for anyone managing Kubernetes clusters, from development to production environments.
Master Kubernetes tools and best practices with our comprehensive Kubernetes training programs. Contact us for customized training designed for your team’s needs.