Module 8.1: k9s & CLI Tools
Toolkit Track | Complexity:
[QUICK]| Time: 30-35 minutes
Overview
Section titled “Overview”kubectl is powerful but verbose. When you’re debugging a production issue at 2 AM, you don’t want to type kubectl get pods -n production -o wide --watch. k9s provides a terminal UI that makes Kubernetes interaction fast and visual. This module covers k9s and other CLI productivity tools.
What You’ll Learn:
- k9s navigation and commands
- kubectl plugins with krew
- Productivity tools (stern, kubectx, kubens)
- Shell integration and aliases
Prerequisites:
- Basic kubectl familiarity
- Terminal/shell basics
- Kubernetes resource concepts
What You’ll Be Able to Do
Section titled “What You’ll Be Able to Do”After completing this module, you will be able to:
- Configure K9s with custom aliases, plugins, and skins for efficient Kubernetes cluster management
- Implement K9s workflows for rapid pod debugging, log tailing, and resource editing in production
- Deploy K9s plugins for extended functionality including benchmark testing and resource cleanup
- Optimize daily Kubernetes operations using K9s keyboard shortcuts and filtering commands
Why This Module Matters
Section titled “Why This Module Matters”Developers spend hours in kubectl. Every second saved compounds. k9s turns 30-second operations into 1-second operations. Over a year, that’s weeks of productivity recovered. More importantly, visual feedback means faster debugging and fewer mistakes.
💡 Did You Know? k9s was created by Fernand Galiana and has become one of the most popular Kubernetes tools with over 20,000 GitHub stars. The name is a play on “canines” (K-9s)—it’s your loyal companion for Kubernetes. The project started because Fernand was tired of typing the same kubectl commands repeatedly.
k9s: Terminal UI for Kubernetes
Section titled “k9s: Terminal UI for Kubernetes”Installation
Section titled “Installation”# macOSbrew install k9s
# Linuxcurl -sS https://webinstall.dev/k9s | bash
# Windows (scoop)scoop install k9s
# Verifyk9s versionStarting k9s
Section titled “Starting k9s”# Default contextk9s
# Specific contextk9s --context production
# Specific namespacek9s -n kube-system
# Read-only mode (safe for production)k9s --readonly
# All namespacesk9s -Ak9s Interface
Section titled “k9s Interface”k9s INTERFACE════════════════════════════════════════════════════════════════════
┌─ K9s - production-cluster ──────────────────────────────────────┐│ Context: prod │ Cluster: eks-prod │ User: admin │ K9s: 0.28.0 │├─────────────────────────────────────────────────────────────────┤│ <pods> all [0] Filter: <f> │├─────────────────────────────────────────────────────────────────┤│ NAMESPACE NAME READY STATUS RESTARTS ││ production api-7f9b4c8d9-abc12 1/1 Running 0 ││ production web-5d4c7b8f-def34 1/1 Running 0 ││ production worker-6e5d8c9f-ghi56 1/1 Running 0 ││ staging api-8a0c5d9e-jkl78 1/1 Running 2 ││ staging web-9b1d6e0f-mno90 0/1 Error 5 │├─────────────────────────────────────────────────────────────────┤│ <0> all <1> default <2> kube-system <3> production <4> staging │├─────────────────────────────────────────────────────────────────┤│ <:> Command <ctrl-a> Aliases <ctrl-d> Delete <l> Logs <s> Shell │└─────────────────────────────────────────────────────────────────┘Essential Commands
Section titled “Essential Commands”| Key | Action |
|---|---|
: | Command mode (type resource name) |
/ | Filter current view |
? | Help / keyboard shortcuts |
Esc | Back / clear filter |
Ctrl+A | Show all aliases |
Enter | View resource details |
d | Describe resource |
y | YAML view |
l | View logs |
s | Shell into container |
Ctrl+K | Kill/delete resource |
e | Edit resource |
p | Port-forward |
Navigation Aliases
Section titled “Navigation Aliases”# Quick resource access with ':':pods # or :po:deploy # or :dp:svc # Services:no # Nodes:ns # Namespaces:cm # ConfigMaps:sec # Secrets:pvc # PersistentVolumeClaims:ing # Ingress:events # or :evPro Tips
Section titled “Pro Tips”K9S PRO TIPS════════════════════════════════════════════════════════════════════
1. FUZZY FILTERING /api → Shows pods containing "api" /!api → Shows pods NOT containing "api" /-Error → Filter by status
2. COLUMN SORTING Shift+C → Sort by CPU Shift+M → Sort by Memory Shift+S → Sort by Status
3. CONTEXT SWITCHING :ctx → List and switch contexts
4. NAMESPACE SWITCHING :ns → List namespaces 0-9 keys → Quick namespace switch (shown at bottom)
5. PORT FORWARDING p on pod → Interactive port-forward setup
6. MULTI-CONTAINER PODS l on pod → Choose container for logs💡 Did You Know? k9s can show resource usage (CPU/memory) directly in the pod list if metrics-server is installed. Press
Shift+Cto sort by CPU and instantly find the pod eating all your resources. No morekubectl top pods | sort -k3 -r | head.
kubectl Plugins with Krew
Section titled “kubectl Plugins with Krew”Installing Krew
Section titled “Installing Krew”# macOS/Linux( set -x; cd "$(mktemp -d)" && OS="$(uname | tr '[:upper:]' '[:lower:]')" && ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" && KREW="krew-${OS}_${ARCH}" && curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" && tar zxvf "${KREW}.tar.gz" && ./"${KREW}" install krew)
# Add to PATHexport PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
# Verifykubectl krew versionEssential Plugins
Section titled “Essential Plugins”# Install pluginskubectl krew install ctx # Context switchingkubectl krew install ns # Namespace switchingkubectl krew install neat # Clean YAML outputkubectl krew install tree # Resource hierarchykubectl krew install images # Show container imageskubectl krew install access-matrix # RBAC visualization
# Search available pluginskubectl krew search
# Update pluginskubectl krew upgradePlugin Usage
Section titled “Plugin Usage”# kubectx - Context switchingkubectl ctx # List contextskubectl ctx production # Switch to productionkubectl ctx - # Switch to previous context
# kubens - Namespace switchingkubectl ns # List namespaceskubectl ns production # Switch to productionkubectl ns - # Switch to previous namespace
# kubectl-neat - Clean YAML outputkubectl get pod nginx -o yaml | kubectl neat
# kubectl-tree - Resource hierarchykubectl tree deployment nginx# Shows: Deployment → ReplicaSet → Pod
# kubectl-images - Show imageskubectl images -A # All images in clusterStern: Multi-Pod Log Tailing
Section titled “Stern: Multi-Pod Log Tailing”Installation
Section titled “Installation”# macOSbrew install stern
# Linuxcurl -LO https://github.com/stern/stern/releases/latest/download/stern_linux_amd64.tar.gztar xzf stern_linux_amd64.tar.gzsudo mv stern /usr/local/bin/# Tail logs from all pods matching regexstern "api-.*"
# Specific namespacestern api -n production
# All namespacesstern api --all-namespaces
# Specific containerstern api --container nginx
# Since durationstern api --since 1h
# Color by podstern api --output raw
# With timestampsstern api --timestamps
# Exclude patternsstern ".*" --exclude-container istio-proxySTERN VS KUBECTL LOGS════════════════════════════════════════════════════════════════════
kubectl logs:• One pod at a time• Must know exact pod name• No color coding• Awkward multi-container
stern:• Multiple pods simultaneously• Regex matching• Color-coded by pod• Follow across deployments• Auto-reconnectsShell Integration
Section titled “Shell Integration”Aliases
Section titled “Aliases”# Add to ~/.bashrc or ~/.zshrc
# Basic kubectl aliasesalias k='kubectl'alias kg='kubectl get'alias kd='kubectl describe'alias kl='kubectl logs'alias kx='kubectl exec -it'
# Resource shortcutsalias kgp='kubectl get pods'alias kgs='kubectl get svc'alias kgd='kubectl get deploy'alias kgn='kubectl get nodes'
# Watch modealias kgpw='kubectl get pods -w'
# All namespacesalias kgpa='kubectl get pods -A'
# Context/namespacealias kctx='kubectl ctx'alias kns='kubectl ns'
# Logsalias klf='kubectl logs -f'alias kl1h='kubectl logs --since=1h'
# Quick deletealias kdel='kubectl delete'alias krm='kubectl delete pod --force --grace-period=0'
# Apply/createalias ka='kubectl apply -f'alias kc='kubectl create'
# Port forwardalias kpf='kubectl port-forward'Shell Completion
Section titled “Shell Completion”# Bashsource <(kubectl completion bash)
# Zshsource <(kubectl completion zsh)
# Fishkubectl completion fish | source
# Also for k9ssource <(k9s completion bash)Prompt Integration
Section titled “Prompt Integration”# Show current context/namespace in prompt# Using kube-ps1 (https://github.com/jonmosco/kube-ps1)source /path/to/kube-ps1.shPS1='$(kube_ps1)'$PS1
# Result:# (⎈|prod-cluster:production) user@host:~$💡 Did You Know? Kubernetes developers use aliases so heavily that many can’t remember the full commands anymore. The official kubectl cheat sheet recommends aliases, and some teams enforce standard aliases so everyone speaks the same “language” when pair debugging.
💡 Did You Know? krew started as a side project and now hosts over 200 kubectl plugins. The
kubectl-neatplugin alone has saved countless hours—it strips the clutter (managedFields, status, defaults) from YAML output, giving you clean manifests you can actually use. Many SREs considerkrew install neattheir first command on any new machine.
Other Productivity Tools
Section titled “Other Productivity Tools”fzf Integration
Section titled “fzf Integration”# Fuzzy pod selectionkfp() { kubectl get pods --all-namespaces | fzf --header-lines=1 | awk '{print "-n", $1, $2}'}
# Fuzzy context switchingkctxf() { kubectl ctx $(kubectl ctx | fzf)}
# Fuzzy namespace switchingknsf() { kubectl ns $(kubectl ns | fzf)}kubectl-who-can
Section titled “kubectl-who-can”kubectl krew install who-can
# Who can delete pods?kubectl who-can delete pods
# Who can exec into pods in production?kubectl who-can create pods/exec -n productionkubecolor
Section titled “kubecolor”# Colorized kubectl outputbrew install kubecolor
# Use instead of kubectlkubecolor get pods
# Alias italias kubectl='kubecolor'Common Mistakes
Section titled “Common Mistakes”| Mistake | Problem | Solution |
|---|---|---|
| No context indicator | Run commands on wrong cluster | Use kube-ps1 in prompt |
| Forgetting namespace | Commands fail or hit wrong namespace | Use kubens, check with kubectl config view |
| Verbose commands | Slow, error-prone typing | Use aliases and k9s |
kubectl logs on many pods | See only one pod | Use stern for multi-pod logs |
| No shell completion | Typing full resource names | Enable bash/zsh completion |
kubectl delete pod without check | Wrong pod deleted | Use k9s confirm dialogs or aliases with -i |
War Story: The Wrong Cluster Delete
Section titled “War Story: The Wrong Cluster Delete”An engineer typed kubectl delete deployment api intending to hit staging. They were still in production context from a previous debugging session.
What went wrong:
- No visual indicator of current context
- Muscle memory from staging work
- Production context from earlier session
The fix:
# kube-ps1 in prompt shows contextPS1='$(kube_ps1)'$PS1# (⎈|production:default) $# ^^^^^^^^^^^^^^^^^^^^^^^# Now you ALWAYS know where you are
# Separate terminal colors per environment# Production = red terminal background# Staging = greenBest practice: Different terminal profiles for different environments. Visual cues save careers.
Question 1
Section titled “Question 1”How do you filter pods in k9s to only show those with “api” in the name?
Show Answer
Type /api in the pods view.
k9s uses fuzzy filtering:
/api- shows pods containing “api”/!api- shows pods NOT containing “api”/-Error- filter by status column
Press Esc to clear the filter.
Question 2
Section titled “Question 2”What’s the difference between stern and kubectl logs -f?
Show Answer
kubectl logs -f:
- Single pod only
- Need exact pod name
- Disconnects if pod restarts
- Single container at a time
stern:
- Multiple pods via regex
- Color-coded by pod name
- Follows across pod restarts
- All containers by default
stern api-.*tails all api pods
stern is essential for microservices debugging where one “service” is multiple pods.
Question 3
Section titled “Question 3”Why use kube-ps1 in your shell prompt?
Show Answer
kube-ps1 shows current context and namespace in your prompt:
(⎈|production:payments) user@host:~$Benefits:
- Always know which cluster you’re targeting
- Prevent accidents - see “production” before pressing Enter
- No extra commands to check context
- Team visibility - others can see in screenshots/recordings
Prevents the “I deleted production” accidents that haunt engineers’ dreams.
Hands-On Exercise
Section titled “Hands-On Exercise”Objective
Section titled “Objective”Install and configure k9s and CLI productivity tools.
Environment Setup
Section titled “Environment Setup”# Install toolsbrew install k9s stern kubectx
# Or on Linuxcurl -sS https://webinstall.dev/k9s | bash# Install stern and kubectx similarly-
Start k9s:
Terminal window k9s -
Navigate resources:
- Type
:podsto view pods - Press
/and filter by name - Press
lon a pod to view logs - Press
dto describe - Press
Escto go back
- Type
-
Try namespace switching:
- Type
:nsto view namespaces - Press
Enterto switch - Or use number keys shown at bottom
- Type
-
Set up aliases:
Terminal window # Add to ~/.bashrc or ~/.zshrcalias k='kubectl'alias kgp='kubectl get pods'alias kctx='kubectl ctx'alias kns='kubectl ns'# Reload shellsource ~/.bashrc -
Test stern (if you have multiple pods):
Terminal window # Tail all pods in default namespacestern ".*" -n default -
Enable shell completion:
Terminal window # Bashecho 'source <(kubectl completion bash)' >> ~/.bashrc# Zshecho 'source <(kubectl completion zsh)' >> ~/.zshrc
Success Criteria
Section titled “Success Criteria”- k9s launches and shows cluster resources
- Can navigate between resource types
- Can filter and search
- Aliases work (e.g.,
kgpshows pods) - Tab completion works for kubectl
Bonus Challenge
Section titled “Bonus Challenge”Set up kube-ps1 to show context/namespace in your prompt, with different colors for production vs staging.
Further Reading
Section titled “Further Reading”Next Module
Section titled “Next Module”Continue to Module 8.2: Telepresence & Tilt to learn about local development with remote Kubernetes clusters.
“A 10x engineer isn’t 10x smarter—they’re 10x more efficient. Tools like k9s make that possible.”