Elevating IaC Workflows with Spacelift Stacks and Dependencies 🛠️

Register for the July 23 demo →

Kubernetes

Kubernetes StatefulSet vs. Deployment with Use Cases

statefulset vs deployment

StatefulSets and Deployments are two Kubernetes API objects used to manage sets of identical Pods. They both make it easy to orchestrate multiple Pod replicas, but they have different features that specialize them for separate use cases.

Deployments offer declarative configuration to automate Pod updates and scaling operations, whereas StatefulSets include additional features that help you orchestrate stateful workloads in your cluster.

In this article, we’ll compare both types of objects and discuss when each should be used.

You will learn:

  1. Stateful vs. stateless applications
  2. What is a Kubernetes StatefulSet?
  3. What is a Kubernetes Deployment?
  4. StatefulSet vs. Deployment
  5. StatefulSet and Deployment use cases
  6. What is the difference between a StatefulSet, a Deployment, and a DaemonSet?

Stateful vs. stateless applications

The difference between StatefulSets and Deployments reflects the divide between stateful and stateless systems. As their name suggests, StatefulSets are designed to run your app’s stateful components, while Deployments are used for stateless ones.

A system is stateless when it doesn’t need to store any data within itself. Website and web app frontends are usually stateless, for example. On the other hand, applications such as databases are said to be stateful. They require persistent storage that outlives the lifecycle of individual container replicas.

Kubernetes is best known for managing stateless services. When an app is stateless, its Pods are fully interchangeable; scaling operations won’t result in the loss of any data. This is not true of stateful applications, however. To run a stateful service in Kubernetes, you’ll need to use a StatefulSet to ensure stable Pod replication and data persistence.

What is a Kubernetes StatefulSet?

Kubernetes StatefulSet is an API-object that’s purpose-built to support stateful application components. It creates a set of identically configured Pods from a spec you supply, but each Pod is assigned a non-interchangeable identity. Pods retain their identity if they have to be rescheduled or you scale the StatefulSet.

StatefulSets solve the challenges of running stateful services in Kubernetes. The persistent Pod identities permit storage volumes to be associated with specific Pods inside the StatefulSet. They also facilitate graceful scaling operations and rolling updates, where Pods are added and removed in a predictable order.

When to Use StatefulSets?

Let’s consider a simple example of running three replicas of a MySQL database server in Kubernetes. The deployment should be configured with one Pod in the primary role, handling read-write operations, and the remaining three Pods as MySQL read-only replicas.

Applications connecting to the database will always need to connect to the Pod that’s in the primary role in order to receive read-write access. This wouldn’t be possible if a Deployment or ReplicaSet was used, as scheduling or replication changes would generate new Pod identities. The application would have no way of knowing which Pod is the primary MySQL instance.

StatefulSets eliminate this problem. Each Pod in the StatefulSet is assigned a predictable and consistent network identity in the form <statefulset-name>-<pod-ordinal-index>. The four Pods in the MySQL deployment would be named as follows:

  • mysql-0 – First Pod, in the primary role
  • mysql-1 – Read-only replica
  • mysql-2 – Read-only replica

Now other applications can connect to mysql-0 to reliably interact with the MySQL primary instance. Because StatefulSets also guarantee ordered updates, the vital mysql-0 replica is only terminated if you scale down to zero. The read-only replicas will always be removed first.

Furthermore, the persistent storage characteristics of StatefulSets mean that each Pod will always have its own storage volume reattached, even after it’s rescheduled. Each replica, therefore, maintains its own copy of the database, ensuring reliable, independent data replication.

Similarly, Pods support stable network identities using a headless service that you must separately create.

Example: Creating a Kubernetes StatefulSet

The following manifest sets up a basic StatefulSet object to run three replicas of an application:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: app
spec:
  selector:
    matchLabels:
      app: app
  replicas: 3
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
        - name: app
          image: nginx:latest

Save the manifest to statefulset.yaml, then use Kubectl to apply it to your cluster:

