| Tested on | Rocky Linux 10.2 (Red Quartz) workstation |
|---|---|
| Package | kubectl 1.36.3 |
| Applies to | Bash-compatible Linux or macOS shell with kubectl configured; any compatible Kubernetes cluster |
| Cert prep | CKA · CKAD · CKS |
| Lab environment | Multi-node kubeadm cluster with containerd — install Kubernetes with kubeadm |
| Privilege | Normal user (no sudo required on the workstation) |
| Scope | Deployment replica counts and conditions, Deployment to ReplicaSet to Pod chain, selector and template label validation, ReplicaFailure and FailedCreate events, ResourceQuota and LimitRange routing, admission rejection patterns, ServiceAccount and reference checks, hidden Pod queries, stalled rollout routing, fix and verify steps, and error-to-fix tables. Does not cover full Deployment creation tutorials, ReplicaSet YAML depth, complete quota policy design, webhook administration, deep scheduling, full image-pull or crash-loop fixes, Service routing, or control-plane repair. |
| Related guides | Kubernetes Pod troubleshooting workflow |
0/3 READY, empty Pod lists, or FailedCreate on the ReplicaSet. It does not teach Deployment YAML from scratch or full rolling-update mechanics; see Deployments and rolling updates for rollout strategy. When Pods exist but fail after creation, route to the Pod error guides listed in the stalled rollout section instead of repeating those fixes here.
You applied a Deployment and expected Pods—but kubectl get pods is empty or short of spec.replicas. The controller chain is Deployment → ReplicaSet → Pod. This walkthrough builds that chain in deploy-lab, reads events at each layer, and routes Pod-level failures to the focused troubleshooting pages.
Quick reference
Start at the Deployment layer—Pod logs may not exist yet. Replace NS and DEPLOY with your namespace and Deployment name.
| Step | Command | What to check |
|---|---|---|
| 1 | kubectl get deployment DEPLOY -n NS |
READY versus spec.replicas; 0/0 is valid when scale is zero |
| 2 | kubectl describe deployment DEPLOY -n NS |
ReplicaFailure condition and controller events |
| 3 | kubectl get rs -n NS |
DESIRED greater than CURRENT points to FailedCreate on the ReplicaSet |
| 4 | kubectl describe rs RS -n NS |
Quota, LimitRange, admission webhook, or ServiceAccount errors |
| 5 | kubectl get pods -n NS -l LABEL |
Pods may exist under template labels but fail after creation |
| 6 | Route Pod-level failures | Pending, ImagePullBackOff, or CrashLoopBackOff → the matching Pod error guide — see stalled rollout routing |
Prepare the Deploy Lab
Create the namespace and baseline objects for the walkthrough:
kubectl apply -f - <<'YAML'
apiVersion: v1
kind: Namespace
metadata:
name: deploy-lab
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zero-replicas
namespace: deploy-lab
spec:
replicas: 0
selector:
matchLabels:
app: zero
template:
metadata:
labels:
app: zero
spec:
containers:
- name: app
image: nginx:1.27.0
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: deploy-lab
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: app
image: nginx:1.27.0
YAMLWait for the baseline Deployment to finish rolling out:
kubectl rollout status deployment/web -n deploy-lab --timeout=120sFollow the Deployment to ReplicaSet to Pod Chain
A Deployment does not create Pods directly. It creates or updates a ReplicaSet from spec.template, sets the ReplicaSet desired replica count, and lets the ReplicaSet controller create Pod objects. When the Deployment exists but Pods are missing, the break is usually at Pod creation by the ReplicaSet (FailedCreate) or on individual Pod scheduling—not a missing Deployment object. FailedCreate means the ReplicaSet could not create Pod objects, not that the Deployment failed to create the ReplicaSet. Rollout mechanics and revision history are in Deployments and rolling updates.
Confirm Replicas and Deployment Conditions
Start with the Deployment row—not Pod logs, which may not exist yet.
kubectl get deployment -n deploy-labSample output:
NAME READY UP-TO-DATE AVAILABLE AGE
web 2/2 2 2 9s
zero-replicas 0/0 0 0 9sREADY is displayed as ready replicas versus desired replicas, so 0/0 is valid for a Deployment intentionally scaled to zero.
READY, UP-TO-DATE, and AVAILABLE should align with spec.replicas on running workloads. A Deployment with replicas: 0 intentionally creates no Pods—0/0 READY is correct when scale is zero, not a controller failure.
Read conditions and events:
kubectl describe deployment zero-replicas -n deploy-lab | grep -A8 '^Conditions:'Sample output:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: zero-replicas-64c6598bc9 (0/0 replicas created)kubectl describe deployment also reports conditions that summarize controller health:
| Condition | Meaning |
|---|---|
Available |
Minimum replicas are available |
Progressing |
Rollout is active or completed successfully |
ReplicaFailure |
Replica creation failed |
ReplicaFailure=True with a message about failed creation points you to ReplicaSet events—not container logs.
Increase spec.replicas when you intended running Pods but see 0/0.
Find the Owned ReplicaSet
List ReplicaSets owned by Deployments in the namespace:
kubectl get replicasets -n deploy-labSample output:
NAME DESIRED CURRENT READY AGE
web-5b6bd7f99b 2 2 2 9s
zero-replicas-64c6598bc9 0 0 0 9s| Result | Continue with |
|---|---|
| No ReplicaSet exists | Deployment validation, conditions, and events |
ReplicaSet with DESIRED 0 |
Deployment replicas and rollout state |
ReplicaSet with DESIRED > 0 but CURRENT 0 |
ReplicaSet FailedCreate events |
| Pods exist but fail | Pod STATUS and the relevant error guide |
Show labels when multiple ReplicaSets share a namespace:
kubectl get rs -n deploy-lab -l app=web --show-labelsThe web ReplicaSet name includes a pod-template hash; old ReplicaSets may remain during rollouts.
Check Whether Pods Already Exist
Pods use template labels, not necessarily the Deployment's metadata.labels:
kubectl get pods -n deploy-lab -l app=webSample output:
NAME READY STATUS RESTARTS AGE
web-5b6bd7f99b-vkg6r 1/1 Running 0 9s
web-5b6bd7f99b-xxwmf 1/1 Running 0 9sIf unsure of namespace:
kubectl get pods --all-namespaces -l app=webConfirm you query spec.template.metadata.labels, not only the Deployment object name.
Fix Selector and Template Label Errors
spec.selector.matchLabels must match labels on spec.template.metadata.labels. Kubernetes rejects mismatches at create time:
kubectl apply -f - <<'YAML'
apiVersion: apps/v1
kind: Deployment
metadata:
name: bad-selector
namespace: deploy-lab
spec:
replicas: 1
selector:
matchLabels:
app: wrong-label
template:
metadata:
labels:
app: right-label
spec:
containers:
- name: app
image: nginx:1.27.0
YAMLSample output:
The Deployment "bad-selector" is invalid: spec.template.metadata.labels: Invalid value: {"app":"right-label"}: `selector` does not match template `labels`Fix template labels or selector before apply. The Deployment selector is immutable after creation—changing only metadata.labels on the Deployment object does not fix Pod template labels. Label and selector rules are covered in Kubernetes Labels and Selectors.
Diagnose ReplicaSet FailedCreate
When a ReplicaSet shows DESIRED 3 but CURRENT 0, describe the ReplicaSet for FailedCreate events after you confirm quota or admission blocked Pod creation.
ResourceQuota and LimitRange
Create the quota only after web Pods exist, then wait until both quota slots are consumed:
kubectl apply -f - <<'YAML'
apiVersion: v1
kind: ResourceQuota
metadata:
name: pod-quota
namespace: deploy-lab
spec:
hard:
pods: "2"
YAMLkubectl wait resourcequota/pod-quota -n deploy-lab --for=jsonpath='{.status.used.pods}'=2 --timeout=60sOnly then create quota-block:
kubectl apply -f - <<'YAML'
apiVersion: apps/v1
kind: Deployment
metadata:
name: quota-block
namespace: deploy-lab
spec:
replicas: 3
selector:
matchLabels:
app: quota
template:
metadata:
labels:
app: quota
spec:
containers:
- name: app
image: nginx:1.27.0
YAMLWait for the controller failure before reading events:
kubectl wait deployment/quota-block \
-n deploy-lab \
--for=jsonpath='{.status.conditions[?(@.type=="ReplicaFailure")].status}'=True \
--timeout=60sKubernetes documents insufficient quota as a cause of ReplicaFailure=True and ReplicaSet FailedCreate.
kubectl get resourcequota -n deploy-labSample output:
NAME REQUEST LIMIT AGE
pod-quota pods: 2/2 11skubectl describe replicaset -n deploy-lab -l app=quota | grep -A6 'FailedCreate'Sample output:
Warning FailedCreate 11s replicaset-controller Error creating: pods "quota-block-86c5c94577-ndlgf" is forbidden: exceeded quota: pod-quota, requested: pods=1, used: pods=2, limited: pods=2FailedCreate from the replicaset-controller means the API rejected Pod creation—no Pod object, no logs.
When events mention exceeded quota, inspect namespace quotas:
kubectl get resourcequota -n deploy-lab
kubectl describe resourcequota pod-quota -n deploy-labFix by raising quota, reducing other workloads, or lowering Deployment replicas. Full quota design and examples are in Kubernetes resource quota.
A LimitRange can inject default requests and limits or reject Pods that violate its minimum, maximum, or request-to-limit constraints. A compute ResourceQuota can separately reject Pods that omit required requests or limits. LimitRange defaults and constraints are separate behaviours; compute quotas can require resource declarations. Describe the ReplicaSet for limit-related FailedCreate text.
Admission Rejections
Search ReplicaSet and Deployment events for:
admission webhook denied the request- Pod Security Admission violations
- Disallowed registries or images
- Missing required labels or annotations
The event message names the rejecting controller or webhook. This article does not repair third-party admission products—use the message to identify which policy or webhook to fix.
Missing ServiceAccount
Verify Pod template references exist in the same namespace:
serviceAccountName- ConfigMap and Secret keys for env vars and volumes
- PVC names for volume claims
imagePullSecretsentries
Some missing references allow Pod creation but stall in ContainerCreating; others fail at admission. When Pods appear as Pending or ContainerCreating, use Fix Pending and ContainerCreating Pods.
Route Pods That Were Created but Failed
When an old ReplicaSet still runs but a new revision produces no healthy Pods, inspect the new ReplicaSet and its Pod events:
- Image pull failures → Fix ImagePullBackOff and ErrImagePull
- Scheduling or mount stalls → Fix Pending and ContainerCreating Pods
- Exit loops after start → Fix Kubernetes CrashLoopBackOff
- Readiness never true → Kubernetes health probes
Check progressDeadlineSeconds on the Deployment when ProgressDeadlineExceeded appears—the rollout may still be retrying unhealthy Pods. Rollout pause and revision details are in Deployments and rolling updates.
Fix and Verify the Deployment
After correcting replicas, labels, quota, or policy:
- Apply the fixed manifest
- Confirm a ReplicaSet exists with the expected
DESIREDcount - Confirm Pods appear with template labels
- Wait for Pods to become
Ready - Verify Deployment
AVAILABLEmatchesspec.replicas
Remove the deliberate quota failure before demonstrating recovery:
kubectl delete deployment quota-block -n deploy-lab
kubectl delete resourcequota pod-quota -n deploy-labkubectl scale deployment zero-replicas -n deploy-lab --replicas=1kubectl rollout status deployment/zero-replicas -n deploy-lab --timeout=120skubectl get deployment zero-replicas -n deploy-labkubectl get replicaset,pods -n deploy-lab -l app=zeroThe two existing web Pods consume the full pods: "2" quota, so zero-replicas cannot create a Pod until you remove or raise the quota, reduce another workload, or otherwise free a quota slot.
Troubleshoot Common Patterns
| Symptom or event | Likely cause | Fix |
|---|---|---|
READY 0/0, replicas: 0 |
Intentional scale to zero | Increase spec.replicas |
| Deployment invalid on apply | Selector/template label mismatch | Align labels before create |
| No ReplicaSet | Deployment conditions and create errors | Read Deployment events and validation output |
Deployment exists, zero Pods, RS DESIRED 0 |
replicas: 0 |
Scale Deployment up |
RS DESIRED 3, CURRENT 0, quota events |
Namespace pod quota full | Free Pods or raise quota |
exceeded quota: pod-quota |
ResourceQuota hard limit reached | Delete workloads or raise quota |
ReplicaFailure=True |
RS cannot create Pods | Describe RS for FailedCreate |
FailedCreate on ReplicaSet |
ResourceQuota, LimitRange, admission | Read event message for the rejecting controller |
admission webhook denied |
Policy or webhook rejection | Fix the named policy or webhook |
| Pods under wrong label query | Used Deployment metadata labels | Query template labels |
| New RS, zero ready, old RS still up | Bad rollout image or probes | Fix template; roll back if needed |
ProgressDeadlineExceeded |
New ReplicaSet Pod health | Inspect new RS Pods and rollout deadline |
What's Next
References
- Deployments — controller behaviour and conditions
- ReplicaSet — Pod creation from templates
- Resource quotas — namespace limits that block Pod creation
Summary
A Deployment with no Pods is rarely fixed at the Deployment layer alone. Confirm spec.replicas, then follow ReplicaSets and events. zero-replicas in deploy-lab correctly showed 0/0 READY; quota-block created a ReplicaSet but FailedCreate events blocked every Pod because pod-quota was already full from web.
Selector mismatches fail at apply time with an explicit validation error—fix labels before the Deployment exists. When ReplicaSets report FailedCreate, read quota, LimitRange, and admission messages; there are no container logs because no Pod was admitted.
Once Pods exist, failures belong on the Pod troubleshooting path—image pull, pending setup, crash loops, or probes. Use this page to reach the right ReplicaSet signal, then open the focused guide for the Pod STATUS you see.

