kubectl port-forward: Usage, Options & Common CI Errors
Tunnel localhost straight into a pod or service.
kubectl port-forward opens a tunnel from a local port to a port inside a pod or service, without an ingress or LoadBalancer. In CI it is handy for smoke-testing a freshly deployed service before exposing it.
What it does
kubectl port-forward TARGET LOCAL:REMOTE forwards traffic from localhost:LOCAL to REMOTE on the target pod (or a pod behind a service). It runs in the foreground and holds the tunnel open until interrupted. --address changes the bind interface.
Common usage
kubectl port-forward pod/my-pod 8080:80
kubectl port-forward svc/web 8080:80
kubectl port-forward deploy/web 5000:5000 & # background in CI
# ... run tests against localhost:5000 ...
kill %1 # tear the tunnel downCommon errors in CI
The race is the killer: port-forward returns "Forwarding from 127.0.0.1:8080" before the pod is actually Ready, so an immediate curl hits "connection refused". Gate on readiness first - kubectl wait --for=condition=Ready pod/X - then start the tunnel, and poll the local port until it answers. "an error occurred forwarding ... lost connection to pod" means the pod restarted mid-tunnel; port-forward does not reconnect, so wrap test runs to retry establishing the tunnel. In CI, background the process and always kill it in a trap so the step does not hang.
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