March 12, 2026 · 7 min read

Kubernetes RBAC Best Practices — Secure Your Cluster Access

Kubernetes RBAC best practices: least privilege, Role vs ClusterRole, service account hardening, kubectl auth auditing, and avoiding common RBAC mistakes.

Kubernetes RBAC Best Practices — Secure Your Cluster Access

Kubernetes RBAC misconfiguration is one of the most common causes of security incidents in cloud-native environments. Over-permissive service accounts, inherited cluster-admin bindings, and undocumented role grants accumulate over time until a compromised pod has far more access than it should.

This guide covers Kubernetes RBAC best practices used in production clusters — from the principle of least privilege to auditing tools to policy enforcement with Kyverno.


Understanding RBAC Fundamentals

Kubernetes RBAC has four core objects:

  • Role — grants permissions within a single namespace
  • ClusterRole — grants permissions cluster-wide, or to cluster-scoped resources (nodes, PVs, namespaces)
  • RoleBinding — binds a Role or ClusterRole to subjects within a namespace
  • ClusterRoleBinding — binds a ClusterRole to subjects cluster-wide

The most common mistake is reaching for ClusterRole/ClusterRoleBinding when a Role/RoleBinding would be sufficient.

Rule of thumb: if the workload only operates in one namespace, use Role + RoleBinding. Reserve ClusterRole for:

  • Cluster-scoped resources (nodes, namespaces, persistent volumes)
  • Roles that need to be reused across multiple namespaces
  • Operators and controllers that watch resources cluster-wide

Principle of Least Privilege in Kubernetes

Least privilege means granting only the permissions required for a workload to function — nothing more.

In practice, this means:

1. Identify what your workload actually needs. Most application pods need zero Kubernetes API access. A web server serving HTTP requests doesn’t need to list pods or get secrets. If your app doesn’t call the Kubernetes API, disable the service account token mount entirely.

2. Start with no permissions and add incrementally. Don’t copy a broad role from another workload and prune later. Build from zero.

3. Use verbs precisely. The difference between get,list,watch (read-only) and get,list,watch,create,update,patch,delete (full CRUD) is enormous from a security standpoint.

4. Scope to specific resource names where possible. You can restrict access to a named resource:

rules:
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["my-app-db-credentials"]  # Only this secret
  verbs: ["get"]

Role vs ClusterRole: Decision Framework

Use this decision tree:

Does the workload need to access cluster-scoped resources?
  → YES: Use ClusterRole + ClusterRoleBinding

Does the workload need the same permissions in multiple namespaces?
  → YES: Use ClusterRole + RoleBinding (per-namespace binding, reuse the role)

Everything else:
  → Use Role + RoleBinding (namespace-scoped, tightly contained)

The ClusterRole + RoleBinding pattern is underused. You define the ClusterRole once (like a template), then bind it in each namespace where it’s needed. This is the right pattern for things like “read pods in namespace X” — you want namespace-scoped access, but you want to define the role centrally.

# Define once as a ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]

---
# Bind in a specific namespace only (not cluster-wide)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production   # Scoped to this namespace
subjects:
- kind: ServiceAccount
  name: my-app-sa
  namespace: production
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Service Account Best Practices

Service accounts are the identity for pods running in Kubernetes. They’re the most frequently misconfigured RBAC element.

1. Disable automatic service account token mounting for pods that don’t need API access:

spec:
  automountServiceAccountToken: false   # On the pod/deployment spec

Or at the service account level:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  namespace: production
automountServiceAccountToken: false

2. Create dedicated service accounts per workload — never use the default service account. The default SA is shared across all pods in the namespace that don’t specify an SA, which means permissions granted to default bleed across all workloads.

# Create a named SA for your app
apiVersion: v1
kind: ServiceAccount
metadata:
  name: order-service-sa
  namespace: production
  labels:
    app: order-service

3. Use short-lived projected tokens — the Kubernetes TokenRequest API creates time-limited tokens bound to specific audiences. These rotate automatically and expire, limiting the blast radius of a leaked token.

spec:
  serviceAccountName: my-app-sa
  volumes:
  - name: token
    projected:
      sources:
      - serviceAccountToken:
          audience: my-app
          expirationSeconds: 3600   # 1 hour, auto-renewed
          path: token

4. Review service account permissions regularly. Team members add RBAC grants during development and forget to scope or remove them. Schedule quarterly RBAC audits.


Auditing RBAC with kubectl auth can-i

