When to Use Kubernetes Deployments, StatefulSets, or DaemonSets in Production
Choose Deployments for stateless horizontally-scalable services, StatefulSets for stateful applications requiring stable network identities and ordered startup, and DaemonSets for node-level agents that must run on every node.
Selecting the appropriate Kubernetes workload controller is critical for production stability and scalability. According to the bregman-arie/devops-exercises repository, the choice between Deployments, StatefulSets, and DaemonSets depends on three core characteristics: statefulness, pod identity requirements, and node distribution patterns. Understanding these differences ensures your applications run efficiently while maintaining data integrity and high availability.
Understanding the Three Primary Workload Controllers
Deployments for Stateless Services
Use Deployments for stateless or loosely-coupled services where pods can be freely recreated without data loss. As documented in topics/kubernetes/README.md at line 726, Deployments provide declarative rollout, rollback, and horizontal scaling capabilities ideal for front-end APIs, web applications, and microservices. Each replica is interchangeable, and the normal scheduler distributes pods across nodes based on selectors, affinity rules, and taints/tolerations without guaranteeing specific placement.
StatefulSets for Persistent Identities
Choose StatefulSets when your workload requires stable network identities, ordered startup/termination, and persistent storage. The topics/kubernetes/README.md file at line 1112 explains that StatefulSets guarantee a stable ordinal index (0…N-1) and unique hostnames, which is essential for databases like PostgreSQL, Cassandra, or clustered services like Kafka and ZooKeeper that require leader election or quorum formation. Each pod maintains its own PersistentVolumeClaim, ensuring data survives rescheduling.
DaemonSets for Node-Level Coverage
Deploy DaemonSets when you need exactly one pod per node (or per nodes matching specific selectors). As described in topics/kubernetes/README.md at line 720, DaemonSets are designed for node-level agents such as log collectors (Fluentd), monitoring exporters (Prometheus node-exporter), or networking plugins (CNI). These pods are typically stateless, using hostPath volumes or external storage rather than PersistentVolumeClaims, and run independently without ordering guarantees.
Decision Criteria for Production Workloads
Statefulness and Storage Requirements
- Stateless/Loosely-coupled: Choose Deployments when pods hold no persistent identity or data and can be replaced arbitrarily.
- Stateful with Stable Storage: Choose StatefulSets when each pod must maintain unique state via PersistentVolumeClaims and requires persistent identity across rescheduling.
- Node-local State: Choose DaemonSets for agents that access node-local resources (logs, system metrics) but do not require persistent pod-specific storage.
Pod Identity and Ordering Guarantees
- Interchangeable Replicas: Deployments treat all pods as identical; any pod can handle any request, and ordering is not guaranteed during scaling.
- Ordinal Index and Hostname Stability: StatefulSets assign predictable names (e.g.,
pg-0,pg-1) and respect creation/termination order, crucial for cluster formation protocols. - Per-Node Independence: DaemonSets create pods named after the node itself, with no ordering constraints between different nodes.
Node Distribution Patterns
- Scheduler-Based Placement: Both Deployments and StatefulSets rely on the Kubernetes scheduler for placement decisions, allowing complex affinity and anti-affinity rules.
- Mandatory Per-Node Execution: DaemonSets bypass the standard scheduler to ensure execution on every selected node, making them ideal for infrastructure-level services that must run regardless of resource constraints.
Practical Implementation Examples
The bregman-arie/devops-exercises repository provides concrete manifest examples in topics/kubernetes/exercises/kustomize_common_labels/ and related sections. Here are production-ready patterns:
# Deployment – Stateless web service (nginx)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
# StatefulSet – PostgreSQL with persistent storage
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: pg
spec:
serviceName: "pg"
replicas: 2
selector:
matchLabels:
app: pg
template:
metadata:
labels:
app: pg
spec:
containers:
- name: postgres
image: postgres:13
volumeMounts:
- name: pgdata
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: pgdata
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
# DaemonSet – Node-level log collector
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
containers:
- name: fluentd
image: fluent/fluentd:v1.11
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log
Decision Workflow for Engineers
Follow this three-step process from the devops-exercises analysis to select the correct controller:
-
Does the workload require stable pod identity or persistent storage?
- Yes → StatefulSet
- No → Continue to step 2
-
Must a pod run on every node (or a specific subset of nodes)?
- Yes → DaemonSet
- No → Continue to step 3
-
Is the workload stateless and horizontally scalable?
- Yes → Deployment
Summary
- Deployments manage stateless applications where pod replacement does not affect service integrity, offering simple scaling and rolling updates as shown in
topics/kubernetes/exercises/kustomize_common_labels/deployment.yml. - StatefulSets provide guaranteed ordering, stable network identities, and persistent storage for applications like databases and message queues, documented at line 1112 of the main README.
- DaemonSets ensure node-level coverage for infrastructure agents like log shippers and monitoring tools, detailed at line 720 of the repository's Kubernetes documentation.
- The
topics/kubernetes/CKA.mdfile provides additional troubleshooting context for these workload controllers.
Frequently Asked Questions
Can I use a Deployment instead of a StatefulSet for a database?
No, using a Deployment for a database risks data loss and split-brain scenarios. Deployments recreate pods with random names and do not guarantee ordered startup, which can break replication protocols. StatefulSets provide the stable network identity and persistent volume binding required for consistent database clustering.
Do DaemonSets support rolling updates?
Yes, DaemonSets support rolling updates through the updateStrategy field, allowing you to update the pod template while maintaining one pod per node. However, unlike Deployments, you cannot scale a DaemonSet to multiple replicas per node; it strictly enforces a one-to-one relationship with selected nodes.
How do StatefulSets handle storage when scaling down?
StatefulSets do not delete PersistentVolumeClaims when scaling down or deleting pods. This safety mechanism prevents accidental data loss. When you scale back up, the new pod reattaches to the existing PVC with its previous data intact. You must manually delete PVCs if you want to remove the storage permanently.
Can I run a DaemonSet on only specific nodes?
Yes, DaemonSets support node selectors, node affinity, and taints/tolerations to limit execution to specific nodes. For example, you can deploy GPU monitoring agents only on nodes with GPU hardware by specifying nodeSelector in the pod template, ensuring the DaemonSet skips irrelevant nodes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →