Blog · October 28, 2025 · Updated on September 7, 2026 · 9 min read

Kubernetes RBAC: Roles and Permissions

Bunch of several different keys resting on a dark textured surface
Photo: George Becker / Pexels

Kubernetes RBAC (Role Based Access Control) determines who can perform which action on which resource in a cluster, through a combination of roles and bindings. On every request to the API, Kubernetes checks whether the requesting person, group or service account holds a matching permission, otherwise the API server rejects the request. One sentence up front, because it clears up the most common misunderstanding: RBAC is not user management. Who you are is settled by authentication, through a certificate, a token or a connected identity provider. RBAC only answers the next question, what you may do as that already established identity. Kubernetes never creates user accounts itself. Without a well thought out RBAC setup, most clusters end up with either far too little or far too much access, and neither works in production.

I run production Kubernetes clusters with roles and permissions built on exactly this model, and I wrote the Kubernetes Practical Guide for Rheinwerk Computing (2024). You can find this article together with all my other Kubernetes topics on my Kubernetes page.

Who can do what: the RBAC model in Kubernetes

Before you create a single role, it helps to look at the three kinds of actors RBAC applies to in the first place. People typically reach the cluster through a kubeconfig, with their name sitting in the common name field of their certificate or coming from an external identity provider. Groups bundle several people together, so you do not have to assign a role to every developer individually but to the whole group at once. Service accounts, finally, are Kubernetes' own identity for pods: every namespace automatically gets a default service account, which applications and processes inside their pods use to talk to the Kubernetes API.

Kubernetes does not manage users and groups itself, that needs an external connection, for example through a certificate, OIDC, or a tool that issues a matching kubeconfig for every person. Service accounts, on the other hand, are proper Kubernetes objects: you create them, bind a role to them, and reference them in the pod.

For an actor to be allowed to do anything at all, you need two parts: a role that describes which actions on which resources are permitted, and a binding that assigns that role to an actor. Without a binding, even the most carefully defined role stays inert, it just sits in the cluster as a definition that nobody benefits from.

Role, ClusterRole and their matching bindings

A Role only applies within a single namespace, a ClusterRole applies cluster-wide or serves as a reusable template. Each of the two has a matching binding that assigns the role to an actor:

Object Scope Job
Role one namespace defines permissions for resources within that namespace
ClusterRole the whole cluster or reusable defines permissions for cluster-scoped resources or as a template for several namespaces
RoleBinding one namespace assigns a Role or ClusterRole to an actor within that namespace
ClusterRoleBinding the whole cluster assigns a ClusterRole to an actor cluster-wide

One detail that gets overlooked in practice: you can assign a ClusterRole through a plain RoleBinding. In that case the permissions only apply within the namespace the RoleBinding lives in, even though the role itself is defined cluster-wide. That saves you from rewriting the same permissions as a separate Role in every namespace.

Inside a role, three fields determine exactly what is allowed: apiGroups groups related resources, the empty group "" stands for core resources such as Pods or Services, apps for example covers Deployments. resources lists the specific object types the role applies to. verbs defines which operations are allowed, among them get, list, watch, create, update, patch, delete and deletecollection. Run kubectl api-resources --sort-by name -o wide to see every object type in your cluster at a glance, including the API group it belongs to.

The following example lets a group of developers read Deployments in the team-shop namespace, but not change them:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deployment-reader
  namespace: team-shop
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: team-shop-read-deployments
  namespace: team-shop
subjects:
  - kind: Group
    name: team-shop-dev
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: deployment-reader
  apiGroup: rbac.authorization.k8s.io

The Role defines the permissions, the RoleBinding assigns them to the team-shop-dev group, and both only apply within the team-shop namespace. Following the least privilege principle, you always grant only the verbs and resources a role actually needs, never more.

Service accounts: identity for pods and automation

A namespace's default service account has practically no rights for good reason, it only serves authentication. For every application that actually needs to talk to the Kubernetes API, you therefore create a dedicated service account and bind it, through a Role or ClusterRole, to exactly the permissions that application needs.

The best way to check whether that setup works is before the pod even runs. kubectl auth can-i simulates a request with any actor's permissions:

kubectl auth can-i list deployments \
  --as=system:serviceaccount:team-shop:ci-deployer \
  --namespace=team-shop

The command answers with yes or no, without you having to roll out a real pod first. The same way, kubectl auth can-i --list --as=system:serviceaccount:team-shop:ci-deployer shows you every permission a service account holds at a glance, which is far faster during troubleshooting than piecing every single permission together by hand.

If a pod needs no access to the Kubernetes API at all, the cleanest option is to turn off the automatic token mount entirely with automountServiceAccountToken: false in the pod spec. When a pod does need the token, the kubelet mounts it as a projected volume with a limited lifetime and automatic renewal, rather than parking it as a Secret in the namespace. How other sensitive values reach a pod is covered in ConfigMap and Secret in Kubernetes.

