kubectl cordon & uncordon: Usage & Common CI Errors
Stop new pods landing on a node, without evicting the running ones.
kubectl cordon flags a node SchedulingDisabled so no new pods get placed there; uncordon makes it schedulable again. They are the bookends around drain and node maintenance.
What it does
kubectl cordon NODE sets spec.unschedulable=true: existing pods keep running, but the scheduler will not assign new ones. kubectl uncordon NODE clears it. cordon is the non-disruptive half of drain - drain cordons and then evicts, while cordon alone just blocks future placement.
Common usage
kubectl cordon ip-10-0-1-5 # no new pods land here
kubectl get nodes # shows SchedulingDisabled
kubectl uncordon ip-10-0-1-5 # allow scheduling againCommon errors in CI
The classic automation bug is a forgotten uncordon: a maintenance job cordons a node, the step that should uncordon it fails or is skipped, and new pods pile up Pending with "0/N nodes are available: N node(s) were unschedulable". Always uncordon in a trap/finally block. Cordoning enough nodes without capacity elsewhere also strands pods in Pending. Check cluster headroom first. Cordon is idempotent, so re-running it in a retried pipeline is safe.
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