Skip to content

Build1 publisher2 min readPublished

The eviction API is the only path a PodDisruptionBudget can block

Gremlin's walkthrough stalls a node drain after evicting one of four nginx replicas. The same budget leaves the Deployment controller and the Horizontal Pod Autoscaler free to delete pods directly, because they never call eviction.

The Engineer · Build desk

Illustration accompanying The eviction API is the only path a PodDisruptionBudget can block

What happened

  • Gremlin's post puts node drains, cluster autoscaler consolidation and pod migration to free a resource in the voluntary disruption class, the class a PodDisruptionBudget governs.
  • PDBs are enforced through the eviction API; the Deployment and StatefulSet controllers and Horizontal Pod Autoscalers delete pods directly and are not limited by a budget.
  • In the walkthrough's four-node cluster no topology spread constraints were set, the scheduler put three of the four nginx pods on one node, and draining it without a PDB would lose three quarters of the deployment.
  • With a budget applied, the drain evicted one pod and then stalled while Kubernetes scheduled a replacement on another node, resuming only once the new replica reported Ready.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint A budget caps only what eviction can remove, so a team relying on PDBs for update safety is protected against drains and autoscaler consolidation and nothing else.
  • contradiction Anyone copying the example manifest inherits a two-pod budget on a four-replica service whose stated floor is three, so the object exists and the SLO is still unenforced.
  • cost Once a PDB is in place, maintenance is paid for in wall-clock time: the operator's drain blocks until a replacement pod comes up and passes readiness elsewhere.
  • exposure Because an empty selector matches the whole namespace, one team's copied PDB can block drains for pods it does not own.

Read the example against its own requirement. The post runs an nginx deployment at four replicas and says it needs at least three available to hold a latency SLO [7]. The manifest it walks through caps unavailability at two [14]. desiredHealthy is expectedPods minus maxUnavailable [11], so four minus two is two, and that budget permits the service to fall to two available pods, one under the stated floor [17]. minAvailable: 3 is the field that expresses the requirement [8]. The status output printed in the post fits minAvailable: 3: it reports disruptionsAllowed of 0 at currentHealthy of 3 [14], where a desiredHealthy of 2 would still allow one disruption [18].

Percentages are accepted as strings, in the form maxUnavailable: "50%" [8]. At four replicas that is the same two pods as the absolute value [23].

Two defaults are worth checking before the manifest goes in. unhealthyPodEvictionPolicy defaults to IfHealthyBudget, which permits an eviction only when currentHealthy is at or above desiredHealthy; the alternative, AlwaysAllow, permits it regardless [10]. Under the default, a deployment already below desiredHealthy allows zero evictions, so a drain aimed at its node waits until the deployment recovers [19]. The selector is the other one: leave it empty and the PDB matches every pod in the namespace [9].

None of this touches the involuntary class. Hardware failures, out-of-memory evictions and cloud provider outages arrive without an eviction call, and a PDB restricts only what a voluntary disruption can take out [2][3]. Kubernetes has no way of knowing which pods you cannot afford to lose; ask it to drain a node and it evicts everything on the node [6].

Gremlin's stated scope is why PDBs matter, the risk of skipping them, and how to find deployments that have none defined [15]. According to the post, consolidating nodes after a traffic spike can take an application offline if it is not done carefully [21]; the post does not put a number on how often that happens. It does say the object takes only a few lines to write, and that choosing the parameters is the hard part [22]. On the clusters I work with, where the autoscaler consolidates on its own schedule, I set minAvailable from the SLO and then read expectedPods and desiredHealthy back out of kubectl get pdb -o yaml before believing it [11].

What to watch

  • Whether the rest of the post's method for listing Deployments with no matching PDB also covers StatefulSets.
  • Whether the example manifest gets corrected to minAvailable: 3, the budget its printed status output actually describes.
  • How long a cluster autoscaler keeps retrying a consolidation that a PDB blocks before it abandons the node.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories