Sets and Controllers
Kubernetes organizes Pods into logical “Sets” and then uses specialized Controllers to manage their lifecycle. At its core, a Set is simply a group of resources most commonly Pods—that share a common purpose. Under the hood, Controllers constantly observe the cluster’s actual state and compare it to your declared desired state, spinning up or tearing down Pods to match. Let’s walk through each major Set type, starting with the foundational ReplicaSet.
1apiVersion: apps/v1 2kind: ReplicaSet 3metadata: 4 name: my-app-replicaset 5spec: 6 replicas: 3 7 selector: 8 matchLabels: 9 app: my-app 10 template: 11 metadata: 12 labels: 13 app: my-app 14 spec: 15 containers: 16 - name: my-app-container 17 image: nginx:1.23
A ReplicaSet ensures exactly N identical Pods exist at all times. Think of it as your application’s insurance policy if a Pod crashes or is evicted, the ReplicaSet immediately spins up a replacement. In practice, you rarely hand-craft ReplicaSets; instead, you declare a Deployment, and Kubernetes creates a ReplicaSet on your behalf. Deployments add rolling-update, rollback, and pause-resume capabilities, orchestrating ReplicaSets behind the scenes.
Moving beyond stateless replicas, a StatefulSet adds stable identities and durable storage to each Pod. It’s the go-to for databases, message queues, or any service that needs a persistent disk and predictable network name (e.g. pod-0
, pod-1
, ...). StatefulSet Pods start and terminate in a strict order, guaranteeing data consistency across restarts.
1apiVersion: apps/v1 2kind: StatefulSet 3metadata: 4 name: my-stateful-app 5spec: 6 serviceName: "my-stateful-service" 7 replicas: 3 8 selector: 9 matchLabels: 10 app: my-app 11 template: 12 metadata: 13 labels: 14 app: my-app 15 spec: 16 containers: 17 - name: my-app-container 18 image: redis:latest 19 volumeMounts: 20 - name: my-app-storage 21 mountPath: /data 22 volumeClaimTemplates: 23 - metadata: 24 name: my-app-storage 25 spec: 26 accessModes: ["ReadWriteOnce"] 27 resources: 28 requests: 29 storage: 1Gi
Where StatefulSets guarantee one-to-one identity with storage, a DaemonSet guarantees one-to-one Pod distribution across nodes. Perfect for cluster-wide agents like log shippers or monitoring daemons—any time a node joins, the DaemonSet Controller schedules a new Pod there; when a node leaves, the Pod follows.
1apiVersion: apps/v1 2kind: DaemonSet 3metadata: 4 name: my-logging-agent 5spec: 6 selector: 7 matchLabels: 8 app: logging-agent 9 template: 10 metadata: 11 labels: 12 app: logging-agent 13 spec: 14 containers: 15 - name: my-logging-agent-container 16 image: fluentd:latest
Not all work is ongoing, though. Jobs handle finite, one-off tasks: database migrations, ETL processes, or batch imports. A Job creates Pods that run to completion, retrying until success or hitting a backoffLimit
.
1apiVersion: batch/v1 2kind: Job 3metadata: 4 name: my-job 5spec: 6 template: 7 spec: 8 containers: 9 - name: my-job-container 10 image: busybox 11 command: ["echo", "Hello Kubernetes!"] 12 restartPolicy: Never 13 backoffLimit: 4
And when you need that batch to recur on a schedule—say nightly backups or weekly reports—you reach for a CronJob. It layers cron-style scheduling atop the Job controller, spinning up Jobs at your chosen times.
1apiVersion: batch/v1 2kind: CronJob 3metadata: 4 name: my-cronjob 5spec: 6 schedule: "0 0 * * *" 7 jobTemplate: 8 spec: 9 template: 10 spec: 11 containers: 12 - name: my-cronjob-container 13 image: busybox 14 command: ["echo", "Daily Backup"] 15 restartPolicy: OnFailure
In every case, the pattern is the same: you declare the desired state in YAML, Kubernetes controllers watch the cluster, and they act in a continuous control loop to reconcile reality with your specification. Understanding how Sets and Controllers pair up lets you choose the right abstraction for stateless services, stateful workloads, cluster-wide agents, one-off tasks, or scheduled jobs—giving you both flexibility and reliability in managing your applications.