The Problem
You're on-call and an alert fires. You need to quickly identify which pods are failing across a cluster with 500+ pods spread across 30 namespaces. Running a bare kubectl get pods dumps everything in the current namespace with no useful filtering. You need precise queries that surface exactly what matters.
This guide covers every practical pattern for querying pods in production Kubernetes clusters — from basic listing to complex JSONPath expressions.
Basic Pod Listing
Start with the fundamentals and build up:
# List pods in the current namespace
kubectl get pods
# List pods in a specific namespace
kubectl get pods -n production
# List pods across ALL namespaces
kubectl get pods -A
# Wide output — shows node assignment, IP, and nominated node
kubectl get pods -o wide
# Watch pods in real-time (useful during deployments)
kubectl get pods -w
The -o wide flag is underrated. It shows which node each pod landed on, which is critical when you suspect a node-level issue.
Filtering by Label
Labels are the primary mechanism for organizing and querying pods. Master label selectors and you can find anything instantly.
# Pods with a specific label
kubectl get pods -l app=api-gateway
# Pods matching multiple labels (AND logic)
kubectl get pods -l app=api-gateway,environment=production
# Pods where a label exists (regardless of value)
kubectl get pods -l 'app'
# Pods where a label does NOT exist
kubectl get pods -l '!canary'
# Set-based selectors — label value in a set
kubectl get pods -l 'tier in (frontend, backend)'
# Set-based selectors — label value NOT in a set
kubectl get pods -l 'environment notin (dev, staging)'
# Combine equality and set-based selectors
kubectl get pods -l 'app=payment-service,version in (v2, v3)'
Production pattern: find all pods for a service across environments
# All pods belonging to the checkout service regardless of environment
kubectl get pods -A -l app.kubernetes.io/name=checkout-service
# All pods managed by a specific deployment
kubectl get pods -l app.kubernetes.io/managed-by=helm,app.kubernetes.io/instance=my-release
Filtering by Field Selectors
Field selectors filter on pod spec fields, not labels. The supported fields are limited but powerful.
# Pods on a specific node
kubectl get pods --field-selector spec.nodeName=ip-10-0-1-42.ec2.internal
# Pods in a specific phase
kubectl get pods --field-selector status.phase=Running
kubectl get pods --field-selector status.phase!=Running
# Pods NOT running (find problems fast)
kubectl get pods -A --field-selector status.phase!=Running,status.phase!=Succeeded
# Combine field selectors
kubectl get pods --field-selector status.phase=Failed,spec.nodeName=worker-03
Find problematic pods across the entire cluster
# All pods that are not in Running or Completed state
kubectl get pods -A --field-selector 'status.phase!=Running,status.phase!=Succeeded'
# Pods stuck in Pending (scheduling issues)
kubectl get pods -A --field-selector status.phase=Pending
Output Formats
The default table output is fine for humans, but you often need structured data for scripting and automation.
JSON and YAML output
# Full JSON output
kubectl get pods -o json
# Full YAML output (more readable)
kubectl get pods -o yaml
# Single pod as JSON
kubectl get pod my-pod-abc123 -o json
# Extract a specific field with JSONPath
kubectl get pod my-pod-abc123 -o jsonpath='{.status.phase}'
# Get all pod names
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
# Pod names with their status — one per line
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
Custom columns — build your own table
Custom columns let you define exactly what information you want in table format:
# Pod name, status, restarts, and node
kubectl get pods -o custom-columns=\
NAME:.metadata.name,\
STATUS:.status.phase,\
RESTARTS:.status.containerStatuses[0].restartCount,\
NODE:.spec.nodeName
# Pod name, image, and resource requests
kubectl get pods -o custom-columns=\
NAME:.metadata.name,\
IMAGE:.spec.containers[0].image,\
CPU_REQ:.spec.containers[0].resources.requests.cpu,\
MEM_REQ:.spec.containers[0].resources.requests.memory
# Pods with their IP addresses and host IPs
kubectl get pods -o custom-columns=\
NAME:.metadata.name,\
POD_IP:.status.podIP,\
HOST_IP:.status.hostIP,\
NODE:.spec.nodeName
go-template for complex formatting
# List pods with restart counts > 0
kubectl get pods -o go-template='{{range .items}}{{if gt (index .status.containerStatuses 0).restartCount 0}}{{.metadata.name}} — {{(index .status.containerStatuses 0).restartCount}} restarts{{"\n"}}{{end}}{{end}}'
Sorting Pods
Sort output by any field path:
# Sort by creation time (newest first)
kubectl get pods --sort-by=.metadata.creationTimestamp
# Sort by restart count (most restarts first)
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
# Sort by node name (group by node)
kubectl get pods --sort-by=.spec.nodeName
# Combine sorting with custom columns for a restart report
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount' \
-o custom-columns=\
NAME:.metadata.name,\
RESTARTS:.status.containerStatuses[0].restartCount,\
LAST_STATE:.status.containerStatuses[0].lastState.terminated.reason
Practical On-Call Patterns
Pattern 1: Triage cluster health
# Quick health check — how many pods are in each state?
kubectl get pods -A --no-headers | awk '{print $4}' | sort | uniq -c | sort -rn
# Find CrashLoopBackOff pods
kubectl get pods -A | grep CrashLoopBackOff
# Find pods with high restart counts
kubectl get pods -A --sort-by='.status.containerStatuses[0].restartCount' | tail -20
# Find ImagePullBackOff issues
kubectl get pods -A | grep -E "ImagePull|ErrImagePull"
Pattern 2: Deployment rollout investigation
# See pods for a deployment with their age
kubectl get pods -l app=my-service --sort-by=.metadata.creationTimestamp
# Compare old and new replicaset pods during rollout
kubectl get pods -l app=my-service -o custom-columns=\
NAME:.metadata.name,\
READY:.status.conditions[?(@.type=='Ready')].status,\
AGE:.metadata.creationTimestamp,\
IMAGE:.spec.containers[0].image
Pattern 3: Resource consumption overview
# Pods and their resource requests (requires metrics-server for actual usage)
kubectl top pods --sort-by=memory
kubectl top pods --sort-by=cpu
# Pods without resource limits (dangerous in production)
kubectl get pods -o json | jq '.items[] | select(.spec.containers[].resources.limits == null) | .metadata.name'
Pattern 4: Pod scheduling and node distribution
# Count pods per node
kubectl get pods -A -o custom-columns=NODE:.spec.nodeName --no-headers | sort | uniq -c | sort -rn
# Find unscheduled pods
kubectl get pods -A --field-selector spec.nodeName="" 2>/dev/null
kubectl get pods -A --field-selector status.phase=Pending
Scripting with kubectl get pods
Combine kubectl output with shell tools for powerful automation:
# Delete all Evicted pods across all namespaces
kubectl get pods -A --field-selector status.phase=Failed -o json | \
jq -r '.items[] | select(.status.reason=="Evicted") | "\(.metadata.namespace) \(.metadata.name)"' | \
while read ns name; do kubectl delete pod "$name" -n "$ns"; done
# Export pod list as CSV
kubectl get pods -A -o custom-columns=\
NAMESPACE:.metadata.namespace,\
NAME:.metadata.name,\
STATUS:.status.phase,\
NODE:.spec.nodeName,\
IP:.status.podIP \
--no-headers | tr -s ' ' ','
# Get container images for vulnerability scanning
kubectl get pods -A -o jsonpath='{range .items[]}{range .spec.containers[]}{.image}{"\n"}{end}{end}' | sort -u
Common Mistakes
kubectl get pods only shows the current namespace. Use -A to see everything or -n to target a specific namespace.READY column (e.g., 0/1 means the container isn't ready).kubectl get pods | grep my-app is fragile. Use -l app=my-app for reliable filtering.--no-headers in scripts — When piping kubectl output to awk or other tools, the header row will pollute your results.kubectl get vs kubectl describe — get shows summary data. For events, conditions, and scheduling decisions, you need kubectl describe pod <name>.Quick Reference
| Task | Command | ||
|---|---|---|---|
| All pods, all namespaces | <code class="inline-code">kubectl get pods -A</code> | ||
| Filter by label | <code class="inline-code">kubectl get pods -l app=name</code> | ||
| Filter by node | <code class="inline-code">kubectl get pods --field-selector spec.nodeName=node1</code> | ||
| Non-running pods | <code class="inline-code">kubectl get pods -A --field-selector status.phase!=Running,status.phase!=Succeeded</code> | ||
| Custom columns | <code class="inline-code">kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase</code> | ||
| JSON specific field | <code class="inline-code">kubectl get pod X -o jsonpath='{.status.phase}'</code> | ||
| Sort by restarts | <code class="inline-code">kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'</code> | ||
| Watch real-time | <code class="inline-code">kubectl get pods -w</code> | ||
| Pod count per node | <code class="inline-code">kubectl get pods -A -o custom-columns=NODE:.spec.nodeName --no-headers \ | sort \ | uniq -c</code> |
| Get all container images | <code class="inline-code">kubectl get pods -A -o jsonpath='{..image}' \ | tr ' ' '\n' \ | sort -u</code> |
Summary
kubectl get pods is your first stop in any Kubernetes investigation. Master label selectors for filtering, custom columns for readable output, and JSONPath for scripting. The difference between a 5-minute and 30-minute incident response often comes down to knowing the right query to run.
---
Frequently Asked Questions
How do I list all pods in all namespaces?
Use kubectl get pods --all-namespaces or the shorthand kubectl get pods -A. Add -o wide to include node names, IP addresses, and nominated nodes. For a specific namespace, use kubectl get pods -n <namespace-name>.
How do I filter pods by label in kubectl?
Use the -l flag with label selectors: kubectl get pods -l app=nginx for exact match, kubectl get pods -l 'environment in (production,staging)' for set-based selection, or kubectl get pods -l app=nginx,version=v2 for multiple labels. Use --show-labels to see all labels on each pod.
How do I get more details about a specific pod?
Use kubectl describe pod <pod-name> for a human-readable summary including events, conditions, and container status. Use kubectl get pod <pod-name> -o yaml for the full resource specification. For just the status, use kubectl get pod <pod-name> -o jsonpath='{.status.phase}'.
What does pod status "Pending" mean?
Pending means Kubernetes accepted the pod but one or more containers cannot start yet. Common causes are: insufficient cluster resources (CPU/memory), no node matching nodeSelector or affinity rules, PersistentVolumeClaim not bound, or image pull taking longer than expected. Run kubectl describe pod and check the Events section for the specific reason.
How do I watch pods in real-time?
Use kubectl get pods --watch or kubectl get pods -w to stream status changes as they happen. For a more visual experience, use tools like k9s or watch -n 1 kubectl get pods. Combine with grep for specific pods: kubectl get pods -w | grep my-app.
---
Related Resources
- kubectl Cheatsheet — 71 kubectl commands searchable by task
- DevOps Interview Academy — 60 DevOps interview questions including Kubernetes
- Production Troubleshooting Scenarios — 15 production troubleshooting scenarios
- Kubernetes Pod Troubleshooting Guide — Debugging CrashLoopBackOff and other pod failures
- Kubernetes ConfigMaps and Secrets — Managing configuration for your pods