← Back to Blog

2026-03-09

Kubernetes RBAC: Control Who Can Do What in Your Cluster

A hands-on guide to Kubernetes Role-Based Access Control — understand Roles, ClusterRoles, RoleBindings, and ServiceAccounts with real YAML examples.

In a Kubernetes cluster, every action — listing pods, creating deployments, deleting secrets — goes through the API server. Without a proper access control strategy, any process or user with cluster access can do anything. That's where RBAC (Role-Based Access Control) comes in.

RBAC lets you define precisely who can do what to which resources in your cluster. It's the standard and recommended way to enforce the principle of least privilege in Kubernetes.

The Core Question RBAC Answers

"Can this user (or service account) perform this action on this resource?"

Every request to the Kubernetes API server is checked against RBAC rules before it's allowed or denied.


Key Concepts

Roles and ClusterRoles

A Role defines a set of permissions within a specific namespace. A ClusterRole does the same but applies cluster-wide.

Permissions in Kubernetes are always additive — nothing is allowed unless you explicitly grant it. There is no "deny" rule; if a permission isn't defined, it's simply not there.

Each rule in a Role specifies:

  • apiGroups — the API group the resource belongs to ("" for core resources like pods and services, "apps" for deployments)
  • resources — the Kubernetes objects the rule applies to (pods, services, deployments, etc.)
  • verbs — the allowed actions (get, list, watch, create, update, delete, patch)

RoleBindings and ClusterRoleBindings

A RoleBinding connects a Role to a subject — a user, a group, or a service account — within a namespace. A ClusterRoleBinding does the same at the cluster level.

Without a binding, a Role has no effect. Roles and bindings are two separate objects that work together.

Subjects

A subject is the entity being granted permissions. Kubernetes recognizes three subject types:

  • User — human users authenticated via certificates, tokens, or external providers
  • Group — a collection of users
  • ServiceAccount — an identity attached to pods and workloads running inside the cluster

Built-in ClusterRoles

Kubernetes ships with several ready-to-use ClusterRoles:

| ClusterRole | Access Level | |-------------|-------------| | cluster-admin | Full unrestricted control over everything | | admin | Broad read/write access within a namespace | | edit | Create and update most objects, no access to Roles | | view | Read-only access to most namespace objects |

These are useful defaults, but for production environments you should define your own narrowly-scoped roles.


A Real-World Example: Scoping a Developer to One Namespace

Let's walk through a complete, practical setup. The goal: give a developer (dev-user) access to the dev namespace — enough to work with pods, services, configmaps, and secrets, but nothing more.

Step 1 — Create the Namespace

kubectl create namespace dev

Step 2 — Create a ServiceAccount

Rather than creating a Kubernetes user (which requires certificate management), we'll use a ServiceAccount. Service accounts are managed natively by Kubernetes and are the preferred identity mechanism for automation and programmatic access.

# service-account.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: dev-user
  namespace: dev

Apply it:

kubectl apply -f service-account.yml

Step 3 — Define a Role

This Role grants the dev-user permission to manage core resources within the dev namespace.

# dev-role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: dev-role
  namespace: dev
rules:
  - apiGroups: [""]
    resources: ["pods", "services", "configmaps", "secrets"]
    verbs: ["get", "list", "watch", "create", "update", "delete"]

A few things to notice:

  • apiGroups: [""] — the empty string refers to the core API group, which includes pods, services, configmaps, and secrets
  • verbs define the full set of allowed actions. If you wanted read-only access, you'd limit this to ["get", "list", "watch"]
  • To also grant access to deployments, you'd add a second rule targeting the apps API group:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch", "create", "update"]

Apply the role:

kubectl apply -f dev-role.yml

Step 4 — Bind the Role to the ServiceAccount

A RoleBinding connects the dev-role to the dev-user service account in the dev namespace.

# rolebinding.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-role-binding
  namespace: dev
subjects:
  - kind: ServiceAccount
    name: dev-user
    namespace: dev
roleRef:
  kind: Role
  name: dev-role
  apiGroup: rbac.authorization.k8s.io

Apply it:

kubectl apply -f rolebinding.yml

Or apply all three manifests at once if they're in the same directory:

kubectl apply -f kubernetes-rbac/

Verifying Access

Before wiring up credentials, you can verify permissions directly using kubectl auth can-i:

# Check if dev-user can list pods in the dev namespace
kubectl auth can-i list pods --namespace=dev --as=system:serviceaccount:dev:dev-user

# Check if dev-user can create deployments (should be denied)
kubectl auth can-i create deployments --namespace=dev --as=system:serviceaccount:dev:dev-user

Using the ServiceAccount as a Kubeconfig Context

To actually use the dev-user service account from kubectl, you need to generate a token and associate it with a kubeconfig context.

Step 5 — Generate a Token

kubectl create token dev-user -n dev

This creates a short-lived token for the service account. Copy the output — you'll use it in the next step.

Step 6 — Set Up Credentials

Register the token with kubectl:

kubectl config set-credentials dev-user --token=<paste-token-here>

Step 7 — Create a Context

A context ties together a cluster, a user, and a namespace:

kubectl config set-context dev-user-context \
  --cluster=<your-cluster-name> \
  --user=dev-user \
  --namespace=dev

Replace <your-cluster-name> with the name of your cluster as it appears in kubectl config get-clusters.

Step 8 — Switch to the Context

kubectl config use-context dev-user-context

Step 9 — Test Live Access

# Should work
kubectl get pods
kubectl get services

# Should be denied (deployments not in the role)
kubectl get deployments

# Switch back to your admin context when done
kubectl config use-context <your-admin-context>

Role vs ClusterRole: When to Use Which

| | Role | ClusterRole | |---|---|---| | Scope | Single namespace | All namespaces or cluster-level resources | | Can grant access to | Namespace resources | Namespace resources + cluster-scoped resources (nodes, PVs, etc.) | | Bound with | RoleBinding | ClusterRoleBinding (or RoleBinding for namespace-scoped use) |

A useful pattern: define a ClusterRole with common permissions, then bind it to specific namespaces using RoleBindings. This avoids duplicating Role definitions across namespaces while still keeping access namespace-scoped.

# Re-use the built-in 'edit' ClusterRole but scope it to the 'dev' namespace only
kubectl create rolebinding dev-edit-binding \
  --clusterrole=edit \
  --serviceaccount=dev:dev-user \
  --namespace=dev

Common Mistakes

Forgetting the namespace in the RoleBinding subjects block

When binding a ServiceAccount, always specify the namespace field under subjects. Without it, the binding may silently fail or bind to the wrong account.

Using ClusterRoleBinding when you mean RoleBinding

A ClusterRoleBinding grants cluster-wide access. If you only want a developer to work in one namespace, use RoleBinding — not ClusterRoleBinding.

Over-permissive verbs

Granting ["*"] as verbs or resources is the equivalent of giving full admin access. Always list the specific verbs and resources your subject actually needs.

Not rotating tokens

The kubectl create token command generates short-lived tokens by default. For longer-lived automation, use projected service account token volumes in your pod specs rather than static tokens.


Summary

Kubernetes RBAC is built around four objects:

  1. Role / ClusterRole — defines what actions are allowed on which resources
  2. RoleBinding / ClusterRoleBinding — attaches a role to a subject
  3. ServiceAccount — provides an identity for workloads and programmatic access

The setup flow is always the same: create a ServiceAccount, define a Role with the minimum required permissions, bind the Role to the account with a RoleBinding, and verify with kubectl auth can-i.

Start narrow. It's always easier to grant more access later than to revoke it after something goes wrong.