$ kubectl apply -f statefulset.yaml
statefulset.apps/app created

The requested three Pods will be created for the StatefulSet:

$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
app-0   1/1     Running   0          18s
app-1   1/1     Running   0          16s
app-2   1/1     Running   0          14s

Try changing your manifest’s spec.replicas field to 5, then reapply it to your cluster:

$ kubectl apply -f statefulset.yaml
statefulset.apps/app configured

You’ll see that two new Pods are created.

Their identities continue the previously established ordinal sequence:

$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
app-0   1/1     Running   0          2m7s
app-1   1/1     Running   0          2m5s
app-2   1/1     Running   0          2m3s
app-3   1/1     Running   0          36s
app-4   1/1     Running   0          34s

Next, edit the manifest again to reduce the replica count back to 3.

Repeat the Kubectl command to update the StatefulSet in your cluster:

$ kubectl apply -f statefulset.yaml
statefulset.apps/app configured

You’ll see that Kubernetes terminates Pods in the reverse order of their creation.

The two extra Pods created by the previous change will be removed, leaving the original three Pods intact:

$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
app-0   1/1     Running   0          13m
app-1   1/1     Running   0          12m
app-2   1/1     Running   0          12m

What is a Kubernetes Deployment?

Deployment is an API object used to manage Pods and ReplicaSets that are part of stateless applications. They support declarative configuration, rollouts, and rollbacks. You use them to automate Pod updates.

Because Deployments use a declarative management model, you only need to define what your desired state looks like. When you apply a Deployment manifest, Kubernetes will automatically compare the state it describes to the current version in your cluster. The Deployment controller will then reconcile the existing state to the new desired state, which results in Pods being added and removed as required.

In practical terms, it allows you to change the number of Pod replicas by adjusting the value in your Deployment’s manifest. Kubernetes will automatically add the correct number of new Pods, or remove existing ones, to achieve the rollout. Deployments also allow you to pause a rollout if you detect a problem and rollback to a previous state.

When to use Deployments?

Use a Deployment to run stateless applications that need to benefit from declarative updates and rollbacks. They permit you to rollout changes safely, without the threat of downtime.

Deployments automatically create Pods and ReplicaSets from a consistent specification you define. This removes much of the administrative burden of configuring, changing, and scaling containerized applications. The Deployment controller handles the orchestration task and will allocate each Pod to the most appropriate Node.

In addition, using a Deployment makes your application more resilient to any failures that occur in your cluster. The Deployment controller will ensure the specified number of Pods are kept running; they’ll be rescheduled automatically after Node failures.

Wrapping Pods in a Deployment is always preferable to running them “bare,” without management by a controller, because those Pods can’t be directly scaled or replicated across your cluster’s Nodes.

Example: Creating a Kubernetes Deployment

Consider the following simple manifest for a Kubernetes Deployment YAML file, which starts three replicas of a Pod running the NGINX web server:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest

Copy this manifest, save it to deployment.yaml in your working directory, and then use Kubectl to apply it to your cluster:

$ kubectl apply -f deployment.yaml
deployment.apps/nginx created

Kubernetes will create three Pods to satisfy the declared replica count:

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-654975c8cd-c5cqj   1/1     Running   0          13s
nginx-654975c8cd-lsw22   1/1     Running   0          13s
nginx-654975c8cd-tkf4s   1/1     Running   0          13s

Try changing the spec.replicas field of your manifest to 5, then reapply it to your cluster and check the updated Pod list:

$ kubectl apply -f deployment.yaml
deployment.apps/nginx configured

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-654975c8cd-7tgnq   1/1     Running   0          43s
nginx-654975c8cd-c5cqj   1/1     Running   0          106s
nginx-654975c8cd-lsw22   1/1     Running   0          106s
nginx-654975c8cd-sfj7m   1/1     Running   0          43s
nginx-654975c8cd-tkf4s   1/1     Running   0          106s

You can see that two new Pods have been created to match the revised replica count.

Now revert the replica count to 3 and apply the updated manifest once more:

