A running Kubernetes pod uses a minimal image with no shell and must not be restarted. How do ephemeral containers created with kubectl debug help, and what does the --target flag change?
answer
- ephemeralcontainers subresource, no restart
- shares net + IPC, not filesystem
- --target = shared PID namespace
- /proc/1/root to read target files
- cannot be removed; --copy-to for dead pods
basics
~20 skubectl debug -it POD --image=busybox --target=app adds an ephemeral container to the live pod, giving you tools without a restart. It shares the pod network; --target additionally shares the target container's process namespace so you see its processes and files via /proc.
solid answer
~50 s`kubectl debug -it mypod --image=busybox:1.36 --target=app -- sh` adds an **ephemeral container** through the pod's `ephemeralcontainers` subresource. The pod is not recreated and no existing container restarts, so the failure state is preserved. The debug container joins the pod's network and IPC namespaces, so `curl localhost:8080` hits the app. It has its **own root filesystem** — the tool image — so it cannot see the app's files by default. `--target=app` requests process-namespace sharing with that container (runtime support required), which lets you run `ps`, send signals, attach a profiler, and reach the app's files as `/proc/1/root/...`. Constraints: ephemeral containers cannot be removed once added (only deleting the pod clears them), have no resource requests, probes, ports, or restarts, and cannot be declared in a Deployment. `--profile` selects a security profile such as `restricted`, `netadmin`, or `sysadmin`. If the pod is not running, use `--copy-to` to debug a modified copy.
code
bash · 5 lineskubectl debug -it mypod --image=busybox:1.36 --target=app -- sh
# inside:
ps -ef
cat /proc/1/root/etc/app/config.yaml
wget -qO- localhost:8080/healthzgo deeper
Know the command and that it adds a temporary tool container to a live pod without restarting it.
Explain which namespaces are shared by default, exactly what --target changes, and the /proc/1/root trick for reading the target's files.
Cover the constraints — irremovable, unbudgeted resources, Pod Security profiles — and know when to switch to --copy-to and what fidelity you lose.
Decide policy: which images and identities may attach debug containers, which debug image is approved, and how the ability is audited and time-boxed.
## The problem they solve Hardened images (distroless, `scratch`) carry no shell, `curl`, `ps`, or `netstat`, so `kubectl exec` is useless on them. The old workaround — redeploy with a fat image — destroys the very state you wanted to inspect. **Ephemeral containers** (stable since Kubernetes 1.25) let you add a temporary, tool-bearing container to a pod that is already running. ## How kubectl debug uses them `kubectl debug -it mypod --image=busybox:1.36 --target=app -- sh` patches the pod's `ephemeralcontainers` subresource. The kubelet starts the new container in the existing pod sandbox. Nothing restarts, the pod keeps its IP and node, and existing containers are untouched. What the debug container shares automatically is the **pod-level** namespaces: network and IPC. That means `localhost` is the app's localhost — `curl -v localhost:8080/healthz`, `ss -lntp`, and DNS checks with `nslookup` all behave as they would inside the app container. What it does **not** share is the filesystem. Each container has its own root filesystem from its own image, so `/app` inside your busybox container is busybox's `/app`, not the application's. Nor does it see the app's processes by default, because each container has its own PID namespace. ## What --target adds `--target=app` asks for **process namespace sharing** with the named container. The debug container then runs in the same PID namespace, so: - `ps -ef` lists the application's processes with their real arguments and PIDs. - You can signal them (`kill -QUIT 1` to force a JVM thread dump) or attach tools by PID. - You can read the target's filesystem through `/proc/<pid>/root/`, typically `/proc/1/root/etc/app/config.yaml`, because /proc exposes each process's mount namespace root. This depends on container-runtime support; containerd and CRI-O support it, and a runtime that does not will make the flag unhelpful. Note the direction: a shared PID namespace means the target can also see your processes, and signals cross the boundary — be careful with `kill`. ## Constraints to state out loud - An ephemeral container **cannot be removed or restarted**. It stays in the pod spec until the pod is deleted, so a pod you debugged is effectively marked; plan to replace it afterwards. - It has no resource requests or limits, no readiness/liveness probes, no ports and no lifecycle hooks, and cannot be declared in a Deployment — it is a debugging-only API. - It does not fix an unschedulable or crash-looping pod: the pod sandbox must exist and be running. - Security context is not inherited. `--profile` (legacy, general, restricted, netadmin, sysadmin) sets it; on a namespace enforcing the `restricted` Pod Security Standard, a sysadmin-profile debug container is rejected. ## The copy variant When the container will not stay up, or you need a different command or image, use a copy instead of a live attach: `kubectl debug mypod --copy-to=mypod-debug --set-image=app=busybox --share-processes -- sleep 1d` This creates a **new pod** based on the original spec with your overrides, leaving the original alone. `--share-processes` sets `shareProcessNamespace: true` across the copy. The trade-off is honest: a copy is not the failing instance — it has a new IP, is not behind the Service's endpoints, and may simply start fine. Delete copies when you are done.
- Why can a debug container reach the application on localhost but not read its /etc directory?Network and IPC namespaces are pod-level and shared by every container in the pod, so localhost and ports are common. The mount namespace and root filesystem are per-container and come from each container's own image, so files are not shared unless a volume is mounted into both. Process-namespace sharing via --target gives an indirect path through /proc/<pid>/root.
- What are the operational consequences of adding an ephemeral container to a production pod?The addition is permanent for that pod's lifetime and cannot be undone, it appears in the pod spec and audit log, and the container consumes node CPU and memory without requests, which can push a tight node over its allocatable capacity. Treat the pod as no longer pristine and recycle it after the incident.
saying these in an interview costs you the question
- Claiming kubectl debug restarts the pod or the target container
- Expecting the debug container to see the app's files without --target or a shared volume
- Thinking an ephemeral container can be deleted from a running pod
- Using ephemeral containers on a pod stuck in Pending or CrashLoopBackOff and expecting it to work
- Declaring ephemeral containers in a Deployment manifest