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/log permission; if your kubectl user can kubectl logs, stern works.
  • Context awareness. stern respects kubectl's current context + namespace settings.
  • kubeconfig. --kubeconfig works 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.