Summary
When a node hosting a Postgres master pod is cordoned, the operator's moveMasterPodsOffNode is supposed to retry finding a Patroni switchover candidate for up to master_pod_move_timeout (default 20m, checked every 1m). In practice it gets exactly one attempt (~4-5s) and then permanently gives up for that node, because retryutil.RetryWorker treats any non-nil error from the retried function as terminal rather than retryable.
If no synced standby exists in that first ~4-second window (e.g. because a replica pod was recreated moments earlier by an unrelated rolling update), the master is never migrated off the node. The node drain then falls back to the plain Kubernetes eviction API, which the Postgres master PodDisruptionBudget (minAvailable: 1, selector spilo-role=master) correctly and indefinitely rejects — since nothing ever moves the master label to another pod. The drain then blocks until an external timeout (e.g. the node-drain timeout used by whatever machine-management layer is orchestrating the drain) forces the node replacement through.
Summary
When a node hosting a Postgres master pod is cordoned, the operator's moveMasterPodsOffNode is supposed to retry finding a Patroni switchover candidate for up to master_pod_move_timeout (default 20m, checked every 1m). In practice it gets exactly one attempt (~4-5s) and then permanently gives up for that node, because retryutil.RetryWorker treats any non-nil error from the retried function as terminal rather than retryable.
If no synced standby exists in that first ~4-second window (e.g. because a replica pod was recreated moments earlier by an unrelated rolling update), the master is never migrated off the node. The node drain then falls back to the plain Kubernetes eviction API, which the Postgres master PodDisruptionBudget (minAvailable: 1, selector spilo-role=master) correctly and indefinitely rejects — since nothing ever moves the master label to another pod. The drain then blocks until an external timeout (e.g. the node-drain timeout used by whatever machine-management layer is orchestrating the drain) forces the node replacement through.