Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 9 min read

Kubernetes Error Guide: 'ReplicaFailure: True' FailedCreate Forbidden Pods

Fix ReplicaFailure on a Deployment: decode the ReplicaSet's FailedCreate event when quota, RBAC, or Pod Security Admission forbids pod creation.

  • #kubernetes-helm
  • #troubleshooting
  • #errors
  • #workloads

Exact Error Message

A Deployment reports the desired number of replicas but no pods ever appear. The Deployment carries a ReplicaFailure condition, and the underlying ReplicaSet records a FailedCreate event explaining that the API server refused to create the pods:

$ kubectl describe deployment web
Conditions:
  Type             Status  Reason
  ----             ------  ------
  Available        False   MinimumReplicasUnavailable
  ReplicaFailure   True    FailedCreate

$ kubectl describe replicaset web-7d8f6c9b54
Events:
  Type     Reason        Age                From                   Message
  ----     ------        ----               ----                   -------
  Warning  FailedCreate  12s (x5 over 30s)  replicaset-controller  Error creating: pods "web-7d8f6c9b54-" is forbidden: exceeded quota: team-quota, requested: requests.cpu=2, used: requests.cpu=9, limited: requests.cpu=10

The headline is ReplicaFailure: True on the Deployment. The actionable detail is on the ReplicaSet: pods "..." is forbidden, followed by the admission decision that blocked the create.

What the Error Means

A Deployment does not create pods directly. It creates a ReplicaSet, and the ReplicaSet controller issues the create pod API calls. When those calls are rejected by an admission plugin, the ReplicaSet cannot reach its desired count and surfaces a FailedCreate event. The Deployment controller observes the failing ReplicaSet and sets a ReplicaFailure: True condition so the failure is visible one level up.

The crucial point is that this is not a scheduling problem. The pods are never admitted into the API at all, so they never reach Pending and the scheduler never sees them. The rejection happens at admission time, before persistence. The reason string after is forbidden: tells you exactly which gate said no — a ResourceQuota, RBAC, or Pod Security Admission.

Common Causes

  • ResourceQuota exceeded — the namespace ResourceQuota for requests.cpu, requests.memory, pods, or an object count is at its limit (exceeded quota).
  • Missing requests/limits under quota — a quota requires requests.cpu/limits.memory, but the pod template omits them (must specify requests.cpu).
  • Pod Security Admission — the namespace enforces a restricted PSA level and the pod template violates it (violates PodSecurity "restricted:latest").
  • RBAC on the service account — the controller’s service account or a webhook identity lacks permission, or a ValidatingAdmissionWebhook denies the pod.
  • LimitRange minimum/maximum — a LimitRange rejects the pod for requesting outside the allowed range.
  • Image pull secret / service account missing — referencing a non-existent service account is forbidden at create time.

How to Reproduce the Error

Create a tight quota, then a Deployment whose template omits resource requests it requires:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-quota
  namespace: demo
spec:
  hard:
    requests.cpu: "1"
    pods: "2"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: demo
spec:
  replicas: 3
  selector:
    matchLabels: { app: web }
  template:
    metadata:
      labels: { app: web }
    spec:
      containers:
        - name: app
          image: registry.k8s.io/pause:3.9
kubectl apply -f quota-and-deploy.yaml
kubectl get deployment web -n demo
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web    0/3     0            0           20s

READY 0/3 with no pods listed is the signature: the ReplicaSet exists but its create calls are rejected.

Diagnostic Commands

# Confirm the ReplicaFailure condition on the Deployment
kubectl get deployment <DEPLOY> -o jsonpath='{.status.conditions}'

# Find the active ReplicaSet and read its FailedCreate event
kubectl describe deployment <DEPLOY> | grep -i 'NewReplicaSet\|ReplicaFailure'
kubectl describe replicaset <RS> | grep -A6 Events

# Inspect quota usage vs hard limits in the namespace
kubectl get resourcequota -n <NS>
kubectl describe resourcequota -n <NS>

# Check Pod Security Admission labels on the namespace
kubectl get namespace <NS> -o jsonpath='{.metadata.labels}'

# Check any LimitRange constraints
kubectl get limitrange -n <NS> -o yaml

The describe replicaset Events block contains the verbatim admission decision — read everything after is forbidden:.

Step-by-Step Resolution

1. Read the forbidden reason on the ReplicaSet. The FailedCreate message names the gate. Route based on its first words:

exceeded quota: team-quota          -> ResourceQuota
violates PodSecurity "restricted"   -> Pod Security Admission
must specify requests.cpu           -> ResourceQuota requires requests
is forbidden: User ... cannot       -> RBAC / webhook

2. Fix a quota overage. Compare used vs hard, then either raise the quota or reduce the workload:

kubectl describe resourcequota -n <NS>
# Used requests.cpu 9, Hard 10, request 2 -> over by 1

Lower the pod template’s requests, scale replicas down, or have a cluster admin raise the hard limit.

3. Fix missing requests under quota. When a quota tracks a resource, every pod must declare it. Add explicit requests and limits to the template:

resources:
  requests: { cpu: "100m", memory: "64Mi" }
  limits:   { cpu: "250m", memory: "128Mi" }

4. Fix Pod Security Admission violations. The message lists each violation (runAsNonRoot, seccompProfile, allowPrivilegeEscalation). Update the pod’s securityContext to comply with the enforced level, or relax the namespace label if appropriate.

5. Fix RBAC / webhook denials. cannot create resource "pods" points at the service account or a webhook. Confirm the referenced service account exists and that any validating webhook backend is healthy:

kubectl get serviceaccount -n <NS>
kubectl get validatingwebhookconfigurations

6. Re-trigger the create. Editing the Deployment template rolls out a new ReplicaSet that retries admission. The controller also retries automatically with backoff, so once the gate is satisfied pods appear without manual intervention.

Prevention and Best Practices

  • Always set requests and limits on every container, especially in namespaces with a ResourceQuota — missing values turn into hard create failures.
  • Alert on the ReplicaFailure Deployment condition; it is the earliest signal that a rollout produced zero pods.
  • Keep quota headroom: size quotas with slack for rolling updates, which briefly run extra pods during a surge.
  • Test workloads against the target PSA level in CI so restricted violations are caught before deploy.
  • Treat 0/N READY with no pods as an admission problem, not a scheduling one, and go straight to the ReplicaSet events. See more in Kubernetes & Helm guides.

Frequently Asked Questions

Why is the condition on the Deployment but the message on the ReplicaSet? The Deployment controller only knows its child ReplicaSet is failing, so it raises the generic ReplicaFailure condition. The detailed reason lives where the create call was made — on the ReplicaSet’s events.

My pods never show up in kubectl get pods — is that normal here? Yes. The pods were rejected at admission and never persisted, so there is nothing to list. This distinguishes ReplicaFailure from a crash or scheduling stall, where pod objects do exist.

Does the controller keep retrying or do I have to redeploy? The ReplicaSet controller retries with exponential backoff indefinitely. Once you remove the blocking condition (raise quota, fix the template), pods are created on the next retry without a manual redeploy.

Quota says I have CPU free but it still fails — why? Quota counts requests already reserved by other pods, not live usage. A namespace can be idle yet have all its quota reserved. Compare against Used in kubectl describe resourcequota, not actual consumption.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.