Tools: Complete Guide to Debugging Distroless Containers: kubectl debug, Ephemeral Containers, and When to Use Each
Debugging Distroless Containers: kubectl debug, Ephemeral Containers, and When to Use Each
Why Distroless Breaks the Normal Debugging Workflow
Option 1: kubectl debug with Ephemeral Containers
Capabilities and Limitations
Accessing the Application Filesystem
RBAC Requirements
Option 2: kubectl debug --copy-to (Pod Copy Strategy)
Limitations
Option 3: Debug Image Variants
Security Considerations
Option 4: cdebug
Option 5: Node-Level Debugging
RBAC and Security
Choosing the Right Approach: Access Profile Matrix
Developer — Local or Development Cluster
Developer — Staging Cluster
Platform Engineer / SRE — Production
Platform Engineer — Production, Node-Level Issue
Common Errors and Solutions
"ephemeral containers are disabled for this cluster"
"cannot update ephemeralcontainers" (RBAC)
"container not found" with --target
Can see processes but cannot read /proc/1/root
tcpdump shows no traffic
Production RBAC Design
Summary Traditional container debugging assumes shell access with standard tools like ps, netstat, and curl. Distroless images intentionally exclude these utilities to reduce attack surface and CVEs. This creates an operational challenge: "when something goes wrong, you cannot use the tools that the process itself is not allowed to run." Kubernetes addresses this through ephemeral containers, stabilized in version 1.25, which enable temporary debug containers to be injected into running pods. The canonical solution uses ephemeral containers to inject a debug container sharing the target pod's network and process namespaces without modifying the original container or restarting the pod. The --target flag shares the process namespace of the specified container, enabling inspection via ps aux and /proc/ access. For network diagnostics, use a richer image: Ephemeral containers provide: Ephemeral containers do not provide: The workaround for filesystem access uses the /proc filesystem: The /proc//root symlink provides read access to the container's filesystem. Ephemeral containers require the pods/ephemeralcontainers subresource permission, separate from pods/exec: In production, scope this tightly with time-limited bindings and approval workflows. The --copy-to flag creates a full pod copy with modifications: This creates a new pod with the container image replaced. Add a debug container alongside the original: The copy strategy does not debug the original pod because: For crash debugging, combine with a modified entrypoint: Maintain a debug variant of your application image including shell tooling. Google distroless images provide :debug tags with BusyBox: Chainguard images follow a similar pattern with :latest-dev variants that include apk and shell: For custom images, use multi-stage builds: Build both targets and push my-app:${VERSION} (production) and my-app:${VERSION}-debug (debug) to your registry. Debug image variants undermine distroless security benefits if deployed to production. Track usage carefully, require explicit approval, and ensure removal after debugging. cdebug is an open-source CLI tool that simplifies ephemeral container debugging: The tradeoff is that it requires third-party tooling installation. For issues that ephemeral containers cannot address—pod crashing too fast, kernel-level problems, or tools requiring elevated privileges—node-level debugging provides direct container access from the host node: From the privileged pod, use nsenter to enter container namespaces: This approach enables running strace and other kernel-level tools: Node-level debugging requires nodes/proxy and ability to create privileged pods. The debug pod runs with hostPID: true and hostNetwork: true, providing visibility into all node processes. Treat this as a break-glass procedure with dual approval, complete audit logging, and immediate cleanup. Goal: Reproduce bugs, inspect configuration, verify service connectivity.
Approach: Debug image variants or cdebug. Speed and iteration take priority. Build the debug variant and deploy it directly, or use cdebug exec for automatic filesystem root access. Goal: Debug integration issues and environment-specific behavior.Approach: kubectl debug with ephemeral containers (--target), scoped to own namespace. Grant developers pods/ephemeralcontainers in their team's namespaces for self-service debugging without ops involvement. Goal: Diagnose live production incidents while minimizing risk.Approach: kubectl debug with ephemeral containers. Ephemeral containers satisfy production requirements: Avoid --copy-to in production incidents because it creates a pod that may not exhibit the issue and adds load during an incident. Goal: Diagnose kernel-level issues, container runtime problems, or multi-pod networking issues.
Approach: Node-level debug pod with nsenter. Treat as break-glass. Create a dedicated RBAC role that grants nodes/proxy access only on-demand with separate authentication and time-limited bindings. Log all access. Ephemeral containers require Kubernetes 1.16+ with the feature gate enabled. They are stable and always-on from Kubernetes 1.25. You have pods/exec but lack pods/ephemeralcontainers. These are separate subresources. The container name in --target must match exactly. Verify with: The ephemeral container may lack CAP_SYS_PTRACE capability. Use the Baseline PodSecurityStandards (PSS) profile for debug namespaces or explicitly add the capability: Use tcpdump -i any to capture on all interfaces including loopback, where inter-container traffic travels. Separate three privilege tiers: Tier 1: Developer self-service (team namespaces) Tier 2: SRE production incident access (all namespaces) Tier 3: Break-glass node access (time-limited binding recommended) Bind Tier 1 permanently to developers. Bind Tier 2 permanently to SREs with audit alerts on use. Bind Tier 3 only on-demand via a Kubernetes operator creating time-limited RoleBindings—never as a permanent ClusterRoleBinding. Distroless containers reduce attack surface and CVEs, forcing a clean separation between application and tooling. Kubernetes provides ephemeral containers and kubectl debug as the clean answer: inject a debug container with necessary tools into the running pod, sharing its network and process namespaces, without restarting or modifying the application. For scenarios ephemeral containers cannot address—filesystem access, crash debugging, kernel-level investigation—the copy strategy and node-level debug fill remaining gaps. The key to scaling this approach is the access model: developers get self-service ephemeral container access in their namespaces, SREs get cluster-wide ephemeral container access for production incidents, and node-level access is a break-glass procedure with audit trail and time limits. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse