kubectl logs -l: Logs Across Pods by Label
kubectl logs -l <selector> aggregates logs from all pods matching the label, instead of naming a single pod.
A deploy has many replicas; the failing one is rarely the one you guessed. A label selector pulls logs from all of them at once.
What it does
kubectl logs with -l selects every matching pod and streams their logs together. --prefix tags each line with its pod, --max-log-requests raises the concurrent-pod cap (default 5), and --since/--tail bound how much you pull.
Common usage
kubectl logs -l app=api --tail=100 --prefix
kubectl logs -l app=api --since=10m --all-containers=true
# follow a whole deployment, raise the pod limit
kubectl logs -l app=api -f --max-log-requests=20 --prefixOptions
| Flag | What it does |
|---|---|
| -l, --selector | Label selector picking the pods |
| --prefix | Prepend the pod (and container) name to each line |
| --max-log-requests | Max concurrent pods to stream (default 5) |
| --all-containers | Include every container in each pod |
| --since=<dur> / --tail=<n> | Limit by time window or last N lines |
| --previous | Logs from the previous, crashed container |
In CI
Add --prefix so you can tell which replica produced a line, and --tail so a debug step does not dump megabytes. When a selector matches more than --max-log-requests pods, raise it explicitly or kubectl errors out rather than truncating silently.
Common errors in CI
"error: you are attempting to follow ... pods, but maximum number of concurrent logs allowed is 5" means the selector matched more than the default cap; raise --max-log-requests. "No resources found" means the selector matched nothing (wrong label or namespace). For a crashed container use --previous, otherwise you get "previous terminated container ... not found" only if it never restarted.
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