Install
# Linux
sudo curl -L -o /usr/local/bin/stern \
https://github.com/stern/stern/releases/latest/download/stern_linux_amd64
sudo chmod +x /usr/local/bin/stern
# macOS
brew install stern
# Via krew (see /tutorials/kubectl-krew-plugins.html)
kubectl krew install stern
# Or via mise
mise use -g stern@latest
stern --version
The basics
# Tail all pods matching a regex in the current namespace
stern . # everything
stern my-app # pods whose name matches "my-app"
stern '.*-canary' # regex
# Specify namespace
stern --namespace prod my-app
stern -n prod my-app
# All namespaces
stern --all-namespaces my-app
# Multiple namespaces
stern --namespaces prod,staging my-app
# Label selector (more reliable than name regex for Deployment pods)
stern -l app=my-app
stern -l 'app in (api, web)'
Each log line is prefixed with: pod name (color-coded), container name (color-coded), timestamp, then the log message. At a glance you can tell which pod / container said what.
Time-range options
# Just the last 5 minutes
stern -s 5m my-app
# Only logs after a specific time
stern --since-time 2026-05-22T14:00:00Z my-app
# Tail only the last N lines (per pod), no historical
stern --tail 100 my-app
Default behavior: get the last hour + follow new logs.
Multi-container, multi-pod
# Multiple containers in the same pod
stern -c "app|sidecar" my-app
# Or all containers (the default; explicit just in case)
stern --container '.*' my-app
# Init containers (default: only main containers)
stern --include-init-containers my-app
Auto-follow rollouts
The killer property: when a new pod matches your selector (new replica spawned during a rollout), stern automatically picks it up. When a pod terminates, it stops tailing that one but keeps tailing the others. Run stern once during a deploy; watch the whole rollout in one stream.
Filter + highlight
# Only lines matching a regex
stern my-app --include 'ERROR|WARN'
# Exclude noisy patterns
stern my-app --exclude 'health|metrics'
# Highlight matches without filtering
stern my-app --highlight 'request_id=<value>'
Output formats
# Default: pod | container | message
stern my-app
# JSON output (for piping into jq)
stern my-app --output json
stern my-app --output json | jq 'select(.message | contains("error"))'
# Raw (just messages, no prefix)
stern my-app --output raw
# Custom template
stern my-app --template '{{.PodName}} {{.Message}}'
Useful patterns
Watch a specific Deployment
# Easier than figuring out the label selector
stern -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx
Tail every pod in a namespace
stern -n my-namespace .
# Prefix is color-coded per pod so you can visually pick threads
Tail across a service mesh during an incident
stern -n prod -l 'tier in (frontend, api, worker)' --since 2m
Catch all errors across the cluster
stern --all-namespaces . --include 'ERROR|panic|FATAL' --since 5m
Tail logs grouped by JSON field (with jq)
stern my-app --output json | jq -r '"\(.timestamp) \(.message)"' | grep request_id=abc123
Worth knowing
- RBAC. stern uses the standard
pods/logpermission; if your kubectl user cankubectl logs, stern works. - Context awareness. stern respects
kubectl's current context + namespace settings. - kubeconfig.
--kubeconfigworks the same as in kubectl. - Performance. Each pod opens a separate connection to the API server; tens of pods are fine, hundreds may strain. For very-large-fleet log aggregation, ship to Loki / VictoriaLogs (see that tutorial) and query there.
stern vs alternatives
- kubectl logs --selector — finally added multi-pod tail in kubectl 1.30+; still less polished than stern. Pick stern for the color-coding, regex filters, and auto-follow.
- k9s (see that tutorial) — has a log view; visual / TUI-shaped; stern is CLI-shaped + composable with pipes.
- Lens / Headlamp — GUI clients with log views; mouse-friendly; not scriptable.
- Loki / VictoriaLogs in Grafana — for historical search across the whole cluster; stern is for real-time tail.
stern's role is the realtime, what-is-happening-right-now log experience. For "I had an error 3 days ago, find the trace," ship to Loki / VictoriaLogs. For "deploy in progress, watch all the pods," stern.
Why this needs to be a separate tool
Kubernetes pod lifecycles are dynamic: pods come and go during rollouts, crash + restart, get evicted + rescheduled. Plain kubectl logs <pod> dies the moment that pod's name changes. stern watches the API for selector-matching pod events and seamlessly attaches to new ones. That's what makes it ergonomic enough to leave running in a terminal pane all day.