Back to Blog

kubectl Output Formatting for the CNCF Exams: JSONPath, Custom Columns, Field Selectors & Sorting (CKA, CKAD, CKS)

Master kubectl output formatting for the CKA, CKAD, and CKS exams — JSONPath queries, custom-columns, field selectors, --sort-by, and -o wide. A commands-first guide to extracting exactly the data a task asks for, fast.

By Sailor Team , July 21, 2026

Every CNCF Kubernetes performance exam — CKA, CKAD, and CKS — eventually hands you a task that boils down to one sentence: “Find the pods/nodes/secrets that match this condition and write the answer to a file.” You already know how to create resources. What separates candidates who finish with time to spare from those who run out of clock is how fast they can extract exactly the right piece of data from a live cluster and pipe it somewhere.

kubectl get pods dumps a table. But the exam rarely wants the whole table. It wants the name of the node a specific pod landed on, the image a container is running, the pods that are not Running, or a list sorted by restart count. Doing that by eyeballing a wide terminal is slow and error-prone. Doing it with JSONPath, --custom-columns, field selectors, and --sort-by takes seconds and never miscounts.

This guide is the output-formatting toolkit that carries across all three hands-on exams. It’s commands-first: copy them, run them against your practice cluster, and build the muscle memory. If you want the broader terminal workflow — aliases, Vim, imperative generators — pair this with our Kubernetes exam terminal and kubectl speed guide.

Why Output Formatting Is an Exam Skill, Not a Nice-to-Have

The CKA, CKAD, and CKS exams are scored on results written to the cluster or to files, under a two-hour clock across ~15–20 weighted tasks. A meaningful fraction of tasks are inspection tasks: identify something, then record it. Consider the shapes these take:

  • “Write the name of the node running pod X to /opt/answer.txt.”
  • “List all pods in namespace mercury sorted by number of restarts, descending.”
  • “Find the Secret whose type is kubernetes.io/tls and output its name.”
  • “Show every container image used by Deployments in the web namespace.”

Each of these has a slow manual path (scroll, squint, copy) and a fast declarative path (one kubectl get with the right flags). The declarative path is faster and self-verifying — if your query returns the right value, you know it’s right. This is exactly the habit that prevents the classic time-management and verification mistakes covered in our 10 Kubernetes exam mistakes guide.

The Five Output Formats You Need

kubectl supports many output formats via -o / --output. For the exams, five matter:

FormatFlagUse it when
Wide table-o wideYou need node, IP, or image without parsing
YAML / JSON-o yaml / -o jsonYou need to read the full object or feed jq/JSONPath
JSONPath-o jsonpath='...'You need one or a few specific fields, scriptable
Custom columns-o custom-columns=...You need a clean table of chosen fields
Name-o nameYou need just kind/name for piping into another command

Start with the cheapest tool that answers the question. If -o wide shows the node, you don’t need JSONPath. But when the field is nested or you need to filter, JSONPath and custom-columns are unbeatable.

# -o wide: node + pod IP without any parsing
kubectl get pods -n mercury -o wide

# -o name: clean list for piping (e.g. delete, label, restart)
kubectl get pods -n mercury -o name
# pod/frontend-7c9f...
# pod/backend-5d8b...

kubectl JSONPath: The Core Skill

JSONPath is a query language for JSON. Because every Kubernetes object is JSON under the hood, JSONPath lets you reach into any field of any resource. The syntax kubectl uses is a subset with a couple of quirks worth memorizing.

Anatomy of a JSONPath Query

kubectl get pods -o jsonpath='{.items[0].metadata.name}'
  • { } wraps the expression.
  • .items[0]get on a list returns a List object with an items array; index into it.
  • .metadata.name — standard dotted path into the object.

When you kubectl get pod <name> (a single resource), there is no items array — query the object directly:

kubectl get pod frontend -o jsonpath='{.spec.nodeName}'

