KubernetesXLVI · Packet Capture in KubernetesPacket capture
Capture performance, retention, and the cost of seeing every byte
What you'll learn
- Quantify the performance cost of packet capture on a node
- Apply the production patterns for bounded capture cost
- Design a retention policy for pcap and flow-log data
- Choose between wire capture, flow logs, and metrics based on the scale and budget
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
Capture is not free. A tcpdump -i eth0 on a busy node
costs CPU, memory, and disk; the cost scales with the
traffic rate. Production capture bounds the cost with BPF
filters, ring buffers, and time limits; declares the
retention up front; and chooses between wire capture,
flow logs, and metrics based on the scale and budget of
the cluster.
The cost of capture
Wire-level capture with tcpdump has three cost
components:
- CPU: the kernel copies every matching packet from
the NIC driver into the capture buffer. On a 10 Gbps
link with 1 Mpps, this is 1 million copies per second.
Modern NICs with
AF_PACKETand zero-copy (e.g.,tpacket_v3) reduce the cost; on a 1 Gbps link, the cost is typically < 5% CPU. - Memory: the capture buffer is sized by
-B(default 2 MB). With a high packet rate, drops occur if the buffer is too small.tcpdumpreports drops with thedropped by kernelline at the end of the capture. - Disk: the pcap file grows with the capture rate. A 1 Gbps link at full utilization writes ~125 MB/s. A 60-second capture is 7.5 GB.
The production rule: never run an unbounded capture.
Every tcpdump invocation must have a time limit, a BPF
filter, a ring buffer, or a packet count.
Bounding the cost
The standard bounded capture:
# 60-second capture, 100 MB per file, 5 files ring-buffered
timeout 60 tcpdump -ni eth0 -s 0 \
-w /tmp/cap.pcap -W 5 -C 100 \
-B 4096 'tcp and port 8080'
The flags:
timeout 60— kills the capture after 60 seconds. The capture cannot outlive the change ticket.-W 5 -C 100— 5 files of 100 MB each, replacing the oldest. Worst case: 500 MB on the host.-B 4096— 4 MB capture buffer. Reduces kernel drops on busy nodes.'tcp and port 8080'— BPF filter. Cuts the capture rate by 95% on a node that mostly serves other ports.
The BPF filter is the most underused cost control. A node that runs 100 services has 100 candidate capture targets; capturing every packet is 100x more expensive than capturing the one service being debugged.
Capture and the kubelet’s eviction model
A capture that fills the host filesystem triggers kubelet
eviction. The kubelet’s eviction thresholds include
imagefs.available, nodefs.available, and
nodefs.inodesFree. A capture that fills /tmp (often
part of nodefs) trips these thresholds and the kubelet
evicts Pods.
# Substitute the node you are capturing on:
NODE=worker-01
# Check the kubelet's eviction thresholds
kubectl get --raw "/api/v1/nodes/$NODE/proxy/stats/summary" | jq '.node.stats.runtimes.imageFs'
# Check current disk usage on the node
df -h /var/lib/kubelet /tmp /var/log
The production rule: capture to a directory the kubelet does not monitor for eviction, or use a separate volume mounted at the capture point. Most production patterns copy the pcap off the host within minutes of stopping the capture.
Retention policy for pcap and flow data
A pcap file contains every byte the operator captured. In a regulated cluster, that is in-scope data. The production retention pattern:
| Artifact | Retention | Access | Deletion |
|---|---|---|---|
| Per-incident pcap | Duration of incident + 30 days | On-call SRE + incident commander | After postmortem sign-off |
| Calico flow logs | 30 days (Loki retention) | Cluster SRE team | Automated by Loki |
| Hubble flow events | 30 days (Hubble Relay storage) | Cluster SRE team | Automated by Hubble |
| Envoy access logs | 90 days (per compliance) | SRE + security team | Automated by Loki |
A pcap file in /tmp that survives a reboot is a
compliance violation. The standard pattern: copy to a
ticket-attached bucket with retention policy, or delete
within 24 hours.
The cost/visibility ladder
The choice between capture, flow logs, and metrics is a trade-off:
| Tool | Visibility | Cost | Production default |
|---|---|---|---|
| Wire capture (tcpdump) | Every byte | High CPU, disk, retention burden | Last resort for specific bytes |
| CNI flow logs (Calico, Hubble) | L3/L4 metadata + identity | Moderate (eBPF or Felix logging) | Cluster-wide, always on |
| Mesh access logs (Envoy, linkerd-proxy) | L7 request/response | Moderate (sidecar logs) | Cluster-wide, always on |
| RED metrics (rate, errors, duration) | Aggregate per workload | Low (Prometheus storage) | Cluster-wide, always on |
The production rule: always-on observability is RED metrics and CNI/mesh logs. Wire capture is incident-only, bounded, and declared in the change ticket.
Sampling and selective capture
At high traffic rates, even bounded capture is expensive. The patterns that reduce cost further:
- Sampling: capture 1 in N packets (
tcpdump -i eth0 -w /tmp/cap.pcap 'tcp and port 8080' --immediate-modeplus an external sampler). - Triggered capture: start capturing when a metric
crosses a threshold (e.g., 5xx rate > 1%). Tools like
tcpdumpwith a sidecar that monitors metrics can implement this. - Endpoint capture: capture only the traffic to/from a
specific Pod, not the whole node. Cilium’s Hubble can
do this via
hubble observe --pod <pod>. - Snapshot capture: capture a specific moment (the failing request) using an Envoy tap or Istio’s on-demand tap.
The most common production pattern is endpoint capture during an incident: the operator enables Hubble or Envoy tap for the failing workload, captures the specific request that failed, and disables the capture as soon as the incident is resolved.
Quiz
Knowledge check · 4 questions
Q1. An operator runs `tcpdump -i eth0 -w /tmp/cap.pcap` without a time limit, BPF filter, or ring buffer on a busy production node. What is the most likely failure mode?
Q2. Flow logs (Calico, Cilium Hubble) and RED metrics (request rate, error rate, latency) are sufficient for cluster-wide observability without wire-level capture for most incidents.
Q3. Your cluster serves 50 Gbps of east-west traffic. You need to capture a specific intermittent failure in app-a. Design a capture strategy that bounds the cost and declares the retention.
50 Gbps east-west, ~5 Mpps per node. app-a serves 100k req/s. The failure is a 1-in-10000 503 that lasts 5 seconds. The cluster uses Cilium. The change ticket is open. The compliance team requires that pcap data is retained for the duration of the incident plus 30 days.
Q4. Name three mechanisms that bound the cost of packet capture on a busy production node, and one mechanism that ensures the capture is deleted after the incident.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Every capture is bounded. Time limit, BPF filter, ring buffer, or packet count. No unbounded captures on production nodes.
- Capture to a path the kubelet does not evict on. Or copy off the host within minutes of capture.
- Declare the retention path up front. Ticket-attached bucket with automatic deletion, or delete within 24 hours.
- Prefer identity-aware tools for cluster-wide observability. Hubble, Calico flow logs, mesh access logs. Wire capture is incident-only.
- The cost/visibility ladder is the budget tool. RED metrics + flow logs at the bottom (always on); wire capture at the top (incident-only, bounded, declared).