# kubectl exec: Usage, Options & Common CI Errors

> kubectl exec runs a command inside a running container. Interactive shells, the -- separator, and the connection-upgrade and no-shell errors in CI.

Source: https://latchkey.dev/learn/command-reference/kubectl-exec  
Updated: 2026-06-25

Run a command - or open a shell - inside a live container.

kubectl exec executes a process in an already-running container. It is how you poke at a live pod from CI: check a config file, hit an internal endpoint, or run a one-off migration.

## What it does

kubectl exec POD -- CMD runs CMD inside the pod's first container; -c selects another. -i keeps stdin open and -t allocates a TTY, so -it CMD gives an interactive shell. Everything after -- is passed verbatim to the container, not parsed by kubectl.

## Common usage

```Terminal
kubectl exec my-pod -- cat /etc/config.yaml
kubectl exec -it my-pod -- sh
kubectl exec -it my-pod -c app -- bash
kubectl exec my-pod -- env | grep DATABASE
```

## Common errors in CI

"OCI runtime exec failed: ... \"sh\": executable file not found" means the image is distroless/scratch and has no shell - exec a static binary the image does ship, or use kubectl debug to attach an ephemeral container with tools. "error: unable to upgrade connection: pod does not exist" usually means the pod already terminated (common when exec-ing into a Job pod that exited). In non-interactive CI, never pass -t: allocating a TTY without a real terminal mangles output and can hang the step.

## Using this in CI

A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.

```Terminal
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods

# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info

# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes
```

> Always set `--request-timeout` in CI. Without it an unreachable API server hangs until the job times out, which turns a thirty-second failure into a twenty-minute one.

## FAQ

### kubectl exec: Usage, Options & Common CI Errors?

kubectl exec executes a process in an already-running container. It is how you poke at a live pod from CI: check a config file, hit an internal endpoint, or run a one-off migration.

### What it does?

kubectl exec POD -- CMD runs CMD inside the pod's first container; -c selects another. -i keeps stdin open and -t allocates a TTY, so -it CMD gives an interactive shell. Everything after -- is passed verbatim to the container, not parsed by kubectl.

### Common errors in CI?

"OCI runtime exec failed: ... \"sh\": executable file not found" means the image is distroless/scratch and has no shell - exec a static binary the image does ship, or use kubectl debug to attach an ephemeral container with tools.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
