When a Pod starts dropping traffic, the traditional move is to stop it, attach tcpdump, redeploy, and hope the failure repeats. But in managed Kubernetes, every restart erases the exact state that caused the problem: conntrack table, NAT rules, neighbor cache, socket memory, iptables jump history, and load balancer backend selection. Instead, you can use eBPF to debug Kubernetes networking without restarting. Live packet tracing with bpftool on EKS and GKE gives you a direct view of packets as they pass through the host kernel while the workload and its flows remain completely untouched.
Why Restarting Is No Longer a Debugging Strategy
Kubernetes restarts are expensive in more ways than scheduling downtime. A restart creates a new network namespace, resets conntrack state, and destroys the exact socket-level evidence you need for diagnosing intermittent connectivity. This is especially painful in production where an issue appears only after a Pod has accumulated long-lived TCP sessions, custom route rules, or specific connection marks.
eBPF changes this by moving the debugger into the kernel. Because eBPF programs run inside the kernel’s tracing infrastructure, they can observe packets, socket buffers, and network functions in real time. They do not alter the kernel’s decision-making path, so they do not trigger the side effects that tcpdump or a Pod restart would. For Kubernetes engineers, this means the failure state stays intact while you inspect it.
bpftool: A Low-Level Escape Hatch for Managed Clusters
Managed Kubernetes platforms now ship with a rich set of observability layers. GKE Dataplane V2, AWS VPC CNI, Cilium Hubble, and Tetragon all provide high-level insights like flow logs, identity-aware telemetry, and policy verdicts. But when those layers report a drop without telling you exactly where the packet disappeared, you need a tool that speaks directly to the kernel.
That tool is bpftool. It is the command-line interface for inspecting eBPF programs, maps, and links on a live node. It can list the BPF programs attached by the CNI, dump raw kernel trace output, and load small precompiled BPF objects into the running kernel. It is deliberately low-level, which is exactly what makes it useful for narrowing a networking problem to a specific function or tracepoint.
In 2026, bpftool remains the simplest way to ask the kernel a direct question: was this packet freed, and for what reason? You do not need to wait for a vendor dashboard to aggregate data, and you do not need to redeploy anything.
Live Packet Tracing Without Touching the Workload
The core pattern for live packet tracing with bpftool is to attach a tracing program to a network tracepoint, stream the output, and correlate it with Kubernetes identities. Common tracepoints include netif_receive_skb, netif_xmit_skb, and kfree_skb. The last one is particularly useful because kfree_skb is called when a socket buffer is freed, which often marks the exact instant a packet is dropped.
A minimal workflow looks like this:
# Load a precompiled BPF object that hooks kfree_skb bpftool prog load /opt/drop-trace.o /sys/fs/bpf/drop-trace # Stream kernel trace pipe output bpftool trace
The precompiled drop-trace.o contains a small eBPF program that sends packet metadata to the trace pipe. Once loaded, it records events such as interface index, protocol, packet length, and, on newer kernels, the drop reason. The target Pod is never restarted. No container is recreated, no CNI plugin is reloaded, and no socket is closed.
Where to Run bpftool on EKS and GKE
On both EKS and GKE, bpftool needs access to the host network namespace and sufficient capabilities to load programs. The easiest approach is to run a dedicated debug Pod on the same node as the failing workload. You do not need to enter the workload’s container, which keeps the application environment clean.
On EKS, you can use a single-node DaemonSet or a Kubernetes ephemeral debug container. The debug Pod should include hostNetwork: true, hostPID: true, and the security capabilities CAP_BPF and CAP_PERFMON. If the node image uses an older kernel without those capability names, privileged mode is still accepted but less refined. Either way, the bpftool Pod itself can be started and stopped freely without affecting the network stack of the Pod you are investigating.
On GKE, the Container-Optimized OS nodes are well suited for eBPF because the kernel exposes BTF, which bpftool uses for reliable program loading. GKE Dataplane V2 already runs eBPF programs in the host kernel, so the node has the required infrastructure. Run a bpftool DaemonSet only on the target node by using node affinity or a single-replica Deployment matched to the node name. If your bpftool image does not include the right library paths, mount /sys/fs/bpf and /sys/kernel/debug from the host into the debug container.
Reading the Output: From Kernel Trace to Kubernetes Traffic
Raw bpftool output does not show Pod names or Kubernetes services. It shows kernel objects: network interface indices, packet addresses, and drop reasons. To make that output useful, you need to correlate it with the cluster’s view of the network.
Start with the interface index from the trace event. Every Pod on the node connects to a veth interface whose host-side index appears in the event. Use the ip command to map that index to the interface name, then match it with the Pod’s IP address:
ip -j link show kubectl get pods -n production -o wide --field-selector spec.nodeName=your-node-name
Once you know which interface belongs to which Pod, the trace output becomes a targeted network story. A kfree_skb event with protocol=0x0800 and a drop reason like NO_SOCKET can point to a Service backend that no longer has a matching socket. A drop reason of NEIGH_UNREACHABLE can expose an ARP or neighbor discovery issue on the node. Correlate that with the Pod’s IP address inside the service endpoint list, and you can identify whether the problem is in the backend Pod, the kube-proxy path, or the CNI policy chain.
Common Kubernetes Network Failures That Show Up in bpftool
Live packet tracing with bpftool is especially effective for intermittent failures that disappear after a restart. Here are a few patterns you can recognize in the trace stream.
- Service traffic dropped after scale-down: A backend Pod is removed, but a stale connection still routes to its IP. The trace shows a drop reason associated with
NO_SOCKETorNO_ROUTE. - DNS timeouts: CoreDNS replies are dropped near the local UDP socket, often because forward policies or conntrack entries have become stale. bpftool shows the DNS packet being freed immediately after arriving from the pod interface.
- Network policy misclassification: On GKE Dataplane V2, eBPF-based policy enforcement can drop packets before they reach the application. Tracing the relevant CNI eBPF program output can reveal whether the packet was rejected in policy enforcement rather than by the service layer.
- Pod-to-Pod connectivity failure across nodes: Packets reach the destination node but are freed before being delivered to the veth interface. The drop reason often indicates a host routing or forwarding issue.
When you identify a drop reason, you can then attach a second BPF program to the specific kernel function named in the trace. This converts a vague “connection timed out” report into a precise function call stack that tells you which layer in the network stack rejected the packet.
The Limits of bpftool as a Cross-Cluster Debugger
bpftool is surgical, not comprehensive. It shows events on one node at a time, and it does not aggregate traces across an entire EKS or GKE cluster. For multi-node flow analysis, you should still rely on Hubble or platform logging. But when you need to understand what the kernel did with a packet at a given instant, bpftool is faster and more precise than restarting a Pod or waiting for a second occurrence.
Another limitation is that bpftool is not a packet sniffer. It does not reconstruct application payloads, nor does it decrypt or decode protocols beyond what the kernel tracepoint exposes. Use it as a layer 3 and layer 4 triage tool, not as a replacement for application-level tracing. The value is in the drop reason and the location at which the packet was freed, not in the body of the packet itself.
Conclusion
Live packet tracing with bpftool on EKS and GKE turns kernel-level visibility into a day-to-day debugging tool for Kubernetes networking. Instead of restarting workloads and losing the evidence, you can attach a tracing program to a live kernel, stream the exact packet drop events, and correlate them with Pods and services in a few minutes. As eBPF becomes the default packet path in managed Kubernetes, bpftool remains the most direct way to ask the running kernel what it did with a packet—without disrupting the production traffic you are trying to save.
