The "Forbidden: User cannot create resource in namespace" error occurs when your Kubernetes user, service account, or IAM role lacks the necessary RBAC permissions to create resources in a specific namespace. This is a permissions issue that requires proper role and binding configuration.
This error indicates successful authentication (you're logged in) but insufficient authorization (you don't have permission). Kubernetes has successfully identified you, but the RBAC system denies your request because your user/service account isn't bound to a role that allows the requested action (create, get, patch, delete, etc.) for the resource type. Unlike Unauthorized (401) which means credentials are missing or invalid, Forbidden (403) means your credentials are valid but your permissions are too limited. You need explicit role bindings that grant you the required verbs (create, patch, delete) for your resource types (Deployments, Services, ConfigMaps, etc.).
Check who you are and what cluster you're connected to:
kubectl config current-context
kubectl whoami # Shows current user (if supported by your cluster)
kubectl config view --minify | grep -E "user:|name:" # Shows full user context
aws sts get-caller-identity # For AWS/EKS usersNote your username—you'll use it when creating role bindings.
Test whether you can perform actions:
kubectl auth can-i create deployments --namespace default
kubectl auth can-i create pods --as=system:serviceaccount:default:mysa -n default
kubectl auth can-i patch configmaps --namespace production
kubectl auth can-i delete secrets --all-namespacesThese return yes or no. The --as flag tests permissions for another user/service account. The --namespace flag checks specific namespaces.
See what roles exist and who they're bound to:
kubectl get roles -n <namespace>
kubectl get rolebindings -n <namespace>
kubectl describe role <role-name> -n <namespace> # See permissions in the role
kubectl describe rolebinding <binding-name> -n <namespace> # See who has the roleFor cluster-scoped permissions:
kubectl get clusterroles
kubectl get clusterrolebindings
kubectl describe clusterrole <role-name>Create a Role that allows creating/patching resources:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-developer
namespace: default
rules:
- apiGroups: [""] # Core API group (pods, services, configmaps, secrets)
resources: ["pods", "services", "configmaps"]
verbs: ["create", "get", "list", "patch", "delete"]
- apiGroups: ["apps"] # For Deployments, StatefulSets, etc.
resources: ["deployments", "statefulsets"]
verbs: ["create", "get", "list", "patch", "update", "delete"]Save as role.yaml and apply: kubectl apply -f role.yaml.
Connect your user to the role:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-developer-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: app-developer
subjects:
- kind: User
name: [email protected] # For certificate-based auth
apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
name: myapp-sa # For pod service accounts
namespace: defaultApply: kubectl apply -f rolebinding.yaml. Verify: kubectl describe rolebinding app-developer-binding -n default.
If you need permissions across namespaces or for cluster-scoped resources (namespaces, nodes, cluster roles):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-admin-limited
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["create", "get", "list"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "clusterrolebindings"]
verbs: ["get", "list"]Bind with ClusterRoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin-limited
subjects:
- kind: User
name: [email protected]Cloud platforms layer their own IAM on top of Kubernetes RBAC:
Azure AKS: Assign "Azure Kubernetes Service RBAC Cluster Admin" or "Container Contributor" at the resource level (not IAM roles). In Azure console, find your cluster and assign the role.
AWS EKS: Verify AWS IAM credentials and add user to aws-auth ConfigMap:
kubectl edit -n kube-system configmap/aws-auth
# Add under mapUsers:
- userarn: arn:aws:iam::123456789012:user/john
username: john
groups:
- system:masters # Full admin, or create custom groupsGCP GKE: Grant container.roles.create and container.admin in Google Cloud IAM console.
API groups are critical: core resources (pods, services) use apiGroups: [""], while apps (Deployments, StatefulSets) use apiGroups: ["apps"]. Always double-check documentation for the correct API group. For namespace-scoped operations, use Role + RoleBinding; for cluster-wide, use ClusterRole + ClusterRoleBinding. Azure AKS may use Azure RBAC (preview feature) which takes precedence over Kubernetes RBAC—check if enabled. Service accounts in pods inherit the permissions of their RoleBindings—ensure both pod service account name and namespace match bindings. In CI/CD (GitHub Actions, GitLab Runner), mount service account tokens properly and verify the service account has RoleBindings. Avoid using system:masters group except for true admin users—create custom groups for least privilege. Enable API server audit logging (--audit-log-maxage flag) to debug RBAC denials in production. Custom resource definitions (CRDs) require separate RBAC entries with correct apiGroup (e.g., apiGroups: ["mycompany.com"]).
No subnets found for EKS cluster
How to fix "eks subnet not found" in Kubernetes
unable to compute replica count
How to fix "unable to compute replica count" in Kubernetes HPA
error: context not found
How to fix "error: context not found" in Kubernetes
default backend - 404
How to fix "default backend - 404" in Kubernetes Ingress
serviceaccount cannot list resource
How to fix "serviceaccount cannot list resource" in Kubernetes