| Tested on | Rocky Linux 10.2 (Red Quartz) workstation |
|---|---|
| Package | kubectl 1.36.3 |
| Applies to | Any host with kubectl configured; any Kubernetes cluster |
| Cert prep | CKAD · CKA · CKS |
| Lab environment | Multi-node kubeadm cluster with containerd — install Kubernetes with kubeadm |
| Privilege | Normal user (no sudo required on the workstation) |
| Scope | Workload selection across Pod, ReplicaSet, Deployment, StatefulSet, DaemonSet, Job, and CronJob: comparison tables, decision checklist, scenarios, and kubectl discovery. Does not cover full controller manifests or pairwise Pod-vs-Deployment depth — those live in linked tutorials. |
| Related guides | Deployments and rolling updates Kubernetes StatefulSets Kubernetes DaemonSets Kubernetes Jobs Kubernetes CronJobs |
Kubernetes runs containers inside Pods, but you rarely create bare Pods for production services. Controllers manage Pods from a template:
- Deployment, StatefulSet, DaemonSet, ReplicaSet, and Job — long-running or batch controllers that reconcile Pod templates
- CronJob — holds a Job template and creates Jobs on a schedule; those Jobs then create Pods
Each kind answers a different workload-management question:
- How many interchangeable replicas should stay running?
- Whether Pod names and storage must stay stable
- Whether one Pod should follow every node
- Whether the work should finish once or repeat on a schedule
At a glance:
- ReplicaSet maintains replica count; Deployment adds rolling updates on top
- StatefulSet gives ordered Pods stable network identity
- DaemonSet places an agent on every matching node
- Job runs batch work to completion; CronJob creates Jobs on a schedule rather than Pods directly
The sections below compare those kinds, walk through a decision checklist, and show how to list them with kubectl before you open a controller-specific tutorial.
Quick answer
| Requirement | Recommended resource |
|---|---|
| Temporary test, short diagnostic, or special unmanaged case | Pod |
| Stateless application with replicas and rolling updates | Deployment |
| Stable Pod names, order, or per-replica storage | StatefulSet |
| One Pod on every eligible node | DaemonSet |
| One-time task that runs to completion | Job |
| Task on a repeating schedule | CronJob |
| Maintain identical Pod replicas without rollout features | ReplicaSet — usually through a Deployment |
Default rules:
- Use a Deployment for most long-running stateless applications.
- Use a StatefulSet when identity, ordering, or per-replica storage matters.
- Use a DaemonSet for node-level agents.
- Use a Job or CronJob for finite batch work.
- Use a bare Pod mainly for testing, short diagnostics, or other special unmanaged cases — even a single-container workload normally belongs on a Deployment or Job.
Workload types compared
The table compares every built-in workload kind at a glance:
- Resource — Kubernetes object kind you create (
Deployment,Job, and so on). - API group — API group and version that defines the object schema (
apps/v1,batch/v1, or corev1for Pod). - Best for — Typical use case that kind is designed to solve.
- Pod identity — Whether Pod names and UIDs are interchangeable, stable ordinals, or tied to node coverage.
- Scaling — Primary field or mechanism that controls how many Pods run (replica count, completions, schedule, or manual).
- Rollout strategy — How template changes reach running Pods through a controller-managed rollout (
RollingUpdate,Recreate,OnDelete, or none). - Designed for run-to-completion work? — Whether the kind is meant for batch work that exits when done, as opposed to long-running services.
- Example — Representative workload that fits the row.
| Resource | API group | Best for | Pod identity | Scaling | Rollout strategy | Designed for run-to-completion work? | Example |
|---|---|---|---|---|---|---|---|
| Pod | v1 |
Tests and special single-Pod cases | Individual | Manual | No controller-managed rollout | Possible, but unmanaged; normally use a Job | Diagnostic container |
| ReplicaSet | apps/v1 |
Maintaining a replica count | Interchangeable | spec.replicas |
No rolling update | No | Owned by a Deployment |
| Deployment | apps/v1 |
Stateless applications | Interchangeable | spec.replicas |
RollingUpdate by default; Recreate supported | No | Web frontend or API |
| StatefulSet | apps/v1 |
Stable identity or ordered storage | Stable ordinal names | spec.replicas |
RollingUpdate by default; OnDelete supported | No | Database cluster member |
| DaemonSet | apps/v1 |
One Pod per selected node | Replaceable Pod; one copy per eligible node | Per eligible node | RollingUpdate by default; OnDelete supported | No | Log or monitoring agent |
| Job | batch/v1 |
Run-to-completion task | Temporary | completions / parallelism |
N/A | Yes | Schema migration |
| CronJob | batch/v1 |
Scheduled batch work | No stable Pod identity; Pods belong to created Jobs | Schedule-driven | N/A | Yes, through each created Job | Nightly backup |
ReplicationController is the legacy predecessor to ReplicaSet. New workloads should use ReplicaSet through a Deployment, not a standalone ReplicationController.
How Pods and controllers relate
Workload resources manage Pods for different application patterns. A controller watches the object you create, compares cluster state to the desired state, and creates or replaces Pods to close the gap. That reconciliation drives scaling, self-healing, rollout behaviour, and — for Jobs — retry until success or policy limits.
Deployment, StatefulSet, DaemonSet, and ReplicaSet live in the apps/v1 API group and reconcile long-running Pod sets. Job and CronJob live in batch/v1 and reconcile work that should finish:
-
A CronJob does not create Pods directly — it creates Job objects on a schedule, and each Job creates Pods
-
Pods are the smallest deployable unit; controllers own Pod templates.
-
The kubelet can restart failed containers inside the same Pod according to
restartPolicy. If the Pod itself is deleted, evicted, or lost with its node, a workload controller creates a replacement Pod with a new UID. -
Most production applications should not run as unmanaged Pods.
Bare Pods fit narrow cases: testing an image once, running a short diagnostic, or learning Pod fields before moving to a controller. Pod phases, restart policies, and lifecycle hooks live in the Kubernetes pods guide.
Continuous workloads compared
These controllers keep Pods running until you scale down or delete the parent object.
| Requirement | ReplicaSet | Deployment | StatefulSet | DaemonSet |
|---|---|---|---|---|
| Maintain a replica count | Yes | Yes | Yes | Auto per eligible node |
| Rollout strategy | No rolling update | RollingUpdate by default; Recreate supported | RollingUpdate by default; OnDelete supported | RollingUpdate by default; OnDelete supported |
| Stable Pod identity | No | No | Yes | No — maintains one replaceable Pod per eligible node |
| Stable ordinal Pod names and DNS identity through a headless Service | No | No | Yes | N/A |
| Ordered create/terminate (default) | No | No | Yes (OrderedReady) |
No |
| Per-replica persistent storage (common pattern) | Manual design | Manual design | volumeClaimTemplates | Rare |
| One Pod on every matching node | No | No | No | Yes |
StatefulSets provide stable identity, while DaemonSets maintain node coverage rather than permanent Pod names or UIDs.
Deployment is the default for stateless services — web servers, APIs, and interchangeable backends. It manages ReplicaSets underneath. The default RollingUpdate strategy replaces Pods in a controlled rollout; Recreate tears down old Pods before starting new ones.
StatefulSet fits when replicas are not interchangeable: stable hostnames, ordered startup or shutdown, or storage bound to a replica index. Stable StatefulSet DNS identity requires a governing headless Service, which you create separately. Mounting a volume alone does not automatically require StatefulSet; evaluate whether identity and order matter for the application. The default RollingUpdate strategy updates one Pod at a time by ordinal; OnDelete is also supported, and ordering can be affected by update and availability settings.
DaemonSet fits node-level agents such as log collectors, monitoring agents, and CNI node plugins. It follows eligible nodes through node selectors, affinity, and tolerations rather than a replica count you set manually. Each Pod is replaceable — the controller maintains one copy per eligible node, not a stable Pod identity tied permanently to that node. The default RollingUpdate strategy applies; OnDelete is also supported. System components such as kube-proxy and Calico calico-node illustrate the pattern on a live cluster.
Operators may manage Deployments, StatefulSets, Jobs, or custom resources internally. Operator development is outside this selection guide.
Batch workloads compared
Batch controllers reconcile work that should complete.
| Requirement | Job | CronJob |
|---|---|---|
| Run once | Yes | No — creates Jobs on a schedule |
| Run on a cron schedule | No | Yes |
| Creates Pods directly | Yes | No — creates Jobs, which create Pods |
| Expected to finish | Yes | Each spawned Job should finish |
| Typical restart policy on Pod template | OnFailure or Never |
Same (via Job template) |
Use a Job for migrations, imports, reports, and one-time administrative tasks. Use a CronJob for nightly backups, periodic cleanup, and recurring synchronization.
Advanced Job fields — parallelism, backoffLimit, deadlines, concurrency policy — and CronJob time zones belong in the dedicated Job and CronJob tutorials linked in Related guides. Manifest and schedule syntax live in those guides.
Where ReplicaSet fits
ReplicaSet keeps a desired number of Pods that match its label selector. If Pods are deleted or nodes fail, the ReplicaSet creates replacements until the count is met again.
Deployments normally create and manage ReplicaSets for you. When you update a Deployment, Kubernetes creates a new ReplicaSet for the new Pod template and scales the old ReplicaSet down during a rolling update. You rarely create a ReplicaSet directly.
Reach for a standalone ReplicaSet only when you need replica count without rollout or revision management — an uncommon case on modern clusters. When rolling updates, rollback history, or the usual stateless application path matter, create a Deployment instead. ReplicaSet behaviour and selector matching are covered in the Kubernetes ReplicaSet guide.
Choose a workload
Start with the checklist when you know the workload shape but not the kind. Use the scenario table when you have a concrete example in mind.
Decision checklist
| Question | If yes → | If no → |
|---|---|---|
| Must the workload run to completion and exit? | Job or CronJob (if scheduled) | Continuous controller below |
| Must one Pod run on every eligible node? | DaemonSet | Deployment, StatefulSet, or Job |
| Do Pods need stable names, order, or per-replica storage? | StatefulSet | Deployment |
| Are replicas interchangeable stateless Pods? | Deployment | StatefulSet or DaemonSet |
| Is this a one-off test or diagnostic? | Bare Pod | Controller-backed resource |
After you choose a resource kind, continue to its dedicated tutorial for manifests and operational details.
Common scenarios
| Scenario | Resource | Why |
|---|---|---|
| Three replicas of an NGINX web application | Deployment | Stateless replicas with rolling updates |
| REST API with rolling upgrades | Deployment | Interchangeable Pods and rollout history |
| MySQL with stable storage and Pod identity | StatefulSet | Persistent identity and per-replica storage |
| Log collector on each worker node | DaemonSet | One Pod per eligible node |
| Run a database migration once | Job | Finite task that should exit |
| Back up a database every night | CronJob | Scheduled Job |
| Test a container image quickly | Pod | Simple temporary workload |
| Maintain replicas without rollout management | ReplicaSet | Rare — Deployment is normally preferable |
Common selection mistakes
| Mistake | Better choice |
|---|---|
| Running a web application as a bare Pod | Deployment |
| Creating a ReplicaSet when rollout support is needed | Deployment |
| Using a Deployment for one agent per node | DaemonSet |
| Using a CronJob for a continuously running service | Deployment or another continuous controller |
| Using a Deployment for a task that should complete | Job |
| Using a Job for a scheduled recurring task | CronJob |
| Choosing StatefulSet only because a volume is mounted | Confirm stable identity or per-replica storage is required |
| Assuming every database belongs in StatefulSet | Evaluate architecture and Operator support |
Discover workload kinds in a cluster
Long-running controllers and batch kinds register under different API groups. List them before writing manifests:
kubectl api-resources --api-group=appsSample output:
NAME SHORTNAMES APIVERSION NAMESPACED KIND
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSetControllerRevision is an internal object StatefulSet and DaemonSet controllers use to track revisions — not something you create directly.
kubectl api-resources --api-group=batchSample output:
NAME SHORTNAMES APIVERSION NAMESPACED KIND
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true JobThe split between apps and batch matches the continuous-versus-finish decision in the checklist above.
See what is already running. Each kind prints different columns, so list them separately:
kubectl get deployments,statefulsets,daemonsets -ASample output (trimmed from a healthy two-node lab cluster):
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system coredns 2/2 2 2 6h43m
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
calico-system calico-node 2 2 2 2 2 kubernetes.io/os=linux 6h42m
kube-system kube-proxy 2 2 2 2 2 kubernetes.io/os=linux 6h43mCoreDNS runs as a Deployment with a fixed replica count — READY matches UP-TO-DATE when all replicas are available. calico-node and kube-proxy are DaemonSets; DESIRED and READY track eligible nodes, not a replica field you set on a Deployment.
kubectl get jobs,cronjobs -AAn empty result only means no Jobs or CronJobs exist in the cluster yet, not that the API kinds are missing.
Before authoring YAML, read the one-line kubectl explain summary for the kind you chose:
| Kind | kubectl explain takeaway |
|---|---|
| Deployment | Declarative updates for Pods and ReplicaSets |
| StatefulSet | Pods with consistent identities (stable DNS and hostname) |
| DaemonSet | Configuration of a daemon set — node coverage |
| Job | Configuration of a single run-to-completion job |
| CronJob | Configuration of a scheduled cron job |
Example:
kubectl explain deploymentSample output (trimmed):
GROUP: apps
KIND: Deployment
VERSION: v1
DESCRIPTION:
Deployment enables declarative updates for Pods and ReplicaSets.API group discovery, preferred versions, and nested field paths live in the Kubernetes API resources guide.
What's Next
- Kubernetes Pods and Pod Lifecycle
- Differences and When to Use Each
- Kubernetes ReplicaSet with Examples
References
Summary
Kubernetes workload resources manage Pods directly or indirectly using different reconciliation rules. Deployments, StatefulSets, DaemonSets, ReplicaSets, and Jobs contain Pod templates, while CronJobs contain Job templates that create Jobs and then Pods. CronJobs create Jobs on a schedule rather than managing Pods directly. Deployments suit interchangeable stateless replicas; StatefulSets suit stable identity and per-replica storage; DaemonSets suit one Pod per selected node; Jobs run tasks to completion once. Bare Pods and standalone ReplicaSets fill narrow roles — start with Deployment unless the comparison tables and checklist point elsewhere, then follow the controller tutorial that matches your choice.

