Use kubectl Effectively
Master kubectl contexts, namespace switching, built-in API docs with explain, structured output, live debugging with ephemeral containers, and Kustomize overlays.
Before you start
- ▸kubectl installed and in PATH (1.25+ recommended for full debug features)
- ▸A reachable Kubernetes cluster with a valid kubeconfig at ~/.kube/config
- ▸Basic familiarity with Kubernetes objects: Pod, Deployment, Service
- ▸curl or a package manager available for optional tooling (kubectx, krew)
kubectl is the primary interface to any Kubernetes cluster. Most people learn a handful of commands and stop there, leaving a large part of the tool's power untouched. This guide covers the features that separate casual users from operators who can actually diagnose and manage clusters efficiently: context and namespace switching, in-terminal API documentation, output formats, live debugging, and Kustomize-based manifest management.
Contexts and Clusters
A context in kubectl ties together a cluster, a user, and a default namespace into a named entry in ~/.kube/config. When you work with multiple clusters — local dev, staging, production — mastering context switching prevents you from running destructive commands against the wrong environment.
List and Inspect Contexts
kubectl config get-contexts
Output includes columns for the active context (marked with *), cluster name, auth user, and default namespace. To see only the current context:
kubectl config current-context
Switch and Rename Contexts
# Switch to a named context
kubectl config use-context staging-cluster
# Rename a context to something memorable
kubectl config rename-context gke_project_us-east1_prod prod
Inline Context Override
You don't have to switch globally. Pass --context or point to an alternate kubeconfig file per command — useful in scripts:
kubectl --context=prod get nodes
KUBECONFIG=~/.kube/prod-config kubectl get pods -A
Install kubectx for Fast Switching
The kubectx and kubens tools wrap these operations into short commands and support fuzzy search when combined with fzf.
# Debian/Ubuntu
sudo apt install kubectx
# Fedora
sudo dnf install kubectx
# Arch
sudo pacman -S kubectx
Namespaces
Kubernetes namespaces partition cluster resources. Forgetting to specify the right one is one of the most common sources of confusion.
Set a Persistent Namespace for a Context
kubectl config set-context --current --namespace=my-app
Every subsequent command in this context now targets my-app without needing -n my-app.
Query Across All Namespaces
kubectl get pods -A
# -A is shorthand for --all-namespaces
# Filter by a label across all namespaces
kubectl get pods -A -l app=nginx
kubectl explain: Built-in API Reference
kubectl explain gives you field-level documentation for any Kubernetes resource without leaving the terminal. It reflects the actual API version served by your current cluster, making it more reliable than web docs when versions differ.
# Top-level fields for a Deployment
kubectl explain deployment
# Drill into a nested field
kubectl explain deployment.spec.strategy
# Show all fields recursively (pipe to less)
kubectl explain deployment --recursive | less
This is especially useful for Custom Resource Definitions (CRDs) installed by operators — the vendor's schema is exposed through the same command.
kubectl explain prometheusrule.spec
Output Formats and get -o yaml
The default table output is fine for a quick look. For automation, auditing, or understanding what a controller actually stored, you need structured output.
YAML and JSON
# Full resource definition as applied to the cluster
kubectl get deployment my-app -n my-app -o yaml
# Same in JSON
kubectl get deployment my-app -n my-app -o json
The YAML output includes server-side fields like resourceVersion, uid, and managedFields. Strip managed fields for cleaner reading:
kubectl get deployment my-app -o yaml \
| kubectl neat
# kubectl-neat is a plugin; install via: kubectl krew install neat
JSONPath for Targeted Extraction
# Get the image tag of the first container in a deployment
kubectl get deployment my-app \
-o jsonpath='{.spec.template.spec.containers[0].image}'
# List all pod names and their node assignments
kubectl get pods -A \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}'
Custom Columns
kubectl get pods -A \
-o custom-columns=\
'NAMESPACE:.metadata.namespace,NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName'
Debugging Workloads
kubectl ships with progressively more powerful debug capabilities. Know the right tool for each situation.
Logs and Events
# Follow logs from all containers in a pod
kubectl logs -f pod/my-app-abc123 --all-containers
# Logs from a previous (crashed) container instance
kubectl logs pod/my-app-abc123 -c app --previous
# Recent events sorted by time (often the first place to look)
kubectl get events -n my-app --sort-by='.lastTimestamp'
Exec Into a Running Container
kubectl exec -it pod/my-app-abc123 -n my-app -- /bin/sh
kubectl debug: Ephemeral Containers
When a pod runs a minimal image with no shell, use kubectl debug to inject an ephemeral debug container. This requires Kubernetes 1.23+ with ephemeral containers enabled (on by default in 1.25+).
# Attach a busybox sidecar to a running pod
kubectl debug -it pod/my-app-abc123 \
--image=busybox:latest \
--target=app \
-n my-app
The --target flag shares the process namespace of the named container, so you can inspect its filesystem and running processes from inside busybox.
# Clone a pod and override the entrypoint for crash-loop debugging
kubectl debug pod/my-app-abc123 \
-it --copy-to=my-app-debug \
--container=app \
-- /bin/sh
The cloned pod starts fresh; delete it when done with kubectl delete pod my-app-debug -n my-app.
Describe for Condition and Event Summary
kubectl describe pod my-app-abc123 -n my-app
The Conditions and Events sections at the bottom of describe output are usually where scheduling failures, image pull errors, and liveness probe failures appear first.
Kustomize
Kustomize is built into kubectl (no separate binary needed since 1.14). It lets you maintain a base set of manifests and apply environment-specific patches without duplicating YAML or using a templating language.
Basic Structure
base/
kustomization.yaml
deployment.yaml
service.yaml
overlays/
staging/
kustomization.yaml
patch-replicas.yaml
production/
kustomization.yaml
patch-replicas.yaml
A Minimal kustomization.yaml
cat base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app: my-app
cat overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
patchesStrategicMerge:
- patch-replicas.yaml
images:
- name: my-app
newTag: staging-abc123
Preview and Apply
# Preview rendered output without applying
kubectl kustomize overlays/staging
# Apply directly from an overlay directory
kubectl apply -k overlays/staging
# Apply from a remote Git repository
kubectl apply -k 'github.com/example/repo/overlays/staging?ref=main'
Verification
After working through these areas, confirm your setup is functional:
# Cluster reachable, context correct
kubectl cluster-info
# Current context, namespace, user
kubectl config view --minify
# API resources available (good for confirming CRDs)
kubectl api-resources | grep -i prometheus
Troubleshooting
- x509 certificate errors: Your kubeconfig certificate has expired or the cluster endpoint changed. Redownload the kubeconfig from your provider or re-run
kubeadm initcertificate rotation. - Error from server (Forbidden): Your user or service account lacks RBAC permissions. Run
kubectl auth can-i get pods -n my-appto check, and reviewClusterRole/RoleBindingobjects. - Ephemeral container not starting: Confirm the node kubelet version is 1.25+. Check
kubectl describe podforEphemeralContainerNotAllowedevents. - kustomize patch not applying: The patched resource must have the same
kind,apiVersion,name, andnamespaceas the base resource, or the merge will silently fail. Runkubectl kustomizeand inspect the output before applying. - Wrong namespace queried: If results seem empty, run
kubectl config view --minifyto confirm your active namespace, then use-Ato search all namespaces.
Frequently asked questions
- What is the difference between a context and a namespace in kubectl?
- A context is a named combination of a cluster endpoint, a user credential, and an optional default namespace stored in ~/.kube/config. A namespace is a Kubernetes API concept that partitions resources within a single cluster. A context can point to any cluster; the namespace only applies within that cluster.
- Is kubectl explain accurate for older clusters?
- Yes — kubectl explain queries the live cluster's API server, so it reflects the exact API version and fields available on that cluster, not a generic online reference. This makes it especially reliable when a cluster is several minor versions behind the current release.
- Do I need to install Kustomize separately?
- No. kubectl has shipped with Kustomize built in since version 1.14 (kubectl apply -k). If you need newer Kustomize features not yet in your kubectl version, you can install the standalone kustomize binary and pipe its output to kubectl apply -f -.
- Can kubectl debug work on pods running distroless or scratch images?
- Yes, that is exactly the scenario it is designed for. The ephemeral container runs your chosen debug image (busybox, ubuntu, nicolaka/netshoot) alongside the existing container. With --target set, it shares the target container's process namespace so you can inspect its processes and filesystem.
- How do I merge multiple kubeconfig files into one?
- Set the KUBECONFIG environment variable to a colon-separated list of config files, then flatten with kubectl config view --flatten > ~/.kube/config. Verify with kubectl config get-contexts before overwriting your existing file.
Related guides
Bash Arrays and Associative Arrays
Master bash indexed and associative arrays: declaration, element access, looping, mapfile, namerefs, and practical patterns for real scripting work.
Bash Functions and Variable Scoping
Master Bash function scoping with local variables, source-based libraries, correct use of return codes, and array passing techniques including namerefs.
Bash Loops: for, while and until
Learn all three Bash loop types — for, while, and until — with practical, copy-paste examples covering file iteration, counting, polling, and safe line reading.
Bash Scripting for Beginners
Learn Bash scripting from scratch: shebang lines, variables, conditionals, loops, and arguments, plus a real backup script to tie it all together.