Compare Kubernetes StatefulSet vs. deployment vs. DaemonSet
Kubernetes has several ways to deploy applications, including deployments, DaemonSets and StatefulSets. But each resource type has unique benefits, drawbacks and use cases.
Although Kubernetes has emerged as the leading platform for container orchestration, navigating its complexity can present challenges for IT professionals. Kubernetes offers multiple options to deploy and run applications, including deployments, DaemonSets and StatefulSets.
Running an app on Kubernetes typically involves using one of these resource types or some combination of all three. Choosing which deployment option to use depends on what your app needs to do -- for example, whether it should maintain state -- and how your Kubernetes clusters should operate.
What is a Kubernetes deployment?
In Kubernetes, a deployment is a type of file that tells Kubernetes how to deploy an application by providing instructions to run a particular set of containers, known as a pod. Deployments can also specify configuration data, such as which network ports to open for containers.
The following example from the Kubernetes documentation shows a deployment file that runs a set of Nginx containers.
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
On its own, a deployment is just a file. To launch the application defined in a deployment, use the apply command in the Kubernetes command-line tool kubectl, as demonstrated in the following example.
kubectl apply -f /path/to/deployment-file.yaml
After applying a deployment, Kubernetes automatically determines which node -- Kubernetes' term for a server inside a Kubernetes cluster -- should host the app's containers. Alternatively, use an option like the nodeSelector field in the pod specification to select certain nodes as hosts. Kubernetes can also automatically restart or reschedule containers that fail or nodes that go down.
Kubernetes deployment benefits
Using deployments offers multiple benefits over executing and managing containers and clusters manually.
Deployments require the least configuration data and setup effort, making them the simplest, most straightforward way to run an application using Kubernetes. When using a deployment, Kubernetes decides which nodes in a cluster should host the containers and automatically attempts to keep containers running if a particular node fails.
Kubernetes deployment drawbacks
Deployments have two main disadvantages compared with StatefulSets and DaemonSets. Both are related to the limited control that deployments provide over how an application runs:
- Lack of granular control. Deployments configure apps in a generic way. With a deployment, it's not possible to assign a unique identifier or specific resources to a particular app or configure each app in an individualized manner.
- Lack of scalability. Each deployment must be applied manually, making deployments tedious to use when running the same app multiple times. For example, deployments are not an efficient way to deploy the same container to each node in a cluster.
What is a DaemonSet in Kubernetes?
A DaemonSet is a special type of application deployment configuration for running a given container or set of containers on multiple nodes within a Kubernetes cluster. A DaemonSet can deploy apps to multiple nodes in a single step.
Like deployments, DaemonSets are files. The following example from the Kubernetes documentation shows a DaemonSet configuration:
apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-elasticsearch namespace: kube-system labels: k8s-app: fluentd-logging spec: selector: matchLabels: name: fluentd-elasticsearch template: metadata: labels: name: fluentd-elasticsearch spec: tolerations: # these tolerations are to have the daemonset runnable on control plane nodes # remove them if your control plane nodes should not run pods - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule containers: - name: fluentd-elasticsearch image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log
Like deployments, DaemonSets must be applied using kubectl before they can take effect.
Kubernetes DaemonSet benefits
Using a DaemonSet can address the second drawback of deployments: lack of scalability. A DaemonSet is an efficient way to deploy containers on multiple servers inside a Kubernetes cluster.
DaemonSets are most often used to run background software, such as a monitoring agent, on each node in a cluster. DaemonSets are not typically used to deploy the main apps hosted on Kubernetes.
Kubernetes DaemonSet drawbacks
There is no inherent drawback to using a DaemonSet, provided you want a given container or set of containers to run on multiple nodes. But DaemonSets aren't designed to run containers on a specific node, making deployments a better choice for apps requiring that capability.
What is a StatefulSet in Kubernetes?
A StatefulSet is a special type of deployment configuration that assigns a unique identifier to each container or set of containers to be run.
In the following example from the Kubernetes documentation, the file creates a StatefulSet named "web" and associates it with three unique Nginx containers:
apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: nginx # has to match .spec.template.metadata.labels serviceName: "nginx" replicas: 3 # by default is 1 minReadySeconds: 10 # by default is 0 template: metadata: labels: app: nginx # has to match .spec.selector.matchLabels spec: terminationGracePeriodSeconds: 10 containers: - name: nginx image: registry.k8s.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "my-storage-class" resources: requests: storage: 1Gi
Like deployments and DaemonSets, StatefulSets must be applied using kubectl.
Kubernetes StatefulSet benefits
StatefulSets are primarily useful for establishing a unique, persistent relationship between a container and another Kubernetes resource.
Use cases for StatefulSets typically involve stateful apps that need access to persistent storage resources. For example, StatefulSets let a container access the same data storage volume even if the container restarts or moves to another node.
With a standard deployment, this wouldn't be possible. Deployments have no simple way to define a unique association between a container and another resource that will remain intact if the container restarts. Instead, Kubernetes deployments automatically assign resources to containers after every restart or rescheduling based on which resources have the most availability at the time of assignment.
Because DaemonSets do something fundamentally different than StatefulSets, it's impossible to directly compare the two.
Kubernetes StatefulSet drawbacks
While StatefulSets are helpful in the scenarios described above, they don't provide value in other situations. For example, standard deployments are best for running stateless apps or apps that use generic resources that don't require specific, persistent configurations.
To run a given container or set of containers on multiple nodes at the same time, use a DaemonSet. Likewise, StatefulSets are a great choice for assigning unique resources to containers and maintaining application state. But in most cases, deployments are the simplest way to run apps in Kubernetes.
Use this Kubernetes and Helm tutorial to simplify app deployments