$linuxjunkies
>

Use kubectl Effectively

Master kubectl contexts, namespace switching, built-in API docs with explain, structured output, live debugging with ephemeral containers, and Kustomize overlays.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

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 init certificate rotation.
  • Error from server (Forbidden): Your user or service account lacks RBAC permissions. Run kubectl auth can-i get pods -n my-app to check, and review ClusterRole/RoleBinding objects.
  • Ephemeral container not starting: Confirm the node kubelet version is 1.25+. Check kubectl describe pod for EphemeralContainerNotAllowed events.
  • kustomize patch not applying: The patched resource must have the same kind, apiVersion, name, and namespace as the base resource, or the merge will silently fail. Run kubectl kustomize and inspect the output before applying.
  • Wrong namespace queried: If results seem empty, run kubectl config view --minify to confirm your active namespace, then use -A to search all namespaces.
tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

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