Allow only one pod of a type on a node in Kubernetes
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
If you want no more than one pod of a given type on each Kubernetes node, the normal answer is pod anti-affinity. You give the pods a label, then instruct the scheduler not to place two matching pods on the same hostname.
This is a scheduling problem, not a container image problem or a resource limit problem. Kubernetes needs an explicit rule that says matching pods should avoid each other at the node level.
Use Pod Anti-Affinity On kubernetes.io/hostname
The most direct solution is a hard pod anti-affinity rule with topologyKey: kubernetes.io/hostname. That tells the scheduler to treat each node as a separate placement domain.
With enough schedulable nodes, Kubernetes will place one app=api pod per node. If you ask for more replicas than available eligible nodes, the extra pods remain pending.
Required Versus Preferred Rules
There are two forms of anti-affinity. The hard form is requiredDuringSchedulingIgnoredDuringExecution. Use it when colocating two matching pods on one node must never happen.
If you only want a preference, use preferredDuringSchedulingIgnoredDuringExecution:
A preferred rule asks the scheduler to spread pods out when possible, but it will still place multiple matching pods on the same node if the cluster is tight on capacity.
When A DaemonSet Is The Better Answer
Sometimes the real requirement is not “at most one per node” but “exactly one on every eligible node.” If that is what you mean, a DaemonSet is usually the correct workload controller.
A DaemonSet naturally runs one pod on each eligible node, subject to node selectors, taints, and tolerations. That is cleaner than forcing a Deployment to simulate node-local behavior.
Node Affinity Is Different
The file title mentions a pod type on a node, and that often leads people to node affinity. Node affinity selects which nodes a pod may run on. It does not by itself prevent two matching pods from landing on the same node.
If you need both behaviors, combine them:
- node affinity to restrict the eligible nodes
- pod anti-affinity to keep matching pods apart on those nodes
That combination is common for workloads that should run only on GPU nodes, storage nodes, or nodes with a specific compliance label.
How To Verify Placement
After applying the manifest, inspect the scheduled pods:
If a pod stays pending, kubectl describe pod usually includes a scheduler event showing that anti-affinity rules blocked placement. That message is often the fastest way to confirm the rule is working as intended.
Common Pitfalls
- Using a soft preferred rule when the requirement is actually strict.
- Forgetting to put the matching label on the pod template, so the anti-affinity selector never matches.
- Expecting Kubernetes to schedule all replicas even when there are not enough nodes.
- Using node affinity alone and wondering why duplicate pods still land on one node.
- Choosing a Deployment when the workload is really a DaemonSet use case.
Summary
- Use pod anti-affinity to keep matching pods from sharing a node.
- Set
topologyKeytokubernetes.io/hostnamefor one-per-node behavior. - Use
requiredDuringSchedulingIgnoredDuringExecutionfor a hard rule. - Expect pending pods if replica count exceeds the number of eligible nodes.
- Use a DaemonSet when the requirement is one pod on every eligible node.
Related reading
- Allow scheduling of pods on Kubernetes master?
- an error occurred forwarding 9090 - 9090 error forwarding port 9090
- Ansible playbook wait until all pods running
- Approve a CSR in Kuberentes Using the Python client
- Are Kubernetes requests really guaranteed?
- Argo Workflow always using default serviceaccount
- Argocd helm app with multiple value files
- ArgoCD ingress is not reachable

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseSystem Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.