kubectl get and describe

By Vishvesh Patel · DevOps EngineerUpdated September 12, 2026

Inspect Kubernetes resources with get and describe. Output formats, label and field selectors, jsonpath, and reading the events that explain most failures.

get lists resources and answers "what exists". describe shows one resource in full, including the events attached to it, and answers "why is this not working".

Most Kubernetes debugging is describe followed by reading the bottom of the output.

get

kubectl get pods
kubectl get pods,services,deployments        # several types at once
kubectl get all                              # common types in this namespace
kubectl get pods -A                          # every namespace
kubectl get pods -n payments

kubectl get all is a convenience rather than a promise. It covers Pods, Services, Deployments, ReplicaSets and StatefulSets, but not ConfigMaps, Secrets, PVCs, Ingresses or anything custom.

Wider output

kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS      AGE   IP            NODE
payments-api-7d4f-x8k2   1/1     Running   0             12m   10.244.1.17   node-1
payments-api-7d4f-m3p9   0/1     Running   4 (30s ago)   12m   10.244.2.31   node-2

Three columns carry most of the signal:

  • READY is containers passing readiness over total. 0/1 while Running means the process started but the readiness probe is failing, so the Pod receives no traffic.
  • RESTARTS with a timestamp means it restarted recently, which is very different from four restarts two days ago.
  • NODE matters when a failure correlates with one machine.

Watching

kubectl get pods -w

Live updates as things change. The clearest way to see a rolling update actually happen.

Selecting

kubectl get pods -l app=payments-api
kubectl get pods -l 'env in (staging,prod)'
kubectl get pods -l 'app=payments-api,version!=1.4.2'
kubectl get pods --show-labels

Label selectors are how Kubernetes objects find each other, and --show-labels is how you check why a Service selector is not matching.

Field selectors filter on object fields rather than labels:

kubectl get pods --field-selector status.phase=Running
kubectl get pods --field-selector spec.nodeName=node-1
kubectl get events --field-selector type=Warning

Sorting

kubectl get pods --sort-by=.status.containerStatuses[0].restartCount
kubectl get events --sort-by=.lastTimestamp

Sorting events by timestamp is worth memorising. The default order is not chronological, which is confusing exactly when you are in a hurry.

Output formats

kubectl get pod payments-api-7d4f-x8k2 -o yaml
kubectl get pod payments-api-7d4f-x8k2 -o json

-o yaml shows the object as stored, including status and defaults you never wrote. It is the definitive answer to "what is actually configured".

jsonpath

Extracting one value, for scripts or just to avoid scrolling:

kubectl get pod <name> -o jsonpath='{.status.podIP}'

# Why did the container die?
kubectl get pod <name> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason}'

# Every image in the namespace
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'

custom-columns

A readable table of exactly what you want:

kubectl get pods -o custom-columns=\
NAME:.metadata.name,\
STATUS:.status.phase,\
READY:.status.containerStatuses[0].ready,\
RESTARTS:.status.containerStatuses[0].restartCount,\
NODE:.spec.nodeName

describe

kubectl describe pod payments-api-7d4f-m3p9

describe assembles the object, its defaults, related objects, and, the part that matters, the events for it.

Events:
  Type     Reason     Age                From     Message
  ----     ------     ----               ----     -------
  Normal   Scheduled  2m                 default-scheduler  Successfully assigned payments/payments-api-7d4f-m3p9 to node-2
  Normal   Pulled     2m                 kubelet  Container image "ghcr.io/acme/payments-api:1.5.0" already present
  Warning  Unhealthy  30s (x6 over 90s)  kubelet  Readiness probe failed: HTTP probe failed with statuscode: 404

That last line is the whole diagnosis: the readiness path returns 404, so the Pod never becomes Ready and gets no traffic. No log reading required.

Events you will meet constantly:

ReasonMeaning
FailedSchedulingNo node fits (the message lists why per node)
Failed / ErrImagePullImage cannot be pulled; the registry's own error is quoted
UnhealthyA probe failed, with the status code or error
OOMKilledExceeded the memory limit
FailedMountVolume could not be attached or mounted
BackOffRestarting with increasing delay

describe works on everything, and is just as useful elsewhere:

kubectl describe node node-2          # conditions, capacity, allocated resources
kubectl describe service payments-api # selector and endpoints
kubectl describe pvc payments-data    # why a claim is Pending
kubectl describe deployment payments-api

Events on their own

describe only shows events for one object. Cluster-wide:

kubectl get events -A --sort-by=.lastTimestamp
kubectl get events --field-selector type=Warning
kubectl get events --field-selector involvedObject.name=payments-api-7d4f-m3p9

Events expire after about an hour by default. If an incident is more than an hour old, the event that explains it is already gone, which is a good argument for shipping events into your logging system.

get or describe?

UseFor
getWhat exists, current status, many objects at once, scripting
get -o yamlExactly what is configured, including defaults
describeWhy one object is unhealthy (events are the payoff)

The habit worth building: get to find the broken thing, describe to find out why, logs only if describe did not say.

Quick reference

TaskCommand
List with detailkubectl get pods -o wide
Everything commonkubectl get all
Across namespaceskubectl get pods -A
Watch livekubectl get pods -w
By labelkubectl get pods -l app=<label>
Show labelskubectl get pods --show-labels
Full objectkubectl get pod <n> -o yaml
One fieldkubectl get pod <n> -o jsonpath='{.status.podIP}'
Diagnosekubectl describe pod <n>
Recent eventskubectl get events -A --sort-by=.lastTimestamp
Warnings onlykubectl get events --field-selector type=Warning

Key takeaways

  • describe is the debugging command, and the Events section at the bottom is why.
  • READY 0/1 with status Running means a failing readiness probe: the Pod gets no traffic.
  • get -o yaml shows the object as stored, including defaults you never wrote.
  • --show-labels resolves most Service selector mismatches in one command.
  • Sort events by .lastTimestamp: the default order is not chronological.
  • Events expire after roughly an hour. Ship them somewhere if you want them later.
  • kubectl get all does not include ConfigMaps, Secrets, PVCs or Ingresses.

Check your understanding

Exercise

Running but not serving

kubectl get pods shows a Pod as Running with READY 0/1 and RESTARTS 0. What does this tell you?

Exercise

An incident with no evidence

You investigate a crash that happened three hours ago. kubectl describe pod shows no events at all, though the Pod clearly restarted. Why?


Frequently Asked Questions

What is the difference between kubectl get and kubectl describe?

get lists resources with a short status summary and works across many objects at once, which makes it the right tool for finding things and for scripting. describe renders one object in full. Its spec, its defaults, related objects, and crucially the events attached to it. Events are where Kubernetes explains itself, so describe is what you run when something is broken and get is what you run to find out what exists.

How do I see why a Pod is failing?

kubectl describe pod <name> and read the Events section at the bottom. It usually states the cause outright: FailedScheduling with the per-node reasons, an image pull error quoting the registry's own message, Unhealthy with the probe's status code, or a FailedMount for a volume problem. Only if the events do not explain it do you need kubectl logs <pod> --previous, which shows output from the container run that actually crashed.

What does READY 0/1 mean?

Zero of one containers are passing their readiness probe. If the Pod's status is also Running, the process started fine and the probe itself is failing. A wrong path or port, an endpoint behind authentication returning 401, or an initialDelaySeconds shorter than real startup time. A Pod in this state is deliberately excluded from its Service's endpoints, so it receives no traffic, which is exactly what readiness is for.

How do I get just one field from a resource?

Use jsonpath: kubectl get pod <name> -o jsonpath='{.status.podIP}'. It is particularly useful for values buried in status, such as kubectl get pod <name> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason}' which returns OOMKilled for a container killed on memory. For tabular output across many objects, -o custom-columns lets you build exactly the table you want rather than scrolling through YAML.

Why are my events missing?

They expire. Kubernetes keeps events for about an hour by default, set by the API server's --event-ttl, because they are high volume and treated as transient. Anything older than that is gone, which routinely means the event explaining an overnight failure has vanished before anyone looks. Exporting events into your log store, the Kubernetes Event Exporter is the usual tool, preserves them, and it is not something the common monitoring stacks do for you.

Does kubectl get all really show everything?

No, and the name is misleading. It covers the common workload and networking types. Pods, Services, Deployments, ReplicaSets, StatefulSets, DaemonSets and Jobs, but omits ConfigMaps, Secrets, PersistentVolumeClaims, Ingresses, ServiceAccounts and every custom resource. To see genuinely everything in a namespace you need to enumerate the API resources and query each, which kubectl api-resources supports but is rarely worth doing by hand.

Continue Learning

Explore Related Topics

Try the Tool

Practise this in the browser

Kubernetes Playground

Practise kubectl against a simulated cluster in your browser.

When it breaks

Related Resources