kubectl attach: Usage, Options & Common CI Errors
Connect to the container's main process - not a new shell.
kubectl attach hooks your terminal up to the streams of a container's existing main process (PID 1), unlike exec which starts a new process. It is useful for interacting with a program that reads stdin or to watch live output.
What it does
kubectl attach POD connects to the running container's stdout/stderr (and stdin with -i, TTY with -t). Because it attaches to PID 1 rather than spawning a process, it is the right tool when the container runs an interactive program expecting input - and the wrong tool when you just want a shell (use exec for that).
Common usage
kubectl attach my-pod # watch the main process output
kubectl attach -it my-pod # interact with its stdin/TTY
kubectl attach -it my-pod -c app # a specific containerCommon errors in CI
attach is rarely right for CI: with no TTY, -t hangs the step, and attaching to a process that ignores stdin gives you nothing useful. "unable to upgrade connection" means the SPDY/websocket upgrade to the kubelet failed (network policy, proxy stripping the upgrade header) - the same cause as the exec variant. The detach sequence is Ctrl-P Ctrl-Q, not Ctrl-C (which would signal the process); a script that pipes Ctrl-C to "detach" actually kills PID 1 and the pod. Prefer kubectl logs -f for non-interactive output and exec for shells.
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.
# 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