| 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 |
| Lab environment | Multi-node kubeadm cluster with containerd — install Kubernetes with kubeadm |
| Privilege | Normal user (no sudo required on the workstation) |
| Scope | Pod vs Deployment differences, minimal YAML, delete and scale behaviour, update trade-offs, and when to choose each. Does not cover full Pod lifecycle, rolling-update tuning, ReplicaSet YAML, StatefulSet, DaemonSet, Job, HPA, probes, or storage. |
| Related guides | Kubernetes labels and selectors |
Every container in Kubernetes runs inside a Pod, yet most production manifests wrap workloads in a Deployment. That jump is easy to miss when kubectl run drops you straight into a bare Pod and both paths can start the same nginx image.
This guide puts both approaches side by side in one namespace. You will apply minimal YAML for a standalone Pod and a two-replica Deployment, delete each type of Pod to see what the cluster recreates, scale the Deployment, and compare how updates behave. For canary and blue/green patterns beyond a single rolling update, see Kubernetes deployment strategies.
Pod vs Deployment Comparison
| Concern | Bare Pod | Deployment |
|---|---|---|
| Resource hierarchy | Pod → containers | Deployment → ReplicaSet → Pods → containers |
| Self-healing after Pod loss | No | Yes, via ReplicaSet |
| Replicas | One Pod per manifest | spec.replicas (defaults to 1 when omitted) |
| Scaling | Create more Pod YAML files manually | kubectl scale or edit spec.replicas |
| Updates | Limited in-place edits; most template fields require replacement | Change Pod template; controlled rollout |
| Rollback | None | kubectl rollout undo (revision history) |
| Pod naming | Fixed metadata.name until deleted |
Generated name per Pod (web-<rs-hash>-<suffix>) |
Pod-level restartPolicy |
Always, OnFailure, or Never |
Must be Always or omitted |
| Stable application endpoint | None automatically | None automatically; normally expose the changing Pods through a Service |
| Typical use | Tests, demos, learning | Web apps, APIs, stateless services |
A Deployment manages Pods but does not automatically create a Service. Pod names and IPs can change during replacement.
A bare Pod can use restartPolicy: OnFailure or Never for one-off or batch-style work. A Deployment Pod template permits only Always, which is why one-time tasks belong in a Job rather than a Deployment.
How Pods and Deployments Work
Standalone Pod
A Pod is Kubernetes' smallest deployable workload unit. It wraps one or more closely related containers that are scheduled together on one node and share the same network namespace and optional volumes.
When you apply a bare Pod manifest:
- Kubernetes creates that single Pod object
- No controller watches it for desired replica count
- Deleting the Pod normally removes the workload permanently
Pod YAML, phases, conditions, restartPolicy, lifecycle hooks, and inspection commands are covered in Kubernetes Pods and Pod Lifecycle.
Deployment and ReplicaSet
A Deployment is a controller for stateless applications. You declare how many replicas you want and a Pod template; the Deployment reconciles the cluster toward that desired state.
- A Deployment owns one or more ReplicaSets
- The active ReplicaSet creates Pods that match
spec.selector - Failed or deleted Pods are replaced to restore
spec.replicas - Changing the Pod template triggers a rollout; revision history enables rollback
The full Deployment workflow — apply, verify, and roll out image changes — lives in Deployments and rolling updates.
Compare Minimal Pod and Deployment YAML
The bare Pod and Deployment share the application label but use different workload labels so the ReplicaSet cannot adopt the standalone Pod. ReplicaSets immediately acquire matching Pods that have no controlling owner reference.
Create the standalone Pod
Save this minimal manifest as web-pod.yaml. It declares one nginx container in the pod-cmp-demo namespace:
apiVersion: v1
kind: Pod
metadata:
name: web-pod
namespace: pod-cmp-demo
labels:
app: web
workload: bare
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
restartPolicy: AlwaysCreate the namespace:
kubectl create namespace pod-cmp-demoSample output:
namespace/pod-cmp-demo createdApply the Pod:
kubectl apply -f web-pod.yamlSample output:
pod/web-pod createdWait until the Pod is Ready before you continue:
kubectl wait --for=condition=Ready pod/web-pod -n pod-cmp-demo --timeout=60sSample output:
pod/web-pod condition metConfirm the final status:
kubectl get pod web-pod -n pod-cmp-demoSample output:
NAME READY STATUS RESTARTS AGE
web-pod 1/1 Running 0 5sCreate the Deployment
Save this manifest as web-deploy.yaml. It runs the same nginx image but asks for two replicas through a Pod template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: pod-cmp-demo
labels:
app: web
workload: deployment
spec:
replicas: 2
selector:
matchLabels:
app: web
workload: deployment
template:
metadata:
labels:
app: web
workload: deployment
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
restartPolicy: AlwaysApply the Deployment in the same namespace:
kubectl apply -f web-deploy.yamlSample output:
deployment.apps/web createdWait for both replicas before you inspect the objects:
kubectl rollout status deployment/web -n pod-cmp-demoSample output:
deployment "web" successfully rolled outList the Deployment, its ReplicaSet, and the Pods it created:
kubectl get deploy,rs,pod -n pod-cmp-demo -l workload=deploymentSample output:
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 2/2 2 2 5s
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-656b664456 2 2 2 5s
NAME READY STATUS RESTARTS AGE
pod/web-656b664456-bkz8j 1/1 Running 0 4s
pod/web-656b664456-cmczc 1/1 Running 0 5sThe ReplicaSet hash (656b664456) appears in each Pod name. You edit the Deployment object; the controllers below it materialize Pods. The bare web-pod still runs separately because its workload: bare label does not match the Deployment selector.
Delete Pods and Compare Recovery
Delete the standalone Pod
Delete the bare Pod you created earlier:
kubectl delete pod web-pod -n pod-cmp-demoSample output:
pod "web-pod" deletedTry to fetch it again:
kubectl get pod web-pod -n pod-cmp-demoSample output:
Error from server (NotFound): pods "web-pod" not foundNo controller recreates a bare Pod. The workload stays gone unless you apply the manifest again or create a replacement manually.
Delete a Deployment-managed Pod
Capture one Deployment Pod name dynamically so the command works on any cluster:
POD_NAME=$(kubectl get pod -n pod-cmp-demo -l workload=deployment -o jsonpath='{.items[0].metadata.name}')Delete that Pod:
kubectl delete pod "$POD_NAME" -n pod-cmp-demoSample output:
pod "web-656b664456-bkz8j" deletedList the Pods and keep watching until the replica count returns to two:
kubectl get pod -n pod-cmp-demo -l workload=deployment --watchSample output:
NAME READY STATUS RESTARTS AGE
web-656b664456-7787c 1/1 Running 0 8s
web-656b664456-cmczc 1/1 Running 0 22sThe exact names and intermediate states will differ between clusters. Wait until a new Pod with a different suffix reaches Running, then press Ctrl+C. Do not use kubectl rollout status for this step because deleting one Pod does not create a new Deployment rollout.
A new Pod replaced the deleted one while the replica count stayed at two. That self-healing behaviour is the main practical difference between a bare Pod and a Deployment-backed workload.
Compare Scaling and Updates
Scaling
A standalone Pod is one object — there is no replicas field and no kubectl scale target. Creating three separate Pod manifests gives you three independent Pods with no shared desired-state management.
Scale the Deployment to three replicas instead:
kubectl scale deployment web -n pod-cmp-demo --replicas=3Sample output:
deployment.apps/web scaledWait until three replicas are Ready before you list Pods:
kubectl wait --for=jsonpath='{.status.readyReplicas}'=3 deployment/web -n pod-cmp-demo --timeout=60sSample output:
deployment.apps/web condition metVerify the new Pod count:
kubectl get pod -n pod-cmp-demo -l workload=deploymentSample output:
NAME READY STATUS RESTARTS AGE
web-656b664456-pqvjn 1/1 Running 0 21s
web-656b664456-vgh8r 1/1 Running 0 17s
web-656b664456-vz9mh 1/1 Running 0 2sThe ReplicaSet created a third Pod to match spec.replicas. You can also edit spec.replicas in the Deployment manifest and re-apply.
Updating
Most fields in an existing Pod specification are immutable. Container and init-container image fields can be updated in place, but a bare Pod provides no multi-replica rollout, availability control, or revision history. Changes to fields such as commands, environment variables, ports, and volumes normally require replacing the Pod.
Updating a Deployment's Pod template creates a new ReplicaSet and gradually replaces old Pods according to the Deployment strategy.
This article stops at that contrast. Rollout strategy fields, pause/resume, and revision-history commands are covered in the rolling updates guide linked above.
When to Use Each
Use a bare Pod
Reach for a bare Pod when automatic recovery is unnecessary:
- smoke-test whether a container image starts
- run a temporary command or short debugging session
- learn Pod YAML, phases, and
restartPolicy - reproduce a simple problem in isolation
- short demonstrations or CKAD-style manifest exercises
kubectl run creates a Pod, which makes it useful for quick tests and temporary commands. Use a Deployment manifest for controller-managed application replicas.
Use a Deployment
Use a Deployment when the workload must stay available and evolve over time:
- web applications and HTTP APIs
- stateless microservices behind a Service
- multiple interchangeable replicas
- automatic Pod replacement after delete or node loss
- rolling updates and rollbacks between image versions
A Deployment can use replicas: 1. It is still useful for a single long-running stateless application because it replaces a missing Pod and provides controlled updates and rollback. The Deployment replica count defaults to one when omitted.
If the application must keep running after kubectl delete pod, start here rather than with a bare Pod.
Common scenarios
| Scenario | Recommended resource |
|---|---|
| Test whether an image starts | Pod |
| Run three web-server replicas | Deployment |
| Keep an API available after a Pod failure | Deployment |
| Study Pod phases and restart behaviour | Pod |
| Release a new application version gradually | Deployment |
| Run a database migration once | Job |
| Run one Pod on every node | DaemonSet |
| Run a stateful workload with stable identity | StatefulSet |
For Job, DaemonSet, and StatefulSet selection, see choose a Kubernetes workload resource.
Common Misunderstandings
| Misunderstanding | Correction |
|---|---|
| Deployment is a different container type | Both approaches run containers inside Pods |
| Deployment runs containers directly | Deployment manages ReplicaSets; ReplicaSets manage Pods |
| Several standalone Pods equal a Deployment | Independent Pods lack one reconciled replica count and rollout history |
| Container restart equals Pod replacement | Kubelet restart keeps the Pod; controller replacement creates a new Pod |
| Deployment fits every workload | Jobs, DaemonSets, and StatefulSets serve different workload requirements |
What's Next
- Kubernetes ReplicaSet with Examples
- Kubernetes StatefulSet with Examples
- Differences and When to Use Each
References
Summary
A Kubernetes Pod is the runnable unit; a Deployment is how you keep interchangeable Pods running at a desired replica count. The comparison table captures the decision in one glance: bare Pods suit tests and temporary work, while Deployments suit long-running stateless applications that must survive Pod deletion and accept controlled rollouts.
The lab walkthrough shows the practical gap. Deleting web-pod left nothing to recreate it, while deleting one Deployment-managed Pod triggered the ReplicaSet to mint a replacement with a new suffix. Scaling the Deployment to three replicas added a third Pod automatically — something independent Pod manifests do not provide as one managed set.
Remember the hierarchy — Deployment → ReplicaSet → Pods → containers — and separate the workload labels so a bare Pod cannot be adopted by the ReplicaSet. Do not confuse kubelet container restarts (restartPolicy) with controller-driven Pod replacement. When your scenario needs batch work, per-node agents, or stable identity, pick Job, DaemonSet, or StatefulSet instead. Follow the Pod lifecycle guide for inspection detail and the rolling updates guide when you are ready to change production images.

