Skip to content
Go back

Krew: Kubectl Plugins You'll Actually Use

By SumGuy 10 min read
Krew: Kubectl Plugins You'll Actually Use
Contents

kubectl Is Fine. kubectl + Krew Is Actually Good.

Out of the box, kubectl is a solid CLI. It can do almost anything. The problem is that “almost anything” often means a wall of --output jsonpath='{.items[*].spec.containers[*].image}' that makes your eyes cross at 11 PM when you’re trying to figure out why a deployment is stuck.

Krew fixes this. It’s the official plugin manager for kubectl, maintained by the kubernetes-sigs org, not some random GitHub repo. You install plugins, they show up as kubectl <plugin-name>, and suddenly you feel like a person again.

Here’s what Krew is, how to install it, and which plugins you’ll actually reach for on a k3s home lab.


Installing Krew

No root required. Krew installs per-user into ~/.krew/bin. The install script is a one-liner:

Terminal window
(
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
)

Then add Krew’s bin dir to your PATH. Drop this into your ~/.bashrc or ~/.zshrc:

Terminal window
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

Source the file or open a new shell, then verify:

Terminal window
kubectl krew version
# GitTag v0.5.0
# GitCommit ...
# IndexURI https://index.krew.sigs.k8s.io

From here, the workflow is simple:

Terminal window
kubectl krew update # fetch latest plugin index
kubectl krew search # browse available plugins
kubectl krew install <name> # install a plugin
kubectl krew list # what's installed
kubectl krew upgrade # update all installed plugins

That’s it. No Helm charts, no cluster permissions, no crying.


The Plugins Worth Installing

Not everything in the Krew index is gold. Some plugins are abandoned, some overlap with built-in functionality that got added in newer kubectl versions (kubectl debug replaced kubectl-debug, for instance, skip that one). The list below is what’s actually useful on a home lab cluster.

kubectl-neat, Clean Up That YAML

You run kubectl get deployment myapp -o yaml and get 200 lines of noise: managedFields, creationTimestamp, resourceVersion, uid, status junk. You just wanted the spec.

kubectl-neat strips all the generated/server-side fields and gives you clean, copyable YAML.

Terminal window
kubectl krew install neat
Terminal window
# Before: 200 lines of noise
kubectl get deployment myapp -o yaml
# After: just what you wrote
kubectl neat get deployment myapp -o yaml

Sample output, clean enough to paste directly into a new manifest or a PR:

apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- image: myapp:1.3.0
name: myapp
ports:
- containerPort: 8080

Honestly, this should be built into kubectl. It isn’t. Install it anyway.


kubectl-tree, See Who Owns What

Kubernetes ownership is a DAG of mystery. A deployment makes a ReplicaSet, which makes Pods, which have PVCs. When something breaks, tracing that chain with kubectl get and kubectl describe is tedious.

kubectl-tree renders the owner-reference chain as an actual tree:

Terminal window
kubectl krew install tree
Terminal window
kubectl tree deployment myapp
NAMESPACE NAME READY REASON AGE
default Deployment/myapp - 3d
default └─ReplicaSet/myapp-7d6b9f8c9 - 3d
default ├─Pod/myapp-7d6b9f8c9-4xk2p True 3d
default └─Pod/myapp-7d6b9f8c9-9vwrq True 3d

Use it to quickly check whether a CronJob’s Jobs are cleaning up, whether a StatefulSet’s PVCs are hanging around after scale-down, or why there are three ReplicaSets for one Deployment (rolling update in progress, probably).


kubectx + kubens, Context and Namespace Switching

If you’re only running one cluster, skip these. If you’re juggling a k3s home lab, a managed cloud cluster, and maybe a dev cluster, you need these.

Terminal window
kubectl krew install ctx
kubectl krew install ns
Terminal window
# List and switch contexts
kubectl ctx
# minikube
# homelab
# * prod-gke
kubectl ctx homelab
# Switched to context "homelab".
# List and switch namespaces
kubectl ns
# default
# kube-system
# monitoring
# * ingress-nginx
kubectl ns monitoring
# Context "homelab" set to namespace "monitoring".

