kubectl logs from all pods of a Deployment at once

kubectl logs deployment/NAME reads one pod. On a Deployment with 6 replicas it printed that pod's lines, wrote Found 6 pods, using pod/… to stderr and exited 0. --all-pods (kubectl 1.31 and later) or a label selector with -l reads every pod and prints the lines pod by pod. With -f, kubectl stops at five streams until you raise --max-log-requests.

By Ostgate · Updated

The test

We ran every command below on 10 November 2026 with kubectl client v1.35.0, against an Autopilot cluster on GKE 1.36.4-gke.2377000. The Deployment t9-logs in namespace ostgate-t ran 6 replicas of busybox:1.37, and each wrote the time, its pod name and a counter every 2 seconds. The pods were about 30 seconds old at the first command, 15:33Z.

replicas: 6
selector:
  matchLabels: {app: t9-logs}
command: ["sh", "-c", "i=0; while true; do i=$((i+1)); echo \"$(date -u +%H:%M:%S) $HOSTNAME request $i\"; sleep 2; done"]

kubectl logs deployment/NAME reads one pod

kubectl -n ostgate-t logs deployment/t9-logs --tail=2
15:33:41 t9-logs-65cc449898-8bk9c request 11
15:33:43 t9-logs-65cc449898-8bk9c request 12

On stderr, one line:

Found 6 pods, using pod/t9-logs-65cc449898-8bk9c

The exit code was 0. A log piped into grep or saved to a file holds one replica of six. kubectl port-forward to a Service also settles on a single pod when it starts (port-forward that survives pod restarts).

--all-pods: kubectl 1.31 and later

“Added flag to kubectl logs called --all-pods to get all pods from a object that uses a pod selector” is the release note of kubernetes#124732, merged for v1.31. The flag “Sets prefix to true” (kubectl logs reference), so each line starts with [pod/POD/CONTAINER].

kubectl -n ostgate-t logs deployment/t9-logs --all-pods --tail=1 --prefix
[pod/t9-logs-65cc449898-8bk9c/app] 15:33:45 t9-logs-65cc449898-8bk9c request 13
[pod/t9-logs-65cc449898-dlhnp/app] 15:33:43 t9-logs-65cc449898-dlhnp request 12
[pod/t9-logs-65cc449898-2q6b5/app] 15:33:44 t9-logs-65cc449898-2q6b5 request 12
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:44 t9-logs-65cc449898-5wtcj request 12
[pod/t9-logs-65cc449898-6c8p5/app] 15:33:44 t9-logs-65cc449898-6c8p5 request 12
[pod/t9-logs-65cc449898-9gq8z/app] 15:33:44 t9-logs-65cc449898-9gq8z request 12

We passed --tail=1 here. The reference gives --tail a default of “-1 with no selector, showing all log lines otherwise 10, if a selector is provided”, and we didn't check which of the two --all-pods gets. On pods that have logged for a week, set it yourself.

A label selector with -l

With an older kubectl, pass the labels from the Deployment's spec.selector. A selector matches pods by label alone (kubectl logs reference), so a pod of another workload with the same labels is read as well.

kubectl -n ostgate-t logs -l app=t9-logs --prefix
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:26 t9-logs-65cc449898-5wtcj request 3
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:28 t9-logs-65cc449898-5wtcj request 4
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:30 t9-logs-65cc449898-5wtcj request 5
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:32 t9-logs-65cc449898-5wtcj request 6
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:34 t9-logs-65cc449898-5wtcj request 7
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:36 t9-logs-65cc449898-5wtcj request 8
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:38 t9-logs-65cc449898-5wtcj request 9
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:40 t9-logs-65cc449898-5wtcj request 10

Those are the first 8 of 60 lines. With a selector and no --tail, kubectl printed 10 lines per pod, and each pod's 10 came as one block before the next pod's.

