What Are RBAC Best Practices for Production Kubernetes?
Production RBAC best practices include following least privilege, using namespaced Roles instead of ClusterRoles where possible, avoiding wildcard permissions, binding to groups instead of users, and regularly auditing role bindings.
Detailed Answer
RBAC is the primary authorization mechanism in Kubernetes. Getting it right in production requires disciplined practices around least privilege, role design, and ongoing auditing.
1. Follow the Principle of Least Privilege
Grant only the permissions absolutely needed for a workload or user to function:
# Good: Specific permissions for a CI/CD deployer
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: production
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "update", "patch"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# Bad: Overly broad permissions
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
2. Prefer Namespaced Roles Over ClusterRoles
Use Roles bound within a namespace whenever possible. Reserve ClusterRoles for truly cluster-wide needs:
| Use Case | Use | |----------|-----| | Deploy to a specific namespace | Role + RoleBinding | | Read Pods across all namespaces | ClusterRole + ClusterRoleBinding | | Manage CRDs | ClusterRole + ClusterRoleBinding | | Namespace-scoped operations | ClusterRole + RoleBinding (reusable role, scoped binding) |
The pattern of ClusterRole + namespace-scoped RoleBinding is powerful — define the role once, bind it per namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-viewer
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-team-viewer
namespace: team-a
subjects:
- kind: Group
name: dev-team-a
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: namespace-viewer
apiGroup: rbac.authorization.k8s.io
3. Bind to Groups, Not Users
Groups scale better than individual user bindings:
# Good: Bind to a group
subjects:
- kind: Group
name: platform-engineers
apiGroup: rbac.authorization.k8s.io
# Avoid: Binding to individual users
subjects:
- kind: User
name: alice@example.com
apiGroup: rbac.authorization.k8s.io
When Alice leaves the team, removing her from the IdP group automatically revokes her Kubernetes access. No RBAC changes needed.
4. Avoid Wildcard Permissions
Never use * for apiGroups, resources, or verbs in production:
# Never do this
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
Wildcards grant access to current and future resources, including CRDs you have not created yet. This violates least privilege.
5. Restrict Dangerous Permissions
Some permissions are particularly dangerous:
# Dangerous: Can exec into any Pod (read secrets from memory)
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
# Dangerous: Can read all secrets
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
# Dangerous: Can create privileged Pods
- apiGroups: [""]
resources: ["pods"]
verbs: ["create"]
# Dangerous: Can escalate their own permissions
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "clusterrolebindings"]
verbs: ["create", "update"]
6. Use resourceNames for Fine-Grained Control
Restrict access to specific resources by name:
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["app-config", "feature-flags"]
verbs: ["get", "update"]
This allows reading and updating only the named ConfigMaps, not all ConfigMaps in the namespace.
7. Secure Default ServiceAccounts
Every namespace has a default ServiceAccount that Pods use if none is specified. Restrict its permissions:
# Disable auto-mounting of the default SA token
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: production
automountServiceAccountToken: false
Create dedicated ServiceAccounts per workload:
apiVersion: v1
kind: ServiceAccount
metadata:
name: api-server
namespace: production
automountServiceAccountToken: true
8. Regular Auditing
# Check what a ServiceAccount can do
kubectl auth can-i --list --as=system:serviceaccount:production:deployer
# Find all ClusterRoleBindings to cluster-admin
kubectl get clusterrolebindings -o json | \
jq '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'
# List all subjects with cluster-admin access
kubectl get clusterrolebindings -o json | \
jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects[]'
# Use rbac-lookup for a comprehensive view
# kubectl rbac-lookup --kind=group
9. RBAC Checklist for New Namespaces
- Disable token automounting on the
defaultServiceAccount - Create workload-specific ServiceAccounts
- Define namespace-scoped Roles with least privilege
- Bind Roles to IdP groups via RoleBindings
- Apply NetworkPolicies to restrict ServiceAccount token access
- Set up audit logging for RBAC-related events
- Document who has access and why
10. Use Admission Control to Enforce RBAC Standards
Pair RBAC with admission control to prevent misuse:
# OPA Gatekeeper constraint: deny ClusterRoleBindings to cluster-admin
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockClusterAdmin
metadata:
name: deny-cluster-admin-binding
spec:
match:
kinds:
- apiGroups: ["rbac.authorization.k8s.io"]
kinds: ["ClusterRoleBinding"]
Why Interviewers Ask This
RBAC misconfiguration is one of the most common Kubernetes security issues. Interviewers ask this to evaluate your security mindset and operational maturity.
Common Follow-Up Questions
Key Takeaways
- Always start with zero permissions and add only what is needed — never start with cluster-admin.
- Bind Roles to Groups, not individual users, for scalable access management.
- Regularly audit RBAC bindings and remove unused ServiceAccounts and bindings.