kubectl auth can-i is your built-in RBAC auditing tool. Use it to verify both your own permissions and those of other subjects.

# Check your own permissions
kubectl auth can-i get pods -n production
kubectl auth can-i create secrets -n production

# Check all permissions in a namespace
kubectl auth can-i --list -n production

# Impersonate a service account to check its permissions
kubectl auth can-i --list \
  --as=system:serviceaccount:production:order-service-sa \
  -n production

# Check a specific action as a service account
kubectl auth can-i delete pods \
  --as=system:serviceaccount:production:order-service-sa \
  -n production

For cluster-wide auditing, kubectl-who-can (a krew plugin) answers the reverse question — “who can perform this action?”

# Install via krew
kubectl krew install who-can

# Who can delete pods in production?
kubectl who-can delete pods -n production

# Who can get secrets cluster-wide?
kubectl who-can get secrets

rbac-lookup is another useful tool for visualizing all bindings for a subject:

# Install via krew
kubectl krew install rbac-lookup

# Show all RBAC bindings for a service account
kubectl rbac-lookup order-service-sa -n production

Common RBAC Mistakes

Mistake 1: Binding cluster-admin to application service accounts

This is the most dangerous pattern. If a pod with cluster-admin SA is compromised, the attacker has full control over the entire cluster.

# Find all cluster-admin bindings (review these carefully)
kubectl get clusterrolebindings -o json | \
  jq '.items[] | select(.roleRef.name == "cluster-admin") | .metadata.name'

Mistake 2: Using the default service account

Any pod that doesn’t specify serviceAccountName gets the default SA. If you’ve granted anything to the default SA (common in tutorials), all pods in that namespace inherit those permissions.

# Find pods using the default SA
kubectl get pods -A -o json | \
  jq '.items[] | select(.spec.serviceAccountName == "default" or .spec.serviceAccountName == null) | "\(.metadata.namespace)/\(.metadata.name)"'

Mistake 3: Granting wildcard resources or verbs

# NEVER do this for production workloads
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]

This grants everything. Even resources: ["pods/*"] is too broad — it includes pods/exec which allows arbitrary code execution in any pod.

Mistake 4: Namespace-scoped bindings that escalate via cross-namespace access

If a workload in namespace A can list or read resources in namespace B via a ClusterRoleBinding, you’ve effectively broken namespace isolation. Audit ClusterRoleBindings carefully.

Mistake 5: No RBAC for CI/CD pipelines

CI/CD systems need to deploy to Kubernetes. A common mistake is creating a service account with cluster-admin for the CI pipeline. Instead, scope it to create,update,patch on deployments,services,configmaps in the namespaces where the pipeline deploys.


Policy Enforcement with OPA Gatekeeper and Kyverno

Manual RBAC hygiene breaks down at scale. Use policy engines to enforce RBAC rules automatically.

Kyverno (simpler, Kubernetes-native):

# Policy: Require all pods to set automountServiceAccountToken: false
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-no-automount-sa-token
spec:
  validationFailureAction: enforce
  rules:
  - name: check-automount
    match:
      resources:
        kinds: ["Pod"]
    validate:
      message: "automountServiceAccountToken must be false"
      pattern:
        spec:
          automountServiceAccountToken: false

OPA Gatekeeper (more powerful, uses Rego policy language):

# Constraint: Block use of default service account
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sNoDefaultServiceAccount
metadata:
  name: no-default-service-account
spec:
  match:
    kinds:
      - apiGroups: ["apps"]
        kinds: ["Deployment", "StatefulSet", "DaemonSet"]

Both tools integrate with admission webhooks — policies are enforced at creation time, before the resource is persisted in etcd.


RBAC Hardening Checklist

Before calling your RBAC posture production-ready, verify:

  • No application service accounts bound to cluster-admin
  • default service account has no role bindings in any namespace
  • automountServiceAccountToken: false on all pods that don’t call the K8s API
  • Dedicated SA per workload in every namespace
  • All ClusterRoleBindings documented and reviewed
  • kubectl auth can-i --list run for every SA in production
  • Kyverno or OPA enforcing SA and RBAC policies at admission

Generate Your RBAC Policies

Use our RBAC Policy Generator tool to generate Role and RoleBinding YAML for common patterns — read-only access, deployment manager, namespace admin, and more.

For comprehensive cluster security review including RBAC audit, see our K8s Security Hardening service at kubernetes.ae.

Get Expert Kubernetes Help

Talk to a certified Kubernetes expert. Free 30-minute consultation — actionable findings within days.

Talk to an Expert