3.4 Output Formats: -o wide, -o json, -o yaml, and jsonpath
Right, let’s talk about making kubectl actually tell you what you want to know. By default, its output is polite, minimal, and often utterly useless. It’s like asking a concierge for directions and getting a single street name. The -o (or --output) flag is your way of saying, “No, seriously, I need the map, the traffic report, and the historical significance of the building on the corner.”
We’re going to move from just getting a little more info to taking full, programmatic control. Strap in.
The Usual Suspects: -o wide and the Structured Bunch
The first step up from the default view is -o wide. It’s the CLI equivalent of squinting slightly harder.
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# my-pod 1/1 Running 0 25m
kubectl get pods -o wide
# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
# my-pod 1/1 Running 0 25m 10.244.1.5 my-worker-node <none> <none>
See? Now we get the Pod’s IP and which Node it’s squatting on. Helpful, but still just a prettified table. For real power, you need structured data: -o json and -o yaml. These are your “give me everything” flags. They spit out the complete resource definition as stored in the Kubernetes API, which is invaluable for debugging, seeing default values the system has applied, or piping into other tools like jq.
kubectl get pod my-pod -o yaml
# apiVersion: v1
# kind: Pod
# metadata:
# name: my-pod
# namespace: default
# uid: a1b2c3d4-1234-5678-90ef-g5h6j7k8l9m0
# spec:
# containers:
# - image: nginx:latest
# name: nginx
# ... (and so on, for pages)
Why this matters: This is the ground truth. The table view is a lie—a pleasant abstraction. The JSON/YAML output is the resource. When a field is mysteriously 0 or <none> in the table, the structured output shows you why.
The Sledgehammer: jsonpath
Now we get to the fun part. What if you don’t want the entire manifesto, just one specific fact, like the Pod’s IP? You could get the whole YAML and grep it, but you’re not a barbarian. You use jsonpath.
The syntax is… well, it’s a bit like Perl. It grew organically and has some frankly weird historical baggage. You use it with -o jsonpath='{<your-template>}'.
The most common pitfall? The {.items[*]} syntax for lists. You almost always need it.
# This fails miserably because 'get pod' returns a List, not a single item.
kubectl get pods -o jsonpath='{.metadata.name}'
# <no output>
# This works. We have to range over the items in the list first.
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
# my-pod other-pod final-pod
# Want a nicer output? Use a format string.
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'
# my-pod 10.244.1.5
# other-pod 10.244.2.10
The real power comes with combining it with jsonpath’s built-in functions, which are bizarrely hidden and underdocumented. Need to see the name of every container in every pod, without duplicates? Sure, why not.
kubectl get pods -o jsonpath="{.items[*].spec.containers[*].name}" | tr ' ' '\n' | sort | uniq
# nginx
# redis
# sidecar
But let’s be honest, the raw jsonpath syntax is kind of a pain to remember. This is where the designers’ questionable choice to create a whole new templating language (instead of just using jq natively) really stings.
Your New Best Friend: jsonpath and jq
So here’s my professional recommendation: use kubectl’s -o json flag to get the raw data, then pipe it to jq. You get a far more powerful, consistent, and well-documented language to slice and dice your resources.
Need to find all Pods that aren’t running?
kubectl get pods -o json | jq -r '.items[] | select(.status.phase != "Running") | .metadata.name'
Want to get a list of all Images being used in the current namespace?
kubectl get pods -o json | jq -r '.items[].spec.containers[].image' | sort | uniq
This combination is unstoppable. You’re using kubectl for what it’s good at—talking to the API—and jq for what it’s good at—manipulating JSON. It’s a clean separation of concerns.
The -o jsonpath flag has its place, mainly for quick, one-off commands where you don’t want to depend on jq being installed. But for any serious troubleshooting or scripting, kubectl get -o json | jq is the way. It turns the overwhelming firehose of API output into exactly the stream of information you need.