These are the same tools as the standalone kubectx/kubens binaries, if you already have those in PATH, you don’t need the Krew versions. But if you want everything under the kubectl umbrella, the Krew install is cleaner.


stern, Multi-Pod Log Tailing

kubectl logs -f pod/myapp-xyz follows one pod. kubectl logs -f -l app=myapp works but mangles the output when multiple pods write simultaneously. stern does this right: color-codes each pod, prefixes lines with the pod name, and lets you filter by regex.

Terminal window
kubectl krew install stern
Terminal window
# Tail all pods matching "myapp" in current namespace
kubectl stern myapp
# Tail across all namespaces, filter to lines containing "error"
kubectl stern --all-namespaces myapp --include error
# Tail by label
kubectl stern -l app=myapp

Sample output (color in the terminal, monotone here):

myapp-7d6b9f8c9-4xk2p myapp 2026-07-25T03:14:12Z INFO request handled in 42ms
myapp-7d6b9f8c9-9vwrq myapp 2026-07-25T03:14:12Z INFO request handled in 38ms
myapp-7d6b9f8c9-4xk2p myapp 2026-07-25T03:14:13Z ERROR failed to connect to db

Your 2 AM self will appreciate not having to remember which pod name has the logs you actually need.


kubectl-images, What’s Running in Your Cluster

You want to audit image versions, find containers still on latest, or just figure out what’s deployed. kubectl-images gives you a deduplicated list.

Terminal window
kubectl krew install images
Terminal window
kubectl images -n monitoring
[Summary]: 1 namespaces, 6 pods, 9 containers
CONTAINER IMAGE
prometheus prom/prometheus:v2.53.0
alertmanager prom/alertmanager:v0.27.0
grafana grafana/grafana:11.1.0
node-exporter prom/node-exporter:v1.8.1
kube-state-metrics registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0

Useful for periodic image hygiene checks. Pipe it through grep latest to find the offenders.


kubectl-resource_capacity, Node Utilization at a Glance

kubectl top nodes gives you raw metrics. It doesn’t tell you what percentage of allocatable CPU/memory you’re using, or how much headroom you have before the scheduler starts having a bad time.

Terminal window
kubectl krew install resource-capacity
Terminal window
kubectl resource-capacity --sort cpu.util
NODE CPU REQUESTS CPU LIMITS CPU UTIL MEMORY REQUESTS MEMORY LIMITS MEMORY UTIL
homelab-01 1250m (31%) 2500m (62%) 420m (10%) 3.2Gi (41%) 6.4Gi (83%) 2.1Gi (27%)
homelab-02 800m (20%) 1600m (40%) 310m (7%) 2.1Gi (27%) 4.2Gi (54%) 1.4Gi (18%)

Add --pods to break it down by pod. Add --util to show actual utilization alongside requests/limits. This is the dashboard you run before adding more workloads to a node.


kubectl-view-secret, Decode Secrets Like a Human

Reading a Kubernetes Secret without plugins is an exercise in masochism:

Terminal window
kubectl get secret myapp-db -o jsonpath='{.data.password}' | base64 -d

kubectl-view-secret skips the ceremony:

Terminal window
kubectl krew install view-secret
Terminal window
# List all keys in a secret
kubectl view-secret myapp-db
# Decode a specific key
kubectl view-secret myapp-db password
# hunter2
# Decode all keys
kubectl view-secret myapp-db -a
# DB_HOST=postgres.default.svc.cluster.local
# DB_NAME=myapp
# DB_PASSWORD=hunter2
# DB_USER=myapp

Note: this decodes base64, not actual encryption. If you’re using Sealed Secrets or SOPS, this shows the decrypted-at-rest values that live in etcd. Treat the output accordingly.


kubectl-deprecations, Find API Breaks Before They Break You

You’re upgrading k3s from 1.29 to 1.31 and you’re wondering if any of your manifests use APIs that got removed. kubectl-deprecations scans your cluster and tells you.

Terminal window
kubectl krew install deprecations
Terminal window
kubectl deprecations
COMPONENT NAMESPACE KIND VERSION REPLACEMENT REMOVED DEPRECATED
cert-manager/webhook cert-manager ModuleSpec policy/v1beta1 policy/v1 1.25 1.21
ingress-nginx/controller ingress-nginx Ingress networking.k1 networking.k1 - 1.22

