stern: Tail Logs Across Multiple Namespaces
stern -A (or --all-namespaces) tails matching pods in every namespace at once, with the namespace shown in each line prefix.
When a request crosses several namespaces (ingress, app, sidecar), watching one namespace hides half the story. stern can span them in a single stream.
What it does
stern reads pods from one namespace by default. -A/--all-namespaces widens it to the whole cluster, and -n can be repeated to name a specific subset. A label selector with -l narrows the match further than the name regex alone.
Common usage
stern -A ingress # every namespace
stern . -n app -n payments # two explicit namespaces
stern -l app=api -A # by label across all namespacesOptions
| Flag | What it does |
|---|---|
| -A, --all-namespaces | Watch pods in every namespace |
| -n, --namespace | Namespace; may be repeated for several |
| -l, --selector | Label selector, e.g. app=api,tier=web |
| --field-selector | Field selector, e.g. status.phase=Running |
| --exclude-pod | Regex of pod names to skip |
Common errors in CI
pods is forbidden: User ... cannot list resource "pods" in API group "" at the cluster scope means -A needs a ClusterRole the CI token lacks; list namespaces explicitly with -n instead. An empty stream with no error usually means the label selector matched nothing; verify with kubectl get pods -A -l <selector>.
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.
# 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