Fix a Kubernetes Deployment Not Creating Pods

Diagnose a Kubernetes Deployment that creates no Pods by checking replicas, ReplicaSets, FailedCreate events, selectors, quotas, and admission errors.

Published

Updated

Read time 10 min read

Reviewed byDeepak Prasad

Kubernetes Deployment not creating Pods troubleshooting with ReplicaSet events quota and selectors
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
IMPORTANT
This guide fixes Deployments that never produce the expected ReplicaSet or Pod count—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:

bash
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
YAML

Wait for the baseline Deployment to finish rolling out:

bash
kubectl rollout status deployment/web -n deploy-lab --timeout=120s

Follow 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.

bash
kubectl get deployment -n deploy-lab

Sample output:

output
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
web             2/2     2            2           9s
zero-replicas   0/0     0            0           9s

READY 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:

bash
kubectl describe deployment zero-replicas -n deploy-lab | grep -A8 '^Conditions:'

Sample output:

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:

bash
kubectl get replicasets -n deploy-lab

Sample output:

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:

bash
kubectl get rs -n deploy-lab -l app=web --show-labels

The 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:

bash
kubectl get pods -n deploy-lab -l app=web

Sample output:

output
NAME                   READY   STATUS    RESTARTS   AGE
web-5b6bd7f99b-vkg6r   1/1     Running   0          9s
web-5b6bd7f99b-xxwmf   1/1     Running   0          9s

If unsure of namespace:

bash
kubectl get pods --all-namespaces -l app=web

Confirm 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:

bash
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
YAML

Sample output:

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:

bash
kubectl apply -f - <<'YAML'
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pod-quota
  namespace: deploy-lab
spec:
  hard:
    pods: "2"
YAML
bash
kubectl wait resourcequota/pod-quota -n deploy-lab --for=jsonpath='{.status.used.pods}'=2 --timeout=60s

Only then create quota-block:

bash
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
YAML

Wait for the controller failure before reading events:

bash
kubectl wait deployment/quota-block \
  -n deploy-lab \
  --for=jsonpath='{.status.conditions[?(@.type=="ReplicaFailure")].status}'=True \
  --timeout=60s

Kubernetes documents insufficient quota as a cause of ReplicaFailure=True and ReplicaSet FailedCreate.

bash
kubectl get resourcequota -n deploy-lab

Sample output:

output
NAME        REQUEST     LIMIT   AGE
pod-quota   pods: 2/2           11s
bash
kubectl describe replicaset -n deploy-lab -l app=quota | grep -A6 'FailedCreate'

Sample output:

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=2

FailedCreate from the replicaset-controller means the API rejected Pod creation—no Pod object, no logs.

When events mention exceeded quota, inspect namespace quotas:

bash
kubectl get resourcequota -n deploy-lab
kubectl describe resourcequota pod-quota -n deploy-lab

Fix 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
  • imagePullSecrets entries

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:

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:

  1. Apply the fixed manifest
  2. Confirm a ReplicaSet exists with the expected DESIRED count
  3. Confirm Pods appear with template labels
  4. Wait for Pods to become Ready
  5. Verify Deployment AVAILABLE matches spec.replicas

Remove the deliberate quota failure before demonstrating recovery:

bash
kubectl delete deployment quota-block -n deploy-lab
kubectl delete resourcequota pod-quota -n deploy-lab
bash
kubectl scale deployment zero-replicas -n deploy-lab --replicas=1
bash
kubectl rollout status deployment/zero-replicas -n deploy-lab --timeout=120s
bash
kubectl get deployment zero-replicas -n deploy-lab
bash
kubectl get replicaset,pods -n deploy-lab -l app=zero

The 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


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.


Frequently Asked Questions

1. Why does my Kubernetes Deployment have no Pods?

If the Deployment exists but has no Pods, first check spec.replicas and whether its ReplicaSet reports FailedCreate. A selector/template-label mismatch instead causes the Deployment apply request to be rejected. If Pod objects exist but show Pending, ImagePullBackOff, or CrashLoopBackOff, continue with Pod-level troubleshooting. Deployment selectors are immutable after creation, and selector/template labels must agree.

2. Does a Deployment create Pods directly?

No. A Deployment manages ReplicaSets. Each ReplicaSet creates Pods from the Pod template. When Pods are missing, inspect the ReplicaSet events even if the Deployment object exists.

3. What does ReplicaFailure on a Deployment mean?

The Deployment controller could not maintain the desired replica count—often because the ReplicaSet could not create Pods. Read the ReplicaFailure message and describe the ReplicaSet for FailedCreate events.

4. Can ResourceQuota stop a Deployment from creating Pods?

Yes. When the namespace pod quota is full, the replicaset-controller reports FailedCreate with exceeded quota in events. No Pod object is created, so there are no application logs.

5. Why was my Deployment rejected with selector does not match template labels?

spec.selector.matchLabels must be a subset of spec.template.metadata.labels. Kubernetes rejects the Deployment at admission when they disagree. Fix labels before apply or create a new Deployment with a new selector.

6. I scaled to three replicas but only see two Pods—what do I check?

Compare Deployment AVAILABLE to spec.replicas, then describe the ReplicaSet for FailedCreate. Quota, LimitRange, admission webhooks, and scheduling failures on individual Pods each show up in different event messages.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)