What Are RBAC Best Practices for Production Kubernetes?

advanced|rbacdevopssreplatform engineerCKA
TL;DR

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

  1. Disable token automounting on the default ServiceAccount
  2. Create workload-specific ServiceAccounts
  3. Define namespace-scoped Roles with least privilege
  4. Bind Roles to IdP groups via RoleBindings
  5. Apply NetworkPolicies to restrict ServiceAccount token access
  6. Set up audit logging for RBAC-related events
  7. 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

Why should you avoid binding to the cluster-admin ClusterRole?
cluster-admin grants unrestricted access to all resources in all namespaces. Even one compromised ServiceAccount with cluster-admin access can lead to full cluster takeover.
How do you handle RBAC for CI/CD pipelines?
Create dedicated ServiceAccounts per pipeline with minimal permissions scoped to the target namespace. Never share credentials between environments.
How do you audit existing RBAC permissions?
Use kubectl auth can-i --list for individual checks, or tools like rbac-lookup, kubectl-who-can, and rakkess for comprehensive auditing.

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.

Related Questions

You Might Also Like