Run this before every minor version upgrade. It’s a lot less painful than discovering a removed API mid-upgrade because your Helm chart is two versions old.


kubectl-node-shell, Drop Into a Node

Sometimes you need to poke around on the node itself, check disk usage, look at host network state, inspect containerd’s storage. kubectl-node-shell creates a privileged debug pod on the target node and drops you into a shell with host PID, network, and IPC namespaces.

Terminal window
kubectl krew install node-shell
Terminal window
kubectl node-shell homelab-01
spawning "nsenter-xk4bq" on "homelab-01"
If you don't see a command prompt, try pressing enter.
root@homelab-01:/#

You’re now in the host namespace. ps aux shows all host processes. df -h shows host disk. crictl images shows containerd’s image cache. Exit like a normal shell, the pod cleans up automatically.

Use this sparingly and purposefully. You’re root on the host.


kubectl-iexec, Interactive Container Picker for exec

kubectl exec requires you to know the full pod name. When pods have random suffixes and you just want to exec into the app container, kubectl-iexec gives you a fuzzy picker:

Terminal window
kubectl krew install iexec
Terminal window
kubectl iexec myapp

It presents an interactive list of matching pods and containers, you pick one, and you’re dropped into an exec session. Saves typing, saves copy-pasting pod names from a separate terminal tab.


kubectl-explore, Fuzzy-Find on kubectl explain

kubectl explain is great if you remember the exact resource name and field path. kubectl-explore adds fuzzy search across the full API schema:

Terminal window
kubectl krew install explore
Terminal window
kubectl explore pod
# Interactive fuzzy finder across pod spec fields
# Type to filter: tolerations
# → pod.spec.tolerations
# → pod.spec.tolerations[].effect
# → pod.spec.tolerations[].key

Good for those “what’s the field called again?” moments when writing manifests from scratch.


Writing Your Own Plugin (It’s Easier Than You Think)

Anything named kubectl-<something> that’s executable and in your PATH is automatically a kubectl plugin. No registration, no Krew required.

Here’s a 10-line bash wrapper that shows a quick cluster health summary, call it kubectl-myhelper:

#!/usr/bin/env bash
# kubectl-myhelper — quick cluster health snapshot
# Usage: kubectl myhelper
set -euo pipefail
echo "=== Nodes ==="
kubectl get nodes -o wide
echo ""
echo "=== Unhealthy Pods ==="
kubectl get pods --all-namespaces --field-selector='status.phase!=Running,status.phase!=Succeeded' 2>/dev/null || echo "All pods healthy"
echo ""
echo "=== Recent Events (Warnings) ==="
kubectl get events --all-namespaces --field-selector=type=Warning --sort-by='.lastTimestamp' | tail -10

Drop it in ~/.local/bin/kubectl-myhelper, make it executable:

Terminal window
chmod +x ~/.local/bin/kubectl-myhelper
kubectl myhelper

That’s it. kubectl discovers it automatically. The kubectl- prefix is the only contract. You can write plugins in Python, Go, or anything else that produces an executable, bash is just the quickest to iterate on.


Keeping Things Updated

The Krew plugin index is separate from the plugins themselves. Update the index first, then upgrade your plugins:

Terminal window
kubectl krew update # refresh the index
kubectl krew upgrade # update all installed plugins

Do this before any cluster upgrade. Plugin maintainers often push updates when new Kubernetes versions drop, and running old plugin binaries against a new API server can produce cryptic errors.


The Bottom Line

Krew is low-overhead and high-payoff. It installs to ~/.krew, doesn’t touch your cluster, and the plugins are just binaries. The best ones, neat, tree, stern, view-secret, resource-capacity, node-shell, cover the exact gaps that make raw kubectl tedious for day-to-day cluster management.

Start with these six, add the others as you hit the use cases, and write a custom plugin the first time you find yourself running the same three-command sequence more than twice in a week.

Your future self, squinting at logs at 2 AM, will thank you.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Pangolin: Self-Hosted Cloudflare Tunnel Alternative
Next Post
Aider & Cline: Terminal AI Coding That Actually Ships

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts