Короткий ответ
cordon помечает узел как непланируемый (Unschedulable), не трогая уже работающие на нём поды, тогда как drain дополнительно корректно выселяет (evict) существующие поды через Eviction API, уважая PodDisruptionBudget, graceful shutdown и terminationGracePeriod, в отличие от аварийного удаления узла, при котором поды просто теряются и пересоздаются только после истечения таймаута обнаружения недоступности узла.
Как это работает подробнее
cordon — это декларативное изменение spec.unschedulable: true у объекта Node, после которого планировщик просто не рассматривает этот узел для новых Pod, но ничего не делает с текущими. drain сначала выполняет cordon, а затем вызывает Eviction API для каждого пода на узле (кроме управляемых DaemonSet и ряда системных), ожидая, что каждый под корректно завершится и будет пересоздан контроллером (Deployment/StatefulSet) на другом узле, при этом соблюдая ограничения PodDisruptionBudget.
Пример кода
kubectl cordon node-3
kubectl drain node-3 --ignore-daemonsets --delete-emptydir-dataЧто использовать на практике
- Практика. перед плановым обслуживанием узла (патчинг ОС, замена инстанса) правильная последовательность —
cordon, затемdrain, затем обслуживание и, при необходимости, удаление узла из кластера; это даёт управляемый, "вежливый" процесс вывода без одновременного исчезновения всех реплик критичного сервиса, если PDB настроен корректно. При аварийной потере узла (например, отказ оборудования) ничего из этого не происходит добровольно — Kubernetes обнаруживает недоступность узла только по истеченииnode-monitoring-grace-periodи дальнейших таймаутов, после чего поды помечаются к пересозданию.
Подводные камни
- Риски. удалять узел из кластера (
kubectl delete node) без предварительного drain, из-за чего под не получает штатного сигнала graceful shutdown; не учитывать, чтоdrainможет "зависнуть", если PDB не позволяет выселить под без нарушенияminAvailable, и требовать либо ручного вмешательства, либо ожидания, пока не появится возможность безопасной эвакуации.