For pods with sidecars, --all-containers reads every container (“Get all containers' logs in the pod(s).”). Our pods had one container each, so we didn't see how extra containers count toward --max-log-requests.

Follow more than five pods with -f

kubectl -n ostgate-t logs -l app=t9-logs --tail=1 --prefix -f --request-timeout=5s
error: you are attempting to follow 6 log streams, but maximum allowed concurrency is 5, use --max-log-requests to increase the limit

Exit 1 and no log lines. The reference describes --max-log-requests as the “maximum number of concurrent logs to follow when using by a selector” and adds “Defaults to 5.”, yet deployment/t9-logs --all-pods --tail=1 -f, with no -l, stopped with the same error. Set the limit to the pod count or higher:

kubectl -n ostgate-t logs -l app=t9-logs --tail=1 --prefix -f --max-log-requests=6 --request-timeout=4s
[pod/t9-logs-65cc449898-9gq8z/app] 15:33:46 t9-logs-65cc449898-9gq8z request 13
[pod/t9-logs-65cc449898-6c8p5/app] 15:33:46 t9-logs-65cc449898-6c8p5 request 13
[pod/t9-logs-65cc449898-8bk9c/app] 15:33:47 t9-logs-65cc449898-8bk9c request 14
[pod/t9-logs-65cc449898-dlhnp/app] 15:33:47 t9-logs-65cc449898-dlhnp request 14
[pod/t9-logs-65cc449898-5wtcj/app] 15:33:46 t9-logs-65cc449898-5wtcj request 13
[pod/t9-logs-65cc449898-2q6b5/app] 15:33:46 t9-logs-65cc449898-2q6b5 request 13
[pod/t9-logs-65cc449898-2q6b5/app] 15:33:48 t9-logs-65cc449898-2q6b5 request 14
[pod/t9-logs-65cc449898-9gq8z/app] 15:33:48 t9-logs-65cc449898-9gq8z request 14

All six pods streamed, in no time order (8 of the 18 lines are shown). We put --request-timeout on these commands only to end the test, and it's why this run exited 1 with error: net/http: request canceled (Client.Timeout or context cancellation while reading body).

How Ostgate does it

On six pods of the same Deployment the pod menu read “5 of 6 pods”. We copied the tab once the 500-line tails and some live lines were in: 2,856 lines, 571 or 572 from each of the five followed pods, and no two consecutive lines from the same pod. One line was 3 ms older than the line above it, where the tails met the live stream.

Logs (All Pods) in the inspector of a Deployment, StatefulSet, DaemonSet or Job, or Show Logs (All Pods) in its row menu, opens one tab for the workload. Ostgate finds the pods by owner, a Deployment's through its ReplicaSets, so a pod that only shares the labels stays out, and during a rollout the pods of an older ReplicaSet are marked “old”. Each pod's stream starts with its last 500 lines. The tab places every line by its full timestamp, nanoseconds included, and after the time comes a pod column: the part of the pod's name after the workload's, such as 65cc449898-8bk9c, in a colour of its own.

Ostgate follows at most five pods at once, the same default as --max-log-requests. With more, it follows the five newest, the pod menu shows the count, and its Follow items change which five. A pod that starts later joins the tab, and one that goes away keeps its lines, greyed.

Symptoms and causes

You seeCauseFix
One pod's lines and Found 6 pods, using pod/… on stderr deployment/NAME resolves to one pod Add --all-pods, or use -l
kubectl doesn't know --all-pods kubectl older than 1.31 -l with the Deployment's selector labels
maximum allowed concurrency is 5 on -f -f over more than 5 pods, with -l or --all-pods --max-log-requests at or above the pod count
10 lines per pod --tail defaults to 10 with a selector --tail with the number you want
Each pod's lines in one block, or out of time order with -f kubectl doesn't sort lines across pods --timestamps to compare the times
Lines from a pod of another workload Its labels match the selector A narrower -l

Questions

How do I get logs from all pods of a Deployment with kubectl?

kubectl logs deployment/NAME --all-pods, in kubectl 1.31 and later, reads every pod the Deployment's selector matches and prefixes each line with the pod and container. With an older kubectl, pass the Deployment's labels: kubectl logs -l app=NAME --prefix. Plain kubectl logs deployment/NAME reads one pod, names it on stderr (Found 6 pods, using pod/t9-logs-65cc449898-8bk9c in our test) and exits 0.

Why does kubectl logs -f fail with “maximum allowed concurrency is 5”?

kubectl follows at most 5 log streams unless --max-log-requests sets a higher number. Following 6 pods failed with “error: you are attempting to follow 6 log streams, but maximum allowed concurrency is 5, use --max-log-requests to increase the limit”, both with -l app=t9-logs and with deployment/t9-logs --all-pods. With --max-log-requests=6 all six pods streamed.

Why does kubectl logs -l show only 10 lines per pod?

With a selector, --tail defaults to 10 lines per pod; without one it defaults to all lines. Pass --tail with the number of lines you want. In our test kubectl logs -l app=t9-logs --prefix printed 60 lines for 6 pods.

Does kubectl merge logs from several pods in time order?

It didn't in our test. Without -f, kubectl logs -l printed each pod's lines as one block, pod after pod. With -f, one pod's 15:33:46 line came after two lines stamped 15:33:47. --timestamps adds the time to each line, so you can at least compare them.

Ostgate runs on Apple Silicon Macs with macOS 15 or later, with a 7-day trial and no sign-up. The Logs tabs are described in the GKE docs, and GKE on a Mac lists what the GKE area does.