The advice sounds reasonable and it's everywhere: don't put a PodDisruptionBudget on a Knative service, because minAvailable: 1 will block scale-to-zero and you'll lose the thing you adopted Knative for.
It will not block scale-to-zero. It cannot. And that is worse, because people set it expecting protection and get a pod that disappears anyway plus a node they can no longer drain.
Why the autoscaler doesn't care
A PodDisruptionBudget is enforced in exactly one place: the Eviction API. When something calls POST /pods/{name}/eviction, the API server consults every PDB whose selector matches that pod and refuses if the budget would be violated. That is the entire mechanism.
Scaling down is not an eviction. When the Knative Pod Autoscaler decides a revision has no traffic, it writes to the Deployment's scale subresource - replicas: 0 - and the ReplicaSet controller deletes the pods directly. No eviction call, no PDB lookup, no budget check.
So the sequence people expect - PDB says one pod must stay, therefore Knative can't go to zero - never happens. The pod goes away on schedule and the PDB is not consulted at any point.
You can watch this from two terminals if you want to be sure. Send traffic, watch a pod appear, stop traffic, and watch kubectl get pdb report ALLOWED DISRUPTIONS 0 the whole time the pod is being removed underneath it.
What it does block
Node drains, which is precisely what a PDB is for, and precisely the interaction nobody plans for.
Take a service pinned with autoscaling.knative.dev/minScale: "1" because it can't tolerate cold starts, and a PDB with minAvailable: 1 because that's what you always write. There is one pod. The budget allows zero disruptions. kubectl drain on that node calls the Eviction API, gets a 429, retries, and keeps retrying.
Forever. The autoscaler has no reason to add a second pod, because there's no traffic pressure to justify one, and the drain has no way to ask for one. A cluster upgrade rolling through the fleet stops on that node and waits for a human.
That failure has a shape worth recognising: a PDB that permits zero disruptions on a workload that will never scale up on its own is a permanent drain block, and it is silent until the day somebody drains that specific node.
Then there's the revision problem
Even where a PDB is the right tool, Knative's object model fights the way you'd normally write one.
Revisions are immutable. Every configuration change makes a new Revision, each with its own Deployment and its own pod labels:
serving.knative.dev/revision: my-app-00042
serving.knative.dev/service: my-appWrite a PDB against the revision label and it's dead weight the moment you deploy: it now selects a Revision that's scaling to zero while the new one runs unprotected. Keeping up means creating a PDB per deploy and garbage-collecting the old ones, which is a controller nobody wants to own.
Selecting on serving.knative.dev/service covers every revision of a service at once, including both sides of a traffic split, which is usually what you meant. It also means your budget arithmetic has to account for pods across two revisions during a rollout.
Where Knative's availability comes from
For a service that scales to zero, asking "how do I keep a pod available" is the wrong question, because the answer is that there isn't one and that's the design.
Requests to a zero-scaled revision don't fail. They go to the Activator, which buffers the request, tells the autoscaler to scale up, and forwards it once a pod is ready. Your availability during that window is the Activator's availability, not your pod's.
Which is why the PDBs that matter for a Knative install are the ones on Knative's own components, and they already exist. A default install runs the activator, autoscaler, controller and webhook with two replicas, and ships an activator-pdb with minAvailable: 70%. If you're going to spend attention on disruption budgets in a Knative cluster, spend it verifying those survived your install tooling rather than adding new ones to application revisions.
What to do instead
For most services: nothing. Scale-to-zero and the Activator are the availability story, and a PDB adds a drain hazard in exchange for no protection.
For a service that must always be warm, set minScale: 2 rather than 1. Two pods across two nodes give a drain somewhere to move work to, and only then does a budget make sense - written as maxUnavailable: 1 rather than minAvailable: 1, because that shape always permits one disruption regardless of how the replica count moves under you.
If you inherited a cluster and want to know whether this is already waiting for you:
kubectl get pdb -A -o custom-columns=\
NS:.metadata.namespace,NAME:.metadata.name,ALLOWED:.status.disruptionsAllowed \
| awk '$3=="0"'Anything listing zero allowed disruptions is a node drain that will hang. Cross-check those against Knative services with minScale: 1.
The limits worth knowing
PDBs only ever governed voluntary disruptions. A node that dies takes your pod with it whatever the budget says, and no arrangement of PDBs changes that - the guarantee was always about planned maintenance.
Knative also isn't unique here. Any autoscaler that writes the replica count directly, HPA included, moves pods without consulting a PDB. The Knative case stands out because scale-to-zero makes the gap between "budget says one" and "reality says none" a routine daily event rather than an edge case.
And this is Knative Serving 1.23 behaviour. Component defaults, including the activator PDB, are the kind of thing that shifts between releases, so check yours rather than trusting a number in a post.