$ kubectl apply -f deployment.yaml
deployment.apps/nginx configured

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-654975c8cd-7tgnq   1/1     Running   0          3m4s
nginx-654975c8cd-c5cqj   1/1     Running   0          4m7s
nginx-654975c8cd-sfj7m   1/1     Running   0          3m4s

The output shows that Kubernetes has randomly terminated two Pods to leave three remaining. This demonstrates how Pods in Deployments are considered to be interchangeable, so their identities and order of creation are not tracked.

StatefulSet vs. Deployment

The decision whether to use a StatefulSet or a Deployment should be based on the characteristics of the service you’re deploying in your cluster. Here’s a quick rundown of their main features and differences:

Feature StatefulSet Deployment
Stateful/Stateless applications Stateful Stateless
Pod identities Pods are assigned a persistent identifier, derived from the StatefulSet’s name and their ordinal creation index. Pods are assigned random identifiers, derived from the Deployment’s name and a unique random string.
Pod interchangeability Pods in a StatefulSet are not interchangeable. It’s expected that each Pod has a specific role, such as always running as a primary or read-only replica for a database application. All Pods are identical, so they’re interchangeable and can be replaced at any time.
Rollout ordering Pods are guaranteed to be created and removed in sequence. When you scale down the StatefulSet, Kubernetes will terminate the most recently created Pod. No ordering is supported. When you scale down the Deployment, Kubernetes will terminate a random Pod.
Storage access Each Pod in the StatefulSet is assigned its own Persistent Volume (PV) and Persistent Volume Claim (PVC). All Pods share the same PV and PVC.

Kubernetes StatefulSet and Deployment use cases

StatefulSets and Deployments both manage Pods, but they’re targeted at specific use cases.

Choose a StatefulSet in the following scenarios:

  • You’re running a stateful application that requires stable, persistent storage, such as a replicated deployment of a database, file server, key-value store, or messaging queue.
  • Pods are non-interchangeable because they each have specific roles, such as being a primary, replica, or worker.
  • You require predictable sequenced rollouts, with terminations that occur in reverse order.

Choose a Deployment when the following criteria apply:

  • Your application is stateless; it does not require persistent storage, or all Pods can share the same storage volume.
  • You require multiple replicas of a Pod to be created from one declaratively defined configuration.
  • You need controlled rollouts and rollbacks, based on changes you make to your declared state.

What is the Difference Between a StatefulSet, a Deployment, and a DaemonSet?

As we’ve discussed in this article, StatefulSets are used to run stateful applications in Kubernetes, whereas Deployments support declarative updates for stateless Pods. DaemonSets are a third kind of Pod controller that you can also use.

A DaemonSet ensures that all or some of the Nodes in your cluster are always running a replica of a Pod. When new Nodes join the cluster, active DaemonSets will automatically start new Pods on those Nodes. This behavior means DaemonSets are ideal for monitoring systems, logging agents, and hardware integrations, where each Node in your cluster must permanently run an instance of the application.

Key points

In this article, we’ve explained the differences between the Kubernetes StatefulSet and Deployment objects. You’ve learned how you can use the objects to easily run both stateful and stateless applications inside your clusters.

A StatefulSet should be chosen for stateful components that require predictable Pod identities, ordered rollouts, and stable storage access. Select a Deployment instead when your service is stateless, doesn’t require persistent storage, and won’t be affected by changes to Pod identities.

If you need any assistance with managing your Kubernetes projects, take a look at Spacelift. It brings with it a GitOps flow, so your Kubernetes Deployments are synced with your Kubernetes Stacks, and pull requests show you a preview of what they’re planning to change. It also has an extensive selection of policies, which lets you automate compliance checks and build complex multi-stack workflows. You can check it for free by creating a trial account.

Manage Kubernetes Easier and Faster

Spacelift allows you to automate, audit, secure, and continuously deliver your infrastructure. It helps overcome common state management issues and adds several must-have features for infrastructure management.

Start free trial

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide