Node Draining and Cordoning in Kubernetes: Taking a Machine Out of Service Without Dropping Anyone
A complete, plain-English guide to cordon, drain, and uncordon: what each one really does, how eviction and disruption budgets protect your applications, why drains get stuck, and how to run safe maintenance and upgrades.
Imagine a hotel that needs to repaint the third floor. The manager cannot simply lock the doors and tell the guests to deal with it. First, the front desk stops giving out rooms on that floor, so no new guests arrive. Then staff politely help the existing guests move to rooms on other floors, a few at a time, making sure the hotel never becomes so crowded that service collapses. Only when the floor is empty do the painters come in. When they finish, the floor reopens. Cordoning and draining a Kubernetes node follow almost exactly this routine. Cordoning is the front desk stopping new arrivals. Draining is the careful, respectful relocation of everyone already staying there.
In this guide we will start from the very beginning. We will recall what a node is and how Kubernetes decides where to place work, and then build up the ideas of cordon, drain, eviction, disruption budgets, and graceful shutdown one step at a time. By the end you will know how to perform maintenance without outages, why drains sometimes hang forever, how cloud platforms and autoscalers use the same machinery, and what mistakes to avoid.
1What Are Cordoning and Draining?
Two small operations that let you retire or repair a machine in a controlled way.
A node is a single machine, physical or virtual, that runs your containers in a Kubernetes cluster. Sooner or later every node needs attention. It may need a new operating system patch, a kernel upgrade, a hardware replacement, a new version of the Kubernetes node software, or simply to be removed because you no longer need that much capacity. Doing any of these while the node is full of running applications would interrupt those applications. Cordoning and draining exist to avoid that interruption.
Cordoning a node marks it as unschedulable. The scheduler, which is the part of Kubernetes that decides where new Pods go, will stop placing new Pods on that node. Importantly, cordoning does not touch anything already running there. Existing Pods carry on exactly as before. Think of it as putting up a “No Vacancy” sign.
Draining a node goes a step further. It first cordons the node, and then asks every eligible Pod on that node to leave, politely and gradually. Pods that belong to a controller, such as a Deployment, are recreated on other nodes by that controller. When the drain finishes, the node is empty of ordinary workloads and safe to work on. Uncordoning is the reverse of cordoning: it removes the “No Vacancy” sign and lets new Pods arrive again.
A road crew repairing a bridge first puts up signs so that no new cars enter the bridge, which is cordoning. Then they guide the cars already on the bridge to the exits, which is draining. Only once the bridge is clear do the workers begin. When the repair is finished, the signs come down, which is uncordoning.
These three operations are the daily bread of anyone who maintains a cluster. Even if you never type the commands yourself, managed upgrades, autoscalers, and automatic repair tools all perform cordon and drain on your behalf. Understanding them helps you design applications that survive these events gracefully.
2Why Nodes Need to Leave Service
Maintenance is not an exception in a cluster. It is a constant, planned part of life.
Nodes do not live forever. Operating systems need security patches. Cloud providers retire underlying hardware. New versions of the node agent bring fixes and features. Teams resize clusters as demand grows and shrinks. Some nodes simply misbehave, with failing disks or flaky networks, and need to be replaced. Because there are so many nodes, these events happen almost every day in a busy organization.
Operating system patching
Security fixes and kernel updates often need a reboot, which would kill every Pod on the machine without preparation.
Kubernetes version upgrades
Upgrading the node agent usually means restarting it and sometimes replacing the whole machine image.
Hardware or instance retirement
Cloud providers and data centers schedule events that will stop or move a machine at a known time.
Scaling the cluster down
When demand falls, extra nodes are removed to save money, and their work must move first.
Troubleshooting a bad node
A node showing odd behavior can be isolated so that no new work lands on it while engineers investigate.
Changing node types or pools
Moving workloads to a different machine size, a different zone, or a newer image requires emptying the old nodes.
The question is never whether a node will be removed. The question is whether the removal will be graceful or abrupt. Cordon and drain are how you make it graceful.
If you simply power off a node without draining it, Kubernetes will eventually notice that the node has stopped reporting, mark it as not ready, and then reschedule its Pods elsewhere. But that discovery takes time, often several minutes, during which users may see errors. A drain moves the work proactively and in a controlled order, so the applications keep serving traffic throughout.
3Foundations You Need First
A short refresher on the building blocks that cordon and drain rely on.
Node
A machine in the cluster that runs Pods. Each node runs an agent called the kubelet that talks to the control plane.
Pod
The smallest deployable unit, holding one or more containers that share a network address and storage.
Scheduler
The control plane component that picks a suitable node for each new Pod.
Controller
A program that keeps the real state matching the desired state, such as keeping three replicas alive.
Taint
A mark on a node that repels Pods unless they carry a matching permission called a toleration.
Eviction
A polite request, made through the API, to terminate a Pod so that it can be rescheduled elsewhere.
The cluster is a hotel chain. Nodes are hotel floors, Pods are guests, the scheduler is the front desk assigning rooms, controllers are the travel agents who make sure each group always has the right number of rooms booked, and a taint is a sign on the door saying “staff only unless you have a pass”.
How Pods Are Normally Placed
When you create a workload, the controller creates Pods, and each new Pod waits without a node. The scheduler examines all nodes, filters out those that cannot host the Pod because of resource shortages, rules, or marks like taints, and then ranks the remaining nodes before choosing one. The key point for us is that a node marked unschedulable is filtered out for ordinary new Pods. That single mark is what cordoning sets.
Controllers Bring Pods Back
A Pod managed by a Deployment, StatefulSet, ReplicaSet, or Job is not precious. If it is removed, its controller notices that the count is short and creates a replacement. The replacement is a brand-new Pod and it is placed by the scheduler on any suitable node, which, after a cordon, excludes the cordoned one. This is why draining works so well: it simply removes Pods and lets the controllers do what they always do.
Draining does not “move” a Pod the way a virtual machine can be live-migrated. A Pod is deleted from one node and a new Pod is created on another. Anything that was only in the old Pod’s memory or local disk is gone, so applications must be designed for this.
4Cordon: Stop New Arrivals
Cordoning is the gentlest operation. It changes where future Pods go, not where current ones are.
When you cordon a node, Kubernetes marks that node as unschedulable. In practice, it sets a flag on the node object and also applies a built-in taint that tells the scheduler to avoid it for ordinary workloads. From that moment, no new Pod will be placed there, unless it is a special kind that tolerates the mark, such as certain system components.
Administrator cordons the node
A request is sent to the API server to mark the node as unschedulable.
Node status shows scheduling disabled
Listing nodes now shows the node as ready but with scheduling disabled.
Scheduler skips the node
All future placement decisions exclude this node for normal Pods.
Running Pods continue untouched
Nothing already on the node is stopped, moved, or restarted.
A restaurant host turns the “reserved” sign on a table. Diners already eating there are not disturbed, but nobody new is seated. The table can be cleared and cleaned once the current diners finish.
When Cordon Alone Is Enough
Investigating a suspicious node
If a node is behaving oddly, cordoning it prevents new work from landing there while you inspect logs and metrics, without disrupting what is already running.
Slow, natural drain-down
For nodes that run short-lived jobs, you can cordon and simply wait. As the jobs finish, the node empties by itself, with no forced eviction at all.
Staging a maintenance window
Cordon several nodes ahead of time so that capacity is already reserved elsewhere, then drain them one by one during the window.
Protecting capacity during an incident
Cordoning prevents a struggling node from being handed even more load while engineers work on the root cause.
Always cordon before you do anything else on a node you plan to touch. Even if you do not intend to drain, cordoning stops the node from collecting new work that you would then have to move.
5Drain: Evict Everyone Politely
Draining is cordoning plus a careful, rule-respecting removal of the Pods.
A drain does two things in sequence. It first cordons the node so that no replacement Pods land there, and then it goes through every Pod on the node and asks each eligible Pod to leave using the eviction mechanism. The word “eviction” here is important, because it is different from simply deleting. An eviction request is checked against the rules you have set for your applications, particularly disruption budgets, and may be refused if granting it would hurt availability. The drain tool keeps retrying until the request is allowed or a time limit is reached.
flowchart TD
S[Start drain on node] --> C[Cordon the node]
C --> L[List Pods on the node]
L --> F{Pod eligible for eviction}
F -->|No| K[Skip or stop with a message]
F -->|Yes| E[Send eviction request]
E --> B{Disruption budget allows it}
B -->|Yes| T[Pod terminates gracefully]
B -->|No| R[Wait and retry]
R --> E
T --> N[Controller creates replacement on another node]
N --> D{More Pods left}
D -->|Yes| F
D -->|No| Z[Node is empty and ready for work]
Which Pods Get Moved and Which Do Not
Not every Pod on a node can or should be evicted. The drain tool applies sensible rules, and stops with an explanation when it meets something it should not touch without your explicit permission.
| Kind of Pod | Default Drain Behavior | Why |
|---|---|---|
| Managed by a Deployment, ReplicaSet, or StatefulSet | Evicted and recreated elsewhere | A controller will bring a replacement |
| Managed by a Job | Evicted; the Job may create a new Pod to finish its work | The Job controller tracks completion |
| Managed by a DaemonSet | Drain stops with a warning unless told to ignore DaemonSet Pods | A DaemonSet would immediately recreate the Pod on the same node, so evicting it is pointless |
| Standalone Pod with no controller | Drain refuses unless forced | Nothing will recreate it, so it would be lost for good |
| Pod using local temporary storage | Drain refuses unless told that losing that data is acceptable | The data lives only on that node and will be deleted |
| Static or mirror Pod | Skipped | These are run directly by the node agent and cannot be removed through the API |
Forcing a drain of standalone Pods without checking what they are. If a Pod was created by hand and nothing manages it, a forced drain permanently deletes it. Always inspect what is on the node first.
6Uncordon: Reopen for Business
Once maintenance is complete, the node needs to be told it may receive work again.
Uncordoning removes the unschedulable mark and the built-in taint. The scheduler then considers the node again for new Pods. It is easy to forget this step, and a forgotten cordon is a classic cause of mysterious capacity problems: the cluster looks as if it has the right number of nodes, yet some are silently refusing work.
Expecting Pods to automatically flow back to a freshly uncordoned node. They will not. Pods that were moved stay where they are. Only new Pods, created later, will consider the node. If you want to rebalance, you must use a rebalancing tool or restart workloads deliberately.
stateDiagram-v2
[*] --> Schedulable: Node is healthy and open
Schedulable --> Cordoned: Cordon applied
Cordoned --> Draining: Drain begins
Draining --> Empty: Pods evicted
Empty --> Maintenance: Patch or upgrade
Maintenance --> Cordoned: Node returns and is checked
Cordoned --> Schedulable: Uncordon applied
Empty --> Removed: Node deleted
Removed --> [*]
Verify Before You Reopen
Before uncordoning, confirm that the node is truly healthy: that its status is ready, that the node agent is running the expected version, that networking and storage plugins are working, and that system Pods on it are healthy. Reopening a node that is only half fixed can cause a new wave of failing Pods. A good habit is to uncordon, watch the first few Pods that arrive, and be ready to cordon again if something looks wrong.
7The Eviction API and How a Drain Really Works
Let us open the hood and follow what happens to a single Pod during a drain.
Kubernetes offers two ways to remove a Pod. Plain deletion removes it immediately, regardless of consequences. The eviction API is a more careful way: it creates an eviction request for the Pod, and the API server checks whether granting it would violate any disruption budget that covers the Pod. If it would not, the Pod is deleted gracefully. If it would, the API server refuses with a “too many requests” style response, which tells the caller to try again later. The drain tool uses eviction for every Pod, which is why drains respect your availability rules.
sequenceDiagram
participant Admin as Administrator
participant Drain as Drain tool
participant API as API Server
participant Kubelet as Kubelet on node
participant Ctrl as Controller
Admin->>Drain: Request drain of node
Drain->>API: Mark node unschedulable
Drain->>API: Evict Pod A
API->>API: Check disruption budget
API-->>Drain: Allowed
API->>Kubelet: Pod A marked for deletion
Kubelet->>Kubelet: Run pre-stop hook and send termination signal
Kubelet->>API: Pod A is gone
Ctrl->>API: Create replacement Pod
Drain->>API: Evict Pod B
API-->>Drain: Refused for now, budget exhausted
Drain->>Drain: Wait and retry
The Life of a Terminating Pod
Marked for deletion
The Pod receives a deletion timestamp and is removed from the lists of ready endpoints so that new traffic stops reaching it.
Pre-stop hook runs
If the Pod defines one, a small action runs first, such as waiting a few seconds for traffic to drain or telling a peer to take over.
Termination signal sent
Each container receives a polite request to shut down, giving the application a chance to finish in-flight work and close connections.
Grace period waits
Kubernetes waits for a configured number of seconds, thirty by default, for the containers to exit on their own.
Forced kill if needed
If a container is still running when the grace period ends, it is stopped forcefully, and any unfinished work is lost.
It is like a shop closing at the end of the day. First the sign flips to “closed” so new customers stop coming in. Then the staff finish serving the people already at the counter. They are given a fixed time to wrap up. Only if someone is still lingering when the time is up does security gently escort them out.
Make your applications listen for the termination signal and shut down cleanly: stop accepting new work, finish current requests, flush buffers, and exit. An application that ignores the signal will always be killed at the end of the grace period, with unpredictable results.
8Pod Disruption Budgets: The Safety Net
A disruption budget tells Kubernetes how much voluntary loss an application can tolerate at one time.
Kubernetes distinguishes two kinds of disruption. Involuntary disruptions are accidents, such as a machine crashing or a network failure. Voluntary disruptions are deliberate actions by an administrator or a tool, such as draining a node for an upgrade. A Pod Disruption Budget, usually shortened to PDB, applies only to voluntary disruptions that go through the eviction API. It says either “at least this many Pods must always be available” or “at most this many Pods may be unavailable at once”.
A hospital must always keep a minimum number of nurses on each ward. Managers can send nurses on training courses, but only if the ward stays above the minimum. A disruption budget is that minimum, enforced automatically.
Minimum available
Specifies how many Pods, as a number or percentage, must remain running and ready during voluntary disruptions.
Maximum unavailable
Specifies how many Pods may be down at once. Often easier to reason about as the application scales.
Selector
Chooses which Pods the budget protects, normally by matching the labels of one application.
Unhealthy Pod policy
Decides whether Pods that are already unhealthy can be evicted freely, which prevents a broken application from blocking maintenance forever.
flowchart LR
A[Eviction request arrives] --> B{Is Pod covered by a budget}
B -->|No| C[Allow eviction]
B -->|Yes| D{Would available count drop below minimum}
D -->|No| C
D -->|Yes| E[Refuse and ask caller to retry]
C --> F[Pod terminates gracefully]
E --> G[Wait for replacement to become ready]
G --> A
Choosing Good Budget Values
The best value depends on how many replicas you have and how much capacity the application needs. For an application with five replicas that can run on three, a budget allowing two unavailable gives drains room to work without risking the service. For a single-replica application, any budget that requires that replica to stay available makes it impossible to drain its node at all, because the one Pod can never leave without breaking the rule. This leads to one of the most common reasons for stuck drains, covered later.
Good Budget Habits
- Run at least two or three replicas of anything that matters.
- Set the budget to leave a little room, so one Pod can always move.
- Prefer the maximum unavailable form, which scales with replica count.
- Match the budget selector exactly to the application’s Pods.
- Combine budgets with readiness checks so replacements count only when truly ready.
Budget Mistakes
- Requiring every replica to stay available, which blocks all drains.
- Applying a budget to a single-replica workload.
- Two overlapping budgets covering the same Pods, which Kubernetes refuses to honor.
- Forgetting that budgets do not protect against crashes, only voluntary actions.
9Taints, Tolerations, and the Unschedulable Mark
Cordoning is built on the same mechanism that Kubernetes uses to repel Pods from nodes in many other situations.
A taint is a label on a node with an effect that discourages Pods. A toleration is a permission slip on a Pod that says “I am allowed on nodes with this taint”. There are three effects. The first prevents new Pods from being scheduled onto the node unless they tolerate it. The second prefers to avoid the node but does not forbid it. The third not only prevents new Pods but also removes existing Pods that do not tolerate the taint.
| Effect | New Pods | Existing Pods | Typical Use |
|---|---|---|---|
| No schedule | Blocked unless tolerated | Unaffected | Cordoning a node, reserving nodes for special work |
| Prefer no schedule | Avoided if possible | Unaffected | Soft reservations |
| No execute | Blocked unless tolerated | Evicted unless tolerated, possibly after a delay | Node failures, forced removal of workloads |
Where Cordon Fits
When a node is cordoned, Kubernetes sets its unschedulable flag and adds a built-in no-schedule taint for unschedulable nodes. Ordinary Pods lack a toleration for it, so they stay away. Certain system Pods, such as those from DaemonSets, carry tolerations for this taint so they can still run on cordoned nodes, which is why per-node agents continue working during maintenance.
Cordon Versus a Custom Taint
Cordon
The simple, standard way to stop new work from landing on a node, understood by every tool in the ecosystem.
No-schedule custom taint
Lets certain Pods still land on the node if they tolerate your taint. Useful for partial maintenance or dedicated nodes.
No-execute custom taint
Forces non-tolerating Pods off the node without going through the eviction API, so disruption budgets are not consulted. Use with great care.
Taints with the no-execute effect remove Pods outside the disruption budget safety net. If you use them to empty a node, you can take down every replica of an application at once. Prefer a drain whenever availability matters.
10Drain Options Explained in Plain Words
The drain tool has a few important switches. Knowing what each does protects you from both surprises and stuck drains.
| Option | What It Does | When to Use It | Risk |
|---|---|---|---|
| Ignore DaemonSets | Lets the drain proceed even though DaemonSet Pods are present, and leaves them running | Almost every drain, since DaemonSet Pods are meant to stay | Low, because those Pods are node-level helpers |
| Delete temporary local data | Allows eviction of Pods that use local temporary storage, deleting that data | When the data is only a cache or scratch space | Data loss if the data mattered |
| Force | Also removes standalone Pods that no controller manages | Only after you have confirmed those Pods are disposable | High, as those Pods are never recreated |
| Grace period override | Overrides each Pod’s own shutdown wait time | When Pods need more or less time than they ask for | Too short a value kills Pods mid-work |
| Timeout | Gives up if the drain has not finished in a set time | In automation, to avoid waiting forever | Leaves the node partly drained |
| Pod selector | Limits the drain to Pods matching certain labels | For partial, targeted evacuation | Node is not fully emptied |
| Dry run | Shows what would happen without doing it | Before every important drain | None |
| Disable eviction | Uses plain deletion that ignores disruption budgets | Only as a last resort in emergencies | Very high, can break availability |
Always preview with a dry run first. It lists the Pods that would be evicted and flags anything that would block the drain, giving you a chance to fix problems before they affect users.
A Careful Manual Routine
Check capacity
Make sure the rest of the cluster has enough free resources to absorb the Pods that will move.
Review what is on the node
List the Pods, noting standalone ones, those with local data, single-replica workloads, and stateful applications.
Cordon and preview
Cordon the node and run a dry run drain to catch problems early.
Drain with sensible options
Run the real drain with a timeout, watching that replacement Pods become ready on other nodes.
Perform the maintenance
Patch, reboot, upgrade, or replace the node.
Verify and uncordon
Confirm the node is healthy, then uncordon it and watch the first Pods that arrive.
11Why Drains Get Stuck
A drain that hangs is one of the most common maintenance frustrations. Almost every case falls into a handful of causes.
Problem
The drain keeps reporting that it cannot evict a Pod because doing so would violate a disruption budget.
Why It Happens
The budget demands that all or nearly all replicas stay available, or the application has only one replica, or other replicas are not yet ready so no capacity can be spared.
Correct Approach
Add replicas, relax the budget to allow one Pod to be unavailable, and confirm that replacement Pods can actually start and become ready on other nodes.
Problem
The evicted Pod stays in a terminating state for a long time and never disappears.
Why It Happens
The application ignores the termination signal and waits for the full grace period, or a finalizer on the Pod is waiting for something that never completes, or the node agent is unhealthy and cannot report that the Pod is gone.
Correct Approach
Handle the termination signal properly, shorten excessive grace periods, investigate any finalizers, and check the health of the node agent.
Problem
Replacement Pods stay pending, so the budget never frees up and the drain waits forever.
Why It Happens
The rest of the cluster lacks free resources, or strict placement rules prevent the Pod from running anywhere else, or a volume is tied to a zone that has no other suitable node.
Correct Approach
Add capacity before draining, review placement rules and zone constraints, and make sure every zone you depend on has enough spare nodes.
Problem
The drain refuses to start, complaining about standalone Pods, DaemonSet Pods, or local storage.
Why It Happens
These are safety checks that protect you from accidental data loss or from evicting Pods that would simply come back.
Correct Approach
Read the message, decide for each case whether the Pod is disposable, and use the matching option deliberately instead of reaching for force by habit.
Problem
The drain is blocked because the application is already unhealthy.
Why It Happens
A broken application has fewer ready Pods than its budget requires, so the budget refuses every eviction, and the broken Pods can never leave.
Correct Approach
Fix the application first, or use the unhealthy Pod policy that allows already unhealthy Pods to be evicted so they do not block maintenance.
When a drain stalls, read its output carefully. It names the Pod it is waiting on and the reason. Then look at that Pod’s budget, its controller, and its events. The cause is almost always visible within a minute or two.
12Special Workloads: Stateful, Single-Replica, and Batch
Not every Pod is a simple stateless web server. Some need extra thought during a drain.
StatefulSets and databases
Pods in a StatefulSet have stable identities and usually their own persistent volumes. During a drain, the Pod is removed, its volume detaches from the old node, attaches to the new node, and the Pod starts again with the same name. This takes longer than for stateless Pods, and the application must be able to rejoin its cluster safely. Disruption budgets are essential here so that a quorum is never lost.
Single-replica applications
An application with only one Pod will have downtime whenever that Pod is evicted, no matter how careful the drain. Accept short downtime, schedule it deliberately, or better, run at least two replicas for anything that must stay available.
Batch jobs and long-running tasks
Evicting a Pod in the middle of a long computation can waste hours of work. Options include cordoning the node and waiting for jobs to finish, designing jobs to save checkpoints, or scheduling maintenance when jobs are idle.
Workloads with persistent volumes tied to a zone
Many storage systems bind a volume to a single availability zone. A Pod using such a volume can only restart in the same zone, so each zone needs spare capacity to host the moved Pod.
Workloads using local disks
Pods that rely on disks physically attached to the node lose that data when moved. They need replication at the application level so another copy exists elsewhere.
Moving a stateless web Pod is like moving a cashier to another till, since any cashier can serve any customer. Moving a database Pod is like moving a surgeon mid-operation: it needs planning, backup staff, and a clear handover.
Draining several nodes at the same time that each hold a replica of the same database. Even with a budget, rapid parallel drains can leave a stateful application without a healthy quorum. Drain nodes one at a time and wait for the application to recover between each.
13Designing Applications That Survive Drains
The best drain is one nobody notices. That depends mostly on how your applications are built.
Run multiple replicas
Two or more replicas mean one can leave while another keeps serving.
Spread across nodes and zones
Use anti-affinity or topology spread rules so replicas do not all sit on the same node, which would make a single drain take out everything.
Set a sensible disruption budget
Allow at least one Pod to be unavailable so drains can make progress, while protecting minimum capacity.
Use accurate readiness checks
A new Pod must only receive traffic once it is truly ready, or users will hit half-started replicas.
Handle the termination signal
Stop accepting new requests, finish existing ones, and exit within the grace period.
Add a short pre-stop delay
A brief wait lets load balancers and routing tables notice that the Pod is leaving before it stops accepting connections.
The Race Between Routing and Shutdown
There is a subtle timing issue. When a Pod is marked for deletion, the system begins removing it from the lists that route traffic to it, but that update takes a moment to reach every proxy and load balancer. If the Pod shuts down instantly, a few requests may still arrive at a Pod that is no longer listening, causing errors. A short delay before shutdown, often a few seconds, gives the network time to catch up so those stragglers are still served.
Pick a grace period longer than your slowest normal request plus the pre-stop delay. Too short and in-flight work is cut off. Too long and drains and rollouts crawl.
14Rolling Upgrades and Managed Platforms
Whenever a cloud platform upgrades your nodes, it is performing cordon and drain behind the scenes.
Managed Kubernetes services and node-management tools automate the routine you just learned. To upgrade a pool of nodes, they typically bring up new nodes with the new version, then cordon and drain old nodes one at a time or in small batches, wait for Pods to settle, and finally delete the empty old nodes. Because they use the eviction mechanism, your disruption budgets are respected, which is why well-defined budgets matter even if you never drain a node by hand.
flowchart TD
A[Start upgrade of node pool] --> B[Add new node with new version]
B --> C[Cordon one old node]
C --> D[Drain the old node]
D --> E{Drain succeeded within time limit}
E -->|Yes| F[Delete old node]
E -->|No| G[Pause or fail upgrade and alert]
F --> H{More old nodes}
H -->|Yes| B
H -->|No| I[Upgrade complete]
| Strategy | How It Works | Strength | Watch Out For |
|---|---|---|---|
| Surge upgrade | Add extra new nodes first, then drain old ones | Capacity never drops, so drains rarely starve the cluster | Temporary extra cost |
| In-place rolling | Drain one node, upgrade it, return it, repeat | No extra machines needed | Capacity dips while each node is out |
| Blue-green node pools | Create a whole new pool, move workloads, remove the old pool | Easy to roll back by keeping the old pool for a while | Doubles capacity during the switch |
| Immutable replacement | Never patch nodes; replace them with fresh images | Clean, repeatable, no configuration drift | Requires strong automation |
Managed platforms often limit how long they will wait for a drain before forcing the node away, or failing the upgrade. A budget that blocks eviction for too long can therefore turn into a forced eviction or a failed upgrade. Check how your platform behaves and make sure your applications can always make progress.
15Autoscalers, Automation, and Reboot Tools
Many tools drain nodes on your behalf. Knowing them helps you predict what will happen to your Pods.
Cluster autoscalers
When demand falls, an autoscaler picks underused nodes, checks that their Pods can fit elsewhere, and removes them after draining. It respects disruption budgets, and it generally avoids nodes holding Pods that cannot be moved, such as standalone Pods or Pods with local storage, unless told otherwise.
Modern node provisioners
Newer provisioning tools continuously look for chances to consolidate workloads onto fewer or cheaper nodes, or to replace old nodes. They cordon and drain nodes as part of this, and they honor disruption budgets and annotations that mark Pods as not to be disrupted.
Automatic reboot daemons
Tools exist that watch for a signal that a node needs a reboot after patching, then safely cordon and drain it, reboot it, and uncordon it, limiting how many nodes are rebooted at once so the cluster stays healthy.
Maintenance operators
Operators can model maintenance as a resource. You declare “this node needs maintenance” and the operator cordons, drains, waits, and later uncordons, recording the progress in status.
Auto-repair features
Cloud platforms can detect unhealthy nodes and replace them automatically, draining first when the node is still responsive and forcing removal when it is not.
Most autoscaling and consolidation tools support a marker, usually an annotation on the Pod, saying “do not remove the node I am on”. Use it sparingly for work that truly cannot be interrupted, because overuse prevents the cluster from ever shrinking.
Controlling the Pace
Automation can drain many nodes quickly. To avoid harm, limit how many nodes can be disrupted at once, add delays between nodes, and run changes in maintenance windows for critical systems. Combining a sensible pace with disruption budgets keeps availability high even during large, fully automatic upgrades.
16Node Shutdown and Failure: When It Is Not Planned
Drain is for planned work. Here is what happens when a node goes away without warning, and how Kubernetes tries to help.
If a node crashes or loses its network, the control plane eventually notices that it has stopped reporting and marks it as not ready. After a waiting period, which is five minutes by default, Pods without a suitable toleration are evicted from the failed node by the node lifecycle controller and recreated elsewhere. This process is slower and rougher than a drain, because the node cannot cooperate: the Pods on it are not given a graceful shutdown.
Graceful node shutdown
When a node is shut down in an orderly way, the node agent can detect it and terminate Pods gracefully, giving ordinary Pods time first and important system Pods a bit more.
Non-graceful shutdown handling
If a node is truly dead but its Pods appear stuck, an administrator can apply a special out-of-service taint so that stateful Pods are force-removed and their volumes released.
Pod priority
During shutdown, critical system Pods are stopped last so that networking and storage remain available as long as possible.
Tolerations for not-ready nodes
Pods can set how long they tolerate a failing node before leaving, trading faster recovery against the risk of reacting to brief hiccups.
A planned drain is like an orderly fire drill where everyone walks out calmly in groups. A node crash is a real fire alarm with the power cut: people eventually get out, but it is slower, noisier, and some belongings are left behind.
Never apply the out-of-service marker to a node that might still be running. If both the old and the new copy of a stateful Pod write to the same data at once, you risk corruption. Use it only when you are certain the node is powered off or isolated.
17Security and Access Control
The power to drain a node is the power to disrupt many applications at once. It deserves careful control.
Cordoning requires permission to update node objects. Draining additionally requires permission to list and evict Pods across namespaces. Anyone who holds these rights can take capacity away from the whole cluster or cause an outage for applications they do not own. In shared clusters, these permissions should be restricted to platform administrators and trusted automation.
Limit who can modify nodes
Reserve node update rights for a small group and for the automation that needs them.
Limit who can evict Pods
Eviction rights in other teams’ namespaces should not be broadly granted.
Audit node operations
Record who cordoned, drained, or uncordoned which node, and when, using the cluster’s audit logs.
Protect critical namespaces
Use admission policies to stop accidental or unauthorized disruption of essential system components.
Use least-privilege automation
Give maintenance tools only the specific rights they need rather than full cluster administrator access.
Review emergency overrides
Options that bypass disruption budgets should be rare, justified, and recorded.
Because Pods can be evicted and then rescheduled anywhere, a malicious or careless user with node control could force sensitive workloads onto nodes they influence. Treat node-level control as a highly privileged capability.
18Monitoring, Logging, and Metrics
You should always be able to see which nodes are cordoned, how a drain is progressing, and how applications are coping.
Cordoned node count
How many nodes are currently unschedulable. A node left cordoned for days is usually a forgotten step.
Pending Pods
A spike during a drain means the cluster lacks capacity to absorb evicted Pods.
Disruptions allowed
For each budget, how many more Pods may be evicted right now. Zero for long periods warns of future stuck drains.
Eviction events and errors
Records of evictions granted and refused, which reveal budget conflicts.
Application health during drains
Error rates, latency, and ready replica counts for applications while nodes are being emptied.
Terminating Pods
Pods that stay terminating for a long time indicate shutdown problems or node trouble.
Alerts Worth Having
Useful alerts include nodes that stay cordoned beyond an expected maintenance window, budgets that allow zero disruptions for an extended time, Pods stuck terminating, pending Pods after a node goes away, and sudden drops in ready replicas of important applications. These alerts catch both forgotten cleanup and hidden design problems before they turn a routine upgrade into an incident.
Add maintenance events to your dashboards as markers on graphs. When latency shifts during an upgrade, you can immediately see which node was being drained and which Pods moved.
19Advantages, Disadvantages, and Trade-offs
Cordon and drain are powerful and safe when used well, yet they come with real constraints.
Advantages
- Maintenance without visible downtime for well-designed applications.
- Respects disruption budgets and graceful shutdown rules.
- Works the same way across clouds, tools, and platforms.
- Allows careful, reversible, step-by-step operations.
- Forms the foundation for automated upgrades and scaling.
- Gives engineers a safe way to isolate a misbehaving node.
Disadvantages and Trade-offs
- Requires spare capacity elsewhere to absorb moved Pods.
- Single-replica and stateful workloads still suffer interruptions.
- Badly designed budgets can stall drains and upgrades.
- Pods lose local data and in-memory state when moved.
- Forgotten cordons silently waste capacity.
Cordon, Drain, and Their Neighbors
| Action | Stops New Pods? | Moves Existing Pods? | Respects Disruption Budgets? | Typical Use |
|---|---|---|---|---|
| Cordon | Yes | No | Not applicable | Isolating a node or preparing for maintenance |
| Drain | Yes, it cordons first | Yes, through eviction | Yes | Safe preparation for maintenance or removal |
| No-execute taint | Yes | Yes, after any delay | No | Forced removal of workloads |
| Delete node object | Node disappears from the cluster | Pods are cleaned up by the control plane | No | Removing a node that is already gone |
| Power off the machine | Not directly | Eventually, after failure detection | No | Not recommended for planned work |
If the node is alive and the work matters, drain it. If the node is already dead, there is nothing to drain, and you let the control plane recover the Pods or remove the node object.
20Best Practices, Anti-Patterns, and Common Mistakes
Habits that make maintenance boring, and traps that make it painful.
Best Practices
- Cordon first, preview with a dry run, then drain.
- Drain one node at a time and let applications recover in between.
- Keep spare capacity so evicted Pods can land immediately.
- Give every important application two or more replicas and a sensible budget.
- Spread replicas across nodes and zones.
- Make applications handle termination signals gracefully.
- Verify node health before uncordoning, and always uncordon.
- Use timeouts in automation so nothing waits forever.
Common Mistakes
- Forcing drains out of habit and deleting standalone Pods.
- Setting budgets that forbid any disruption.
- Draining many nodes at once without checking capacity.
- Forgetting to uncordon after maintenance.
- Assuming Pods return to the node on their own.
- Ignoring local data that will be lost.
- Bypassing eviction to “make it faster” during an upgrade.
Problem
Teams routinely run drains with every override enabled, including force and disabling eviction, so that they never get stuck.
Why It’s Harmful
It removes every safety check, so budgets are ignored, standalone Pods vanish, and applications can lose all replicas at once.
Correct Approach
Use the safest options by default and add an override only after understanding exactly why the drain is blocked and what the override will remove.
Problem
Important applications run as a single replica, protected by a budget that requires it to be always available.
Why It’s Harmful
Every maintenance operation is blocked, so upgrades stall, engineers bypass safety checks, and the node pool slowly falls behind on patches.
Correct Approach
Run multiple replicas, or accept short planned downtime and remove the blocking budget for that workload.
Problem
All replicas of an application are scheduled onto the same node or the same zone.
Why It’s Harmful
One drain or one failure takes out the entire application, and budgets cannot prevent it because the Pods are all on the node being removed.
Correct Approach
Use spread rules and anti-affinity so replicas live on different nodes and zones.
Problem
Applications ignore the termination signal and rely on being killed at the end of the grace period.
Why It’s Harmful
Every drain takes the full grace period per Pod, in-flight requests are dropped, and data may be left half written.
Correct Approach
Handle the signal, finish current work, and exit promptly, with a suitably sized grace period and a short pre-stop delay.
21Frequently Asked Questions
Cordon only stops new Pods from being placed on the node and leaves running Pods alone. Drain cordons the node and then evicts the Pods so they run elsewhere. Cordon is the first half of drain.
Not for applications with multiple replicas, good readiness checks, graceful shutdown, and sensible budgets. Single-replica applications will have a short interruption while their Pod restarts elsewhere.
No. Uncordoning only allows new Pods to be placed there. Existing Pods stay on their new nodes until they are restarted or rebalanced by some other mechanism.
Usually because a disruption budget would be violated. The budget may demand too many available replicas, the application may have too few replicas, or replacement Pods may not be ready yet. Fix the budget, add replicas, or resolve what blocks the replacements.
By default the drain refuses to proceed because of them, since a DaemonSet would just recreate them on the same node. You tell the drain to ignore them, and they remain running, which is normally what you want.
Temporary local storage is deleted when the Pod leaves, so the drain asks for your explicit permission. Data on persistent volumes survives, because the volume is detached and reattached to the new location, subject to zone and storage-system rules.
No. Budgets apply only to voluntary disruptions that go through the eviction mechanism. For crashes, you rely on replicas, spreading across nodes and zones, and fast recovery.
It can be, if the cluster has plenty of spare capacity and applications are well spread, but it is safer to go one at a time, especially for stateful systems. Parallel drains multiply the chance of exhausting capacity or breaking quorum.
Only if you are permanently removing it. For maintenance, keep the node, perform the work, and uncordon it. If your platform replaces nodes rather than patching them, deleting the drained node is the normal final step.
It depends on the number of Pods and their grace periods. Many drains finish in a minute or two. Long drains point to large grace periods, stateful workloads, slow volume movement, or budgets that force waiting. Always set a timeout in automation.
22Summary and Key Takeaways
Cordoning and draining are how you take a node out of service without letting anyone down. Cordoning closes the door to new arrivals. Draining then walks the existing residents out, politely and in order, respecting the rules that keep your applications available. Uncordoning reopens the door when the work is done. Behind the scenes, the same machinery powers managed upgrades, autoscaling, node consolidation, and automatic repair, so understanding it makes you better at designing for the realities of a living cluster.
The safest clusters are not those that avoid maintenance but those whose applications expect it. Run several replicas, spread them out, give them sensible disruption budgets, make them shut down gracefully, keep spare capacity, and monitor the process. With those habits in place, draining a node becomes a calm, routine, almost invisible event rather than a nervous midnight gamble.
Key Takeaways
- Cordon stops new Pods; drain also moves existing ones — cordon alone never touches running Pods, while drain cordons first and then evicts.
- Eviction respects your rules — drains use the eviction mechanism, so disruption budgets and graceful shutdown periods are honored.
- Budgets are a safety net, not a wall — set them to protect minimum capacity while always allowing at least one Pod to move.
- Most stuck drains have a handful of causes — over-strict budgets, single replicas, pending replacements, slow shutdowns, and unmanaged Pods.
- Design for movement — multiple replicas, spreading across nodes and zones, accurate readiness checks, and clean handling of the termination signal.
- Pods do not return after uncordon — and a forgotten cordon quietly wastes capacity, so verify, uncordon, and monitor.
- Treat node control as privileged — restrict who can cordon, drain, and evict, audit the actions, and avoid overrides that bypass safety checks.