When Identity and Node Placement Matter
Summary
- Most Kubernetes workloads are interchangeable replicas, but some need either a stable per-pod identity or a fixed relationship to the nodes they run on.
- Insight: A Deployment treats its pods as a fungible herd; a StatefulSet treats each pod as a named individual, and a DaemonSet ties pod count to node count.
- Key Concepts: stable identity (name, network, storage that survive rescheduling), ordered lifecycle (predictable start/stop sequence), and node-affinity placement (one pod per node).
- When to Use: Reach for a StatefulSet when peers must find each other by name or own specific data; reach for a DaemonSet when every node needs an agent.
- Limitations/Trade-offs: Both controllers trade the elasticity and simplicity of Deployments for stronger guarantees you must operate carefully.
- Related Topics: StatefulSets, headless Services, DaemonSets, PersistentVolumeClaim templates, storage classes.
Foundations
A Deployment answers one question well: run N identical copies of this Pod and keep them running.
Those replicas are anonymous. Any request can go to any pod, and if a pod dies the ReplicaSet makes a fresh one with a random name.
That model breaks down for two distinct families of workload.
The first family needs identity. A database node is not interchangeable with its peers - it owns a shard of data, holds a role like primary or replica, and other members address it by a fixed hostname.
The second family needs placement. A log collector or metrics exporter has no meaning as "3 replicas somewhere"; it must run exactly once on every node so it can read that node's logs and kernel counters.
Kubernetes ships two purpose-built controllers for these cases: the StatefulSet for identity, and the DaemonSet for placement.
Mechanics & Interactions
A StatefulSet gives each pod a stable ordinal index, starting at zero.
Pods are named <statefulset>-<ordinal>, so a StatefulSet named db produces db-0, db-1, db-2.
That name is durable. When db-1 is rescheduled onto a different node, it comes back as db-1, not as a new random identity.
Paired with a headless Service, each pod also gets a stable DNS record like db-1.db.default.svc.cluster.local, so peers can address one specific member.
Storage is the other half of identity. A volumeClaimTemplates block makes the StatefulSet create one PersistentVolumeClaim per pod, and that claim follows the ordinal, not the node.
So db-0 always re-attaches to its own volume even after it moves hosts. This is how a StatefulSet preserves data across rescheduling.
StatefulSets also sequence their lifecycle by default. Pods are created in order 0, 1, 2 and terminated in reverse, and a pod must be Running and Ready before the next one starts.
A DaemonSet works from the opposite premise: it does not have a replica count at all.
The scheduler places one DaemonSet pod on each node that matches the DaemonSet's node selector and tolerations.
When the cluster autoscaler or Karpenter adds a node, the DaemonSet controller schedules a pod there automatically. When a node is removed, its DaemonSet pod goes with it.
Because DaemonSet pods often need privileged access to the host, they commonly mount host paths, use hostNetwork, or carry tolerations so they land even on tainted control-plane or GPU nodes.
Both controllers still run ordinary containers under containerd via the CRI on each node - the identity and placement logic lives in the control plane, not the runtime.
Advanced Considerations & Applications
Ordered rollout is a double-edged guarantee. It protects quorum-based systems during upgrades, but it also means a stuck db-1 blocks the rollout of db-2 and beyond.
You can loosen this with podManagementPolicy: Parallel when your app tolerates pods starting at once, or with partitioned RollingUpdate to canary the highest ordinals first.
StatefulSets do not delete their PVCs when you scale down or delete the set, by default. That is a safety feature, but it means orphaned volumes accumulate and cost money until you reclaim them.
Kubernetes offers persistentVolumeClaimRetentionPolicy to control whether PVCs are deleted on scale-down or on StatefulSet deletion, which you should set deliberately.
For DaemonSets, the sharp edges are resource pressure and taints. A DaemonSet pod competes for the same node resources as your app pods, so set tight requests and limits so a busy log agent cannot starve tenants.
Critical DaemonSets like CNI plugins and CSI node drivers must tolerate the taints Kubernetes applies to not-ready or cordoned nodes, or networking never comes up.
A useful mental model: a StatefulSet scales along the data axis, a DaemonSet scales along the node axis, and a Deployment scales along the traffic axis.
Common Misconceptions
"StatefulSets make my app highly available." They provide identity and stable storage, not replication or failover. Your application still has to handle leader election and data replication itself.
"I need a StatefulSet because my app writes to a volume." Not necessarily. If each replica is still interchangeable and does not need a stable name, a Deployment with a shared or dynamically provisioned volume can be simpler.
"DaemonSets guarantee a pod on literally every node." Only on nodes that match the selector and where the pod tolerates the node's taints. Control-plane and specialized nodes are often excluded unless you add tolerations.
"StatefulSet pod names are just cosmetic." The ordinal name drives DNS, PVC binding, and rollout order. It is load-bearing, not decorative.
"Deleting a StatefulSet frees its storage." By default it leaves PVCs and their underlying volumes behind. You must set a retention policy or clean them up manually.
FAQs
When should I choose a StatefulSet over a Deployment? When peers must be addressed by stable name, when each replica owns durable data that must survive rescheduling, or when startup and shutdown order matters.
Can a Deployment use persistent storage? Yes, but all replicas typically share a definition and there is no per-pod stable identity or per-pod PVC template. Use a StatefulSet when identity is required.
Do DaemonSets support rolling updates?
Yes. DaemonSets support a RollingUpdate strategy with maxUnavailable so nodes are updated gradually rather than all at once.
How do StatefulSet pods discover each other? Through a headless Service that publishes a stable DNS record per pod, letting each member resolve peers by ordinal hostname.
Is Docker the runtime for these pods? No. Docker is for building images and local development; on nodes, containerd runs the pods through the CRI. StatefulSets and DaemonSets are control-plane concepts independent of the runtime.
What runs a DaemonSet on new nodes automatically? The DaemonSet controller reacts to nodes joining the cluster and schedules a matching pod without any change to a replica count.
Related
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).