Your Kubernetes operation fails with Error from server (Forbidden): ... or pods can't access the Kubernetes API. RBAC (Role-Based Access Control) governs who can do what in Kubernetes, and permission denied errors indicate authorization failures. Understanding RBAC is essential for both cluster administration and application development.
Introduction
This article covers troubleshooting steps and solutions for Fix Kubernetes RBAC Permission Denied Error. The error typically occurs in production environments and can cause service disruptions if not addressed promptly.
Symptoms
Common error messages include:
```bash # For kubectl commands, check current user kubectl config current-context kubectl auth whoami
# For pods, check service account kubectl get pod pod-name -n namespace -o jsonpath='{.spec.serviceAccountName}' ```
```bash # Test if you can perform specific action kubectl auth can-i get pods -n namespace
# Test as specific service account kubectl auth can-i get pods -n namespace --as=system:serviceaccount:namespace:sa-name
# Test as specific user kubectl auth can-i get pods -n namespace --as=user@example.com
# List all allowed actions kubectl auth can-i --list -n namespace ```
```bash # List roles in namespace kubectl get roles -n namespace kubectl describe role role-name -n namespace
# List role bindings kubectl get rolebindings -n namespace kubectl describe rolebinding binding-name -n namespace
# Cluster-wide kubectl get clusterroles kubectl get clusterrolebindings ```
Common Causes
- Configuration misconfiguration
- Missing or incorrect credentials
- Network connectivity issues
- Version compatibility problems
- Resource exhaustion or limits
- Permission or access denied
Understanding Kubernetes RBAC
RBAC controls API access based on roles assigned to users, groups, or service accounts. Permission denied means the requesting identity lacks the necessary role or role binding. The RBAC system checks: who is making the request (subject), what they want to do (verb), and what resource they're accessing (resource).
Step-by-Step Fix
Identify the requesting identity:
```bash # For kubectl commands, check current user kubectl config current-context kubectl auth whoami
# For pods, check service account kubectl get pod pod-name -n namespace -o jsonpath='{.spec.serviceAccountName}' ```
Check existing permissions:
```bash # Test if you can perform specific action kubectl auth can-i get pods -n namespace
# Test as specific service account kubectl auth can-i get pods -n namespace --as=system:serviceaccount:namespace:sa-name
# Test as specific user kubectl auth can-i get pods -n namespace --as=user@example.com
# List all allowed actions kubectl auth can-i --list -n namespace ```
Check roles and bindings:
```bash # List roles in namespace kubectl get roles -n namespace kubectl describe role role-name -n namespace
# List role bindings kubectl get rolebindings -n namespace kubectl describe rolebinding binding-name -n namespace
# Cluster-wide kubectl get clusterroles kubectl get clusterrolebindings ```
Common Solutions
Solution 1: Create Missing Role
Define the required permissions:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: namespace
name: pod-reader
rules:
- apiGroups: [""] # Core API group
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]For more permissions:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: namespace
name: deployment-manager
rules:
- apiGroups: ["", "apps", "extensions"]
resources: ["deployments", "replicasets", "pods", "services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]Solution 2: Create RoleBinding
Bind role to subject:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: namespace
name: pod-reader-binding
subjects:
- kind: ServiceAccount
name: default
namespace: namespace
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioFor user binding:
```yaml subjects: - kind: User name: user@example.com apiGroup: rbac.authorization.k8s.io
# For group subjects: - kind: Group name: developers apiGroup: rbac.authorization.k8s.io ```
Solution 3: Create ClusterRole for Cross-Namespace Access
ClusterRoles work across all namespaces:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]Bind with ClusterRoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: node-reader-binding
subjects:
- kind: ServiceAccount
name: monitoring
namespace: monitoring
roleRef:
kind: ClusterRole
name: node-reader
apiGroup: rbac.authorization.k8s.ioSolution 4: Fix Service Account Configuration
Pods use the default service account unless specified:
# Specify custom service account
spec:
serviceAccountName: custom-saCreate dedicated service account:
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: namespace
name: custom-saCheck if token is mounted:
```bash # Verify token exists in pod kubectl exec pod-name -n namespace -- ls /var/run/secrets/kubernetes.io/serviceaccount/
# Check token content kubectl exec pod-name -n namespace -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ```
Solution 5: Fix API Group Specification
Resources belong to specific API groups:
```yaml # Common API groups: # "" (empty) - Core resources: pods, services, configmaps, secrets, namespaces # "apps" - Deployments, StatefulSets, DaemonSets, Replicasets # "batch" - Jobs, CronJobs # "networking.k8s.io" - Ingress, NetworkPolicy # "rbac.authorization.k8s.io" - Roles, RoleBindings
# WRONG: Missing API group for deployments rules: - apiGroups: [""] # Wrong - deployments are in apps resources: ["deployments"]
# CORRECT: rules: - apiGroups: ["apps"] resources: ["deployments", "statefulsets"] ```
Solution 6: Fix Verb Specification
Verbs define allowed actions:
```yaml # Common verbs: # get - Read single resource # list - Read multiple resources # watch - Stream updates # create - Create new resource # update - Update existing resource # patch - Partial update # delete - Delete resource
# For read-only access verbs: ["get", "list", "watch"]
# For full access verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# For specific subresources rules: - apiGroups: [""] resources: ["pods", "pods/log", "pods/exec"] # pods/log, pods/exec are subresources verbs: ["get"] ```
Solution 7: Fix Resource Names Restrictions
Roles can restrict to specific resources:
# Restrict to specific resource names
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["app-config", "app-secrets"] # Only these specific ConfigMaps
verbs: ["get", "update"]Remove resourceNames for broader access:
# Without resourceNames - all ConfigMaps in namespace
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "create", "update"]Solution 8: Use Aggregated ClusterRoles
Combine existing roles:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-view
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
- matchLabels:
monitoring: "true"
rules: [] # Controller fills in from aggregated rolesCreate label for aggregation:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-metrics-reader
labels:
monitoring: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
resources: ["pods"]
verbs: ["get", "list"]Verification
After applying RBAC changes:
```bash # Test permission kubectl auth can-i get pods -n namespace --as=system:serviceaccount:namespace:sa-name
# Test in pod kubectl exec pod-name -n namespace -- curl -s -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default/api/v1/namespaces/namespace/pods
# Verify role binding kubectl describe rolebinding binding-name -n namespace ```
Check effective permissions:
# List all permissions for identity
kubectl auth can-i --list -n namespace --as=system:serviceaccount:namespace:sa-nameCommon RBAC Permission Errors
| Error | Cause | Solution |
|---|---|---|
Forbidden on pods | No role for pods | Create Role with pods resource |
Forbidden on deployments | Wrong API group | Use apiGroups: ["apps"] |
Forbidden cross-namespace | Role is namespace-scoped | Use ClusterRole |
Forbidden for exec | Missing pods/exec | Add pods/exec subresource |
Forbidden for logs | Missing pods/log | Add pods/log subresource |
| ServiceAccount token invalid | Wrong SA in pod | Set correct serviceAccountName |
| User cannot access cluster | No ClusterRoleBinding | Create binding for user/group |
RBAC Best Practices
Use namespace-scoped Roles for most permissions. Create dedicated service accounts for applications. Avoid overly broad permissions (limit verbs/resources). Use ClusterRoles sparingly, only when necessary. Document RBAC requirements for applications. Audit RBAC regularly for unnecessary permissions. Use aggregated roles for standard permissions sets.
RBAC permission denied errors require checking who (subject) lacks what (role/binding). Create the appropriate Role/ClusterRole with correct resources and verbs, then bind it to the subject needing access.
Related Articles
- [Fix Envoy Rate Limit Configuration with envoyproxy/ratelimit](envoyproxy-ratelimit-configuration-guide)
- [Fix Fix Argocd App Not Syncing Issue in Kubernetes](fix-argocd-app-not-syncing)
- [Fix Fix Argocd Sync Conflict Issue in Kubernetes](fix-argocd-sync-conflict)
- [Fix ArgoCD Sync Timeout](fix-argocd-sync-timeout)
- [How to Fix Cilium Identity Exhaustion and Endpoint Allocation Failed](fix-cilium-identity-exhaustion)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Kubernetes RBAC Permission Denied Error", "description": "Learn how to fix Kubernetes RBAC permission denied errors including role configuration, binding issues, and service account permissions.", "url": "https://www.fixwikihub.com/fix-kubernetes-rbac-permission-denied", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-11-18T20:48:25.436Z", "dateModified": "2025-11-18T20:48:25.436Z" } </script>