Skip to content
LatchkeyLatchkey home

stern: Tail Pod Logs by Regex in CI

stern <query> streams logs from every pod whose name matches the regex, prefixing each line with the pod and container.

kubectl logs handles one pod; stern follows a whole Deployment or ReplicaSet by name pattern. In CI it surfaces logs from all replicas while an integration test runs.

What it does

stern takes a pod query (a regex, or a resource/name like deployment/api) and tails the logs of every matching pod and container at once. Each line is prefixed and colored by pod, so interleaved output stays readable.

Common usage

Terminal
stern api                       # all pods whose name matches /api/
stern "web-.*" --since 5m       # only the last 5 minutes
stern deployment/checkout       # follow a Deployment's pods
stern api -c nginx              # only the nginx container

Options

FlagWhat it does
<query>Pod name regex, or kind/name (e.g. deployment/api)
-n, --namespaceNamespace to watch (default: current context)
-c, --containerContainer name regex within each pod
--sinceOnly logs newer than a duration, e.g. 10m, 1h
--tailNumber of prior lines per container (-1 = all)
-o, --outputOutput format: default, raw, json, ppextjson

In CI

Run stern in the background with --no-follow --since 2m to dump recent logs once and exit, instead of streaming forever. Use -o raw when you pipe into a log assertion, since the default prefix breaks line-exact grep.

Common errors in CI

no pods found for the given query means the regex matched nothing in that namespace; check -n and that the workload exists. failed to set up watch: ... Unauthorized means the kubeconfig token expired or the ServiceAccount lacks pods/log. On large clusters --all-namespaces plus a broad regex can hit too many open files; narrow the query.

Using this in CI

A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.

Terminal
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods

# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info

# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes

Frequently asked questions

stern: Tail Pod Logs by Regex in CI?
kubectl logs handles one pod; stern follows a whole Deployment or ReplicaSet by name pattern. In CI it surfaces logs from all replicas while an integration test runs.
What it does?
stern takes a pod query (a regex, or a resource/name like deployment/api) and tails the logs of every matching pod and container at once. Each line is prefixed and colored by pod, so interleaved output stays readable.
In CI?
Run stern in the background with --no-follow --since 2m to dump recent logs once and exit, instead of streaming forever. Use -o raw when you pipe into a log assertion, since the default prefix breaks line-exact grep.
Common errors in CI?
no pods found for the given query means the regex matched nothing in that namespace; check -n and that the workload exists. failed to set up watch: ... Unauthorized means the kubeconfig token expired or the ServiceAccount lacks pods/log. On large clusters --all-namespaces plus a broad regex can hit too many open files; narrow the query.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card