The Wildcard: Looping Over All Items

Use [*] to iterate every element of an array. This is how you extract a field from every pod:

# Every pod name in the namespace, space-separated
kubectl get pods -n mercury -o jsonpath='{.items[*].metadata.name}'

# Every container image across all pods
kubectl get pods -n mercury -o jsonpath='{.items[*].spec.containers[*].image}'

Ranges and Newlines: Readable Output

Space-separated output is hard to read and hard to copy one value from. Use range/end with {"\n"} to put each result on its own line and combine multiple fields per row:

kubectl get pods -n mercury -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}'

This prints podname<TAB>nodename per line — a mini report you can redirect to a file. {"\t"} is a tab, {"\n"} a newline. Quote the whole expression in single quotes so your shell leaves it alone.

JSONPath Filters: Selecting by Condition

The ?() filter expression selects array elements matching a condition — the exam’s bread and butter for “find the X where Y”:

# Name of the pod(s) scheduled on node "node01"
kubectl get pods -A -o jsonpath='{.items[?(@.spec.nodeName=="node01")].metadata.name}'

# The container port of a specific container
kubectl get pod frontend -o jsonpath='{.spec.containers[?(@.name=="app")].ports[0].containerPort}'

@ refers to the current element. Comparisons use ==. A common exam use is finding a Secret or Service by a nested attribute:

# Names of all TLS-type secrets
kubectl get secrets -A -o jsonpath='{.items[?(@.type=="kubernetes.io/tls")].metadata.name}'

Quirk to remember: kubectl’s JSONPath does not support the full JSONPath spec. Regex matches and some operators are unavailable, and filters can be finicky with non-string types. When a filter misbehaves, fall back to custom-columns + grep or pipe -o json into jq.

A Practical JSONPath Recipe Book

# ClusterIP of a service
kubectl get svc my-svc -o jsonpath='{.spec.clusterIP}'

# All node internal IPs
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'

# Image of the first container in a deployment
kubectl get deploy web -o jsonpath='{.spec.template.spec.containers[0].image}'

# Names of pods that are NOT in Running phase (see note below)
kubectl get pods -A -o jsonpath='{range .items[?(@.status.phase!="Running")]}{.metadata.name}{"\n"}{end}'

# The current context's cluster server URL (handy in CKS)
kubectl config view -o jsonpath='{.clusters[0].cluster.server}'

Custom Columns: Clean Tables of Exactly What You Want

--custom-columns builds a table where you name each column and its JSONPath. It’s more readable than raw JSONPath for multi-field output and easier to eyeball or pipe into grep/sort.

kubectl get pods -n mercury -o custom-columns=\
'NAME:.metadata.name,NODE:.spec.nodeName,STATUS:.status.phase'

The format is HEADER:jsonpath pairs separated by commas. Note the JSONPath here is relative to each item — you don’t write .items[*], kubectl loops for you. To pull a field from an array element, use an index or wildcard:

# Pod name + first container image + restart count
kubectl get pods -n mercury -o custom-columns=\
'POD:.metadata.name,IMAGE:.spec.containers[0].image,RESTARTS:.status.containerStatuses[0].restartCount'

For long specs, --custom-columns-file=cols.txt reads column definitions from a file, but on the clock inline is usually faster.

Field Selectors: Filter Server-Side Before Formatting

JSONPath filters run client-side — kubectl downloads everything, then filters. --field-selector filters server-side, which is faster on large clusters and often cleaner syntax. The catch: only certain fields are selectable (it varies by resource), most commonly metadata.name, metadata.namespace, status.phase, and for pods spec.nodeName.

# All pods on a specific node, cluster-wide
kubectl get pods -A --field-selector spec.nodeName=node01

# All non-Running pods (great for troubleshooting tasks)
kubectl get pods -A --field-selector status.phase!=Running

# All events of type Warning
kubectl get events -A --field-selector type=Warning

# Everything in a namespace except kube-system (combine selectors with commas)
kubectl get pods -A --field-selector metadata.namespace!=kube-system

Field selectors compose nicely with output formatting — filter server-side, then format what’s left:

kubectl get pods -A --field-selector status.phase=Failed \
  -o custom-columns='NS:.metadata.namespace,POD:.metadata.name'

Sorting: —sort-by

--sort-by takes a JSONPath into each item and sorts the output table by that value. It’s the fastest way to answer “which pod has the most restarts” or “list nodes by CPU.”

# Pods sorted by restart count (ascending)
kubectl get pods -n mercury --sort-by='.status.containerStatuses[0].restartCount'

# Pods by creation time — oldest first
kubectl get pods -A --sort-by=.metadata.creationTimestamp

# Nodes by allocatable memory
kubectl get nodes --sort-by='.status.allocatable.memory'

--sort-by only sorts ascending. When a task wants “highest first,” sort ascending and read the bottom row, or pipe through tac. Combine --sort-by with a label selector to scope it:

kubectl get pods -l app=nginx --sort-by='.status.containerStatuses[0].restartCount'

Label & Selector Filtering (Don’t Forget the Basics)

Before reaching for JSONPath, remember that -l/--selector and --show-labels solve a huge share of “find the resource with label X” tasks with almost no typing:

kubectl get pods -l tier=backend,env=prod          # AND of two labels
kubectl get pods -l 'env in (dev,staging)'          # set-based
kubectl get pods --show-labels                       # see every label
kubectl get pods -L app -L tier                       # labels as columns

-L (capital) adds label values as their own columns — a lightweight alternative to custom-columns when you only need labels.

Putting It Together: Worked Exam-Style Tasks

Here’s how the toolkit collapses real task shapes into one-liners.

Task: Write the name of the node running pod data-loader in namespace pluto to /opt/node.txt.

kubectl get pod data-loader -n pluto -o jsonpath='{.spec.nodeName}' > /opt/node.txt
cat /opt/node.txt   # verify — always verify

Task: List all pods in mercury with their images, sorted by name, and save to /opt/images.txt.

kubectl get pods -n mercury \
  -o custom-columns='POD:.metadata.name,IMAGE:.spec.containers[*].image' \
  --sort-by=.metadata.name > /opt/images.txt

Task (CKS flavor): Identify all ServiceAccounts in the cluster that have automountServiceAccountToken: true and record their names.

kubectl get sa -A -o jsonpath='{range .items[?(@.automountServiceAccountToken==true)]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}'

Task: Which pod in neptune has restarted the most?

kubectl get pods -n neptune \
  --sort-by='.status.containerStatuses[0].restartCount' \
  -o custom-columns='POD:.metadata.name,RESTARTS:.status.containerStatuses[0].restartCount'
# read the bottom row

Notice the pattern: filter → format → verify → redirect. That loop is the entire skill.

When JSONPath Fights Back: The jq Escape Hatch

kubectl’s JSONPath is intentionally limited. When you need regex, arithmetic, boolean logic, or complex transformations, dump JSON and use jq (available in the exam environment):

# Pods using the 'latest' image tag — regex, which JSONPath can't do
kubectl get pods -A -o json | jq -r \
  '.items[] | select(.spec.containers[].image | test(":latest$")) | .metadata.name'

# Count pods per namespace
kubectl get pods -A -o json | jq -r '.items[].metadata.namespace' | sort | uniq -c

Know both. JSONPath is faster to type for simple lookups; jq handles the cases JSONPath can’t. Don’t burn three minutes wrestling a JSONPath filter when a jq pipe would take thirty seconds.

Speed Tips That Compound Across All Three Exams

  • Alias early. alias k=kubectl and export do="--dry-run=client -o yaml" in the first 60 seconds. See the terminal speed guide for a full setup.
  • kubectl explain --recursive reveals the exact field path so your JSONPath matches reality: kubectl explain pod.spec --recursive | grep -i nodeName.
  • Test the query, then redirect. Run the command, confirm the output, then add > file. Redirecting a wrong query silently writes garbage.
  • Prefer --field-selector for phase/node/name filters — server-side is faster and less typo-prone than a JSONPath filter.
  • Don’t over-engineer. If -o wide answers it, stop there.

Because these formatting skills are shared across all five KubeAstronaut exams (the hands-on trio uses them constantly; even KCNA/KCSA questions assume you understand kubectl output), they’re some of the highest-leverage minutes you can invest. For the full map of which skills each exam tests, see our KubeAstronaut curriculum map.

Practice Until the Query Comes Before the Thought

Reading these commands isn’t enough — the exam rewards recall under pressure. The only way to make -o jsonpath='{range ...}' come out of your fingers automatically is repetition against a real cluster on a timer.

That’s exactly what a realistic mock environment gives you. The Sailor.sh KubeAstronaut Mock Exam Bundle packages 15 full-length performance and MCQ exams across all five CNCF certifications — 900+ questions with hands-on labs for CKA, CKAD, and CKS — so you practice extracting, filtering, and formatting data under the same two-hour clock you’ll face on exam day. Every question ships with a detailed explanation, so when a JSONPath filter surprises you, you learn why. If you want to try the interface first, our free CK-X Kubernetes exam simulator lets you rehearse in a browser-based terminal.

For the authoritative syntax reference, bookmark the official kubectl JSONPath support and kubectl cheat sheet pages — both are inside the allowed documentation during the exams.

Frequently Asked Questions

Is JSONPath actually needed to pass the CKA, CKAD, or CKS?

You can technically pass without deep JSONPath by eyeballing -o wide output, but you’ll be slower and more error-prone on inspection tasks. Given the two-hour clock, fluent output formatting is one of the cheapest ways to buy back time. Treat it as core, not optional.

What’s the difference between a field selector and a JSONPath filter?

A --field-selector filters server-side and only supports a small set of fields (like metadata.name, status.phase, spec.nodeName). A JSONPath ?() filter runs client-side on the full downloaded object and can match almost any field. Use field selectors when the field is supported (faster, cleaner); use JSONPath filters for arbitrary nested fields.

Can I use jq during the exam?

Yes — jq is available in the CNCF exam terminal, and it’s the right tool when kubectl’s limited JSONPath can’t express your query (regex, arithmetic, complex conditions). Dump with -o json and pipe into jq.

Why does my JSONPath return nothing?

Three common causes: (1) you queried a single object but used .items[*] (single-object get has no items array); (2) the field path is wrong — verify with kubectl explain <resource> --recursive; (3) a filter comparison type mismatch (e.g., comparing a boolean or number as a string). Test incrementally, starting from {.items[0]} and adding depth.

How do I sort descending with —sort-by?

--sort-by only sorts ascending. Sort ascending and read the last row, or pipe the output through tac (reverse lines) or sort -rn on a specific column if you’ve formatted it with custom-columns.

Which is better for the exam, custom-columns or JSONPath?

Use --custom-columns when you want a readable multi-field table or need to grep/sort the result. Use raw -o jsonpath when you need a single value to redirect into a file, or when you need range-based multi-line output with tabs. They’re complementary — most candidates use both within a single exam.

Conclusion

Output formatting is the quiet skill that decides how much time you have left for the hard tasks. JSONPath extracts single fields and filters by condition; custom-columns builds clean tables; field selectors filter server-side; --sort-by orders results; and jq covers what kubectl can’t. Together they turn “find the X where Y and write it to a file” from a squinting exercise into a reliable one-liner.

Drill these against a live cluster until the query forms before you’ve finished reading the task. When you’re ready to test that fluency under exam conditions across all five CNCF certifications, the KubeAstronaut Mock Exam Bundle gives you the timed, hands-on reps that make it automatic.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now