Limiting a development team to one namespace

A pattern I set up in almost every client cluster: each team gets its own namespace, more on that in Kubernetes Namespaces Done Right, and a RoleBinding that gives the team broad rights inside that namespace and none at all outside it.

Kubernetes already ships with matching ClusterRoles for this: view for read-only access, edit for creating and changing most objects without managing permissions, admin which additionally lets you grant further roles within the namespace, and cluster-admin for unrestricted access to the entire cluster. For a development team, edit is usually enough, bound through a namespace-scoped RoleBinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: team-shop-edit
  namespace: team-shop
subjects:
  - kind: Group
    name: team-shop-dev
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: edit
  apiGroup: rbac.authorization.k8s.io

That lets the team do almost anything inside its own namespace, while it sees neither other teams' objects nor cluster-scoped resources such as nodes or namespaces themselves. That is the difference between a team that can work productively and a team that accidentally changes someone else's namespace.

Auditing permissions and avoiding common RBAC mistakes

The most common mistake I see in clusters that have grown over time is the pragmatic shortcut under time pressure: cluster-admin for everyone, because otherwise a permission always seems to be missing. That works right up until a single compromised pod or a misconfigured kubeconfig is enough to take over the entire cluster. Wildcards in resources or verbs are just as risky: a star in the verbs is practically equivalent to cluster-admin for the affected resources, just less visible in the manifest.

More RBAC best practices from my own work: bind roles to groups rather than individual people, so a team change means updating group membership instead of hunting down ten bindings. Audit permissions regularly, not only when you create them: kubectl auth can-i --list --as=<subject> shows you, for any actor, what they can actually do right now, and reliably surfaces forgotten bindings. And checking kubectl get rolebindings,clusterrolebindings -A is a fixed part of every security review I run, because an astonishing amount accumulates there over months that nobody needs anymore.

RBAC for GitOps, CI and operators

Automated actors need permissions thought through just as carefully as people, often more urgently, because they do not pause to reconsider when a permission is too broad. A CI pipeline that rolls out Deployments into a namespace gets its own service account with a role covering exactly the resources and verbs it needs for that, but for example no access to secrets in other namespaces.

A GitOps controller that keeps an eye on many namespaces at once, on the other hand, almost inevitably needs a ClusterRole, because it has to read and reconcile objects cluster-wide. It still pays off to keep write permissions as narrow as possible, scoped to the projects or applications actually managed, instead of using one single, very powerful ClusterRole for everything. Operators that bring their own custom resources also need a ClusterRole, because they watch their CRDs cluster-wide, but the actual instances of those resources can still be further constrained through namespaces and additional roles. Starting with the smallest roles possible from day one means you never trade the whole cluster for one compromised automation account later.

Frequently asked questions

What is the difference between Role and ClusterRole?

A Role only applies within the namespace it lives in, a ClusterRole either applies cluster-wide or serves as a reusable template that you can still make effective in a single namespace only, through a RoleBinding. Plain namespace permissions usually need only a Role, cluster-scoped resources such as nodes or reusable role templates need a ClusterRole.

How do I give a user read-only access?

Bind the built-in view ClusterRole to the user or their group through a RoleBinding in the target namespace, then they can see everything there but change nothing. For a single, very narrow read permission, say only on Deployments, define your own Role with the verbs get, list and watch instead.

How do I see which permissions a service account has?

The fastest way is kubectl auth can-i --list --as=system:serviceaccount:<namespace>:<name>. The command lists every resource and verb the service account can actually use, without you first having to piece together every role and binding by hand.

Is RBAC enough to secure a Kubernetes cluster?

No, RBAC only controls who can perform which action on which Kubernetes resource, not what happens inside a container. A pod with overly broad container permissions can still endanger the node despite clean RBAC, for that you additionally need Pod Security Standards and ongoing monitoring of cluster behavior.

Where to go next

The next building block for a secure cluster is the security context of individual pods, more on that in Kubernetes Pod Security Standards. My suggestion for today: run kubectl auth can-i --list across your most important namespaces and check how many bindings there are actually still needed. The full reference for all RBAC objects is in the Kubernetes documentation on RBAC, and details on authenticating users are in the documentation on authentication.

In full detail with all examples, this is covered in chapter 7 of my Kubernetes Practical Guide (Rheinwerk Computing).

Kevin Welter

Kevin Welter

Developer, IT architect, author of technical books (Kubernetes, cloud infrastructures) and speaker. Runs his business with an AI workforce of eight AI employees and shows solo business owners in his community how to hire their first AI employee.

More about AI employees

Kubernetes from the basics to a production-ready cluster

Get the book