DEV Community

Harshit Luthra
Harshit Luthra

Posted on • Originally published at harshit.cloud

kubectl JSONPath: Extract Exactly What You Need

Originally published at harshit.cloud on 2024-12-12.


TIL: kubectl JSONPath: Extract Exactly What You Need

Stop piping kubectl output to grep, awk, and sed. JSONPath can get you exactly what you need in one command.

the basic pattern

kubectl get <resource> -o jsonpath='{<jsonpath-expression>}'
Enter fullscreen mode Exit fullscreen mode

simple examples

get pod IPs

Instead of:

kubectl get pods -o wide | awk '{print $6}'
Enter fullscreen mode Exit fullscreen mode

Do:

kubectl get pods -o jsonpath='{.items[*].status.podIP}'
Enter fullscreen mode Exit fullscreen mode

get pod names only

kubectl get pods -o jsonpath='{.items[*].metadata.name}'
Enter fullscreen mode Exit fullscreen mode

get pod name + IP

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

Output:

nginx-abc123    10.244.1.5
redis-xyz789    10.244.1.6
Enter fullscreen mode Exit fullscreen mode

real-world use cases

1. find all container images

kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u
Enter fullscreen mode Exit fullscreen mode

2. get pods not running

kubectl get pods -o jsonpath='{range .items[?(@.status.phase!="Running")]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

3. find pods using most memory

kubectl top pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.usage.memory}{"\n"}{end}' | sort -k2 -h
Enter fullscreen mode Exit fullscreen mode

4. get all node capacities

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.capacity.cpu}{" CPU\t"}{.status.capacity.memory}{" RAM\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

5. find secrets in a namespace

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.volumes[?(@.secret)].secret.secretName}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

6. get all services and their type

kubectl get svc -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.type}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

JSONPath syntax cheat sheet

Pattern Description Example
.items[*] All items Get all pods
.items[0] First item Get first pod
.items[0:3] First 3 items Get first 3 pods
.items[-1] Last item Get last pod
.items[?(@.field=="value")] Filter Pods where phase=Running
{range .items[*]}...{end} Loop Iterate over items
{"\n"} Newline Format output
{"\t"} Tab Format output

advanced filtering

pods with specific label

kubectl get pods -l app=nginx -o jsonpath='{.items[*].metadata.name}'
Enter fullscreen mode Exit fullscreen mode

pods in Running state

kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'
Enter fullscreen mode Exit fullscreen mode

containers in Waiting state

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[?(@.state.waiting)].name}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

pods with restart count > 0

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[0].restartCount}{"\n"}{end}' | awk '$2 > 0'
Enter fullscreen mode Exit fullscreen mode

useful aliases

Add to your ~/.bashrc or ~/.zshrc:

# Get pod IPs
alias kip='kubectl get pods -o jsonpath='\''{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'\'''

# Get images
alias kimages='kubectl get pods -o jsonpath='\''{.items[*].spec.containers[*].image}'\'' | tr " " "\n" | sort -u'

# Get pod with most restarts
alias krestart='kubectl get pods -o jsonpath='\''{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[0].restartCount}{"\n"}{end}'\'' | sort -k2 -n -r | head -1'

# Get not ready pods
alias knotready='kubectl get pods -o jsonpath='\''{range .items[?(@.status.phase!="Running")]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'\'''
Enter fullscreen mode Exit fullscreen mode

custom columns (even better)

Sometimes custom columns are cleaner than JSONPath:

# Pod name, phase, and IP
kubectl get pods -o custom-columns=NAME:.metadata.name,PHASE:.status.phase,IP:.status.podIP

# Node name, CPU, and memory
kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.capacity.cpu,MEMORY:.status.capacity.memory

# Services and their ClusterIP
kubectl get svc -o custom-columns=NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP
Enter fullscreen mode Exit fullscreen mode

common patterns I use daily

1. quick debug — get all pod info

kubectl get pod nginx-abc123 -o jsonpath='{range .spec.containers[*]}Name: {.name}{"\n"}Image: {.image}{"\n"}Ports: {.ports[*].containerPort}{"\n\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

2. get all environment variables

kubectl get pod nginx-abc123 -o jsonpath='{range .spec.containers[*].env[*]}{.name}={.value}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

3. find pods on a specific node

kubectl get pods --all-namespaces -o jsonpath='{range .items[?(@.spec.nodeName=="node-1")]}{.metadata.name}{"\t"}{.metadata.namespace}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

4. get ConfigMaps used by pods

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.volumes[?(@.configMap)].configMap.name}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

5. network policies applied to pods

kubectl get netpol -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podSelector.matchLabels}{"\n"}{end}'
Enter fullscreen mode Exit fullscreen mode

the live-updates move

Combine JSONPath with watch for live updates:

watch -n 2 'kubectl get pods -o jsonpath='\''{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'\'''
Enter fullscreen mode Exit fullscreen mode

debugging JSONPath

If your JSONPath isn't working, test it step by step:

# Get full JSON first
kubectl get pod nginx-abc123 -o json | jq '.'

# Then build your JSONPath incrementally
kubectl get pod nginx-abc123 -o jsonpath='{.metadata}'
kubectl get pod nginx-abc123 -o jsonpath='{.metadata.name}'
kubectl get pod nginx-abc123 -o jsonpath='{.status}'
kubectl get pod nginx-abc123 -o jsonpath='{.status.phase}'
Enter fullscreen mode Exit fullscreen mode

the gotcha

JSONPath in kubectl has some quirks:

  1. Filters must use @: .items[?(@.field=="value")] not .items[?(.field=="value")]
  2. Arrays need [*]: .items[*] not .items[]
  3. Quotes matter: use single quotes outside, double inside: '{.items[?(@.name=="value")]}'

This has eliminated so much grep | awk | sed pipeline complexity from my daily kubectl commands.

Top comments (0)