
Last time I set up a role that let a user mess with pods in one namespace. Then I tried the same trick on a node and it just wouldn't work, no matter how I wrote the rule. Turns out a normal Role literally can't reach a node, because a node doesn't live in a namespace. That gap is the whole reason ClusterRoles exist, and it's what today is about.
If you've not read Topic 9 on RBAC yet, start there, because this builds straight on it. Same format as always: what it is, how it works, why it matters, one takeaway.
The split nobody tells you about first
Here's the thing that unlocks all of this: Kubernetes resources come in two flavours, and where a resource lives decides which RBAC objects can control it.
Namespaced resources live inside a namespace. Pods, deployments, services, secrets, jobs, replica sets. When you say "the pods in default", the namespace is part of the address. A Role and RoleBinding cover these, scoped to that one namespace.
Cluster-scoped resources don't belong to any namespace at all. A node is a physical or virtual machine, and it just is, cluster-wide. Same with persistent volumes (chunks of storage), namespaces themselves, and certificate signing requests. There's no namespace in their address, so a namespaced Role has nothing to grab onto.
You don't have to memorise which is which. Ask the cluster:
# everything that lives in a namespace
kubectl api-resources --namespaced=true
# everything that doesn't (nodes, PVs, namespaces, CSRs...)
kubectl api-resources --namespaced=false
pods, deployments, services, secrets, configmaps, jobs, replica sets. Addressed as "this resource, in this namespace".
nodes, persistent volumes, namespaces, certificate signing requests. No namespace in the address, so a plain Role can't touch them.
If a resource has no namespace, a Role can't govern it. That's your cue to reach for a ClusterRole.
What a ClusterRole and ClusterRoleBinding actually are
Good news: if Topic 9 stuck, you already know 90% of this. A ClusterRole is the exact same idea as a Role, a bundle of permissions written as apiGroups, resources and verbs, except it isn't pinned to a namespace. A ClusterRoleBinding is the same idea as a RoleBinding, the link that hands that role to a user or group, except it applies across the whole cluster.
Two objects, same job as before, just one scope wider:
| Object | Scope | Governs |
|---|---|---|
| Role | one namespace | namespaced resources in that namespace |
| RoleBinding | one namespace | attaches a Role (or ClusterRole) to subjects there |
| ClusterRole | whole cluster | cluster-scoped resources, or namespaced ones everywhere |
| ClusterRoleBinding | whole cluster | attaches a ClusterRole to subjects cluster-wide |
Building one: a node admin
Say I want a user who can look at, create and delete nodes anywhere in the cluster. Nodes are cluster-scoped, so this has to be a ClusterRole. The YAML looks almost identical to a Role, the only real change is kind: ClusterRole and no namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-admin
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "create", "delete"]
Now bind it. A ClusterRoleBinding says "give this ClusterRole to this subject, everywhere":
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: node-admin-binding
subjects:
- kind: User
name: cluster-admin-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: node-admin
apiGroup: rbac.authorization.k8s.io
Apply both and you're done:
kubectl create -f node-admin-role.yaml
kubectl create -f node-admin-binding.yaml
Same shape for a storage admin: point the ClusterRole at persistentvolumes and persistentvolumeclaims instead of nodes, pick the verbs you want, bind it. The pattern doesn't change, only the resources do. A ClusterRole is really just a Role that forgot its namespace, and on paper that's the entire difference.
apiGroups: [""] is still the core group, the same one that holds nodes and persistent volumes. If you ever bind a ClusterRole to CSRs you'll switch to certificates.k8s.io. This is the API groups map from Topic 8 doing its job again.The trick that catches everyone: scope comes from the binding
This is the part I got wrong in my head at first, so pay attention here. A ClusterRole doesn't have to mean "cluster-wide access". The binding decides the scope, not the role.
Bind a ClusterRole with a ClusterRoleBinding and the permissions apply everywhere. But bind that same ClusterRole with an ordinary RoleBinding inside one namespace, and the permissions only apply in that namespace. Same role, two very different blast radii.
| Binding used | Where it applies | Status |
|---|---|---|
| ClusterRoleBinding | every namespace, plus cluster-scoped resources | widest reach |
| RoleBinding (in namespace X) | only inside namespace X | contained |
Why would anyone do that? Reuse. You define a ClusterRole like "secret-reader" once, then hand it out namespace by namespace with RoleBindings, so each team only gets it in their own space. One definition, controlled reach. The ClusterRole is the permission set; the binding type is the scope dial. Read the binding if you want to know the real reach.
The default ClusterRoles already on your cluster
You don't start from nothing. Every cluster ships with built-in ClusterRoles, and four are worth knowing by name because you'll bind to them constantly (and attackers look for them):
viewreads most things in a namespace but not secrets.editcan read and write most things, still no RBAC changes.adminfull control within a namespace, including RBAC, but not the cluster.cluster-adminthe god role. Every verb on every resource, everywhere. No limits.
These save you writing common roles from scratch. They're also the thing I check first on an engagement, because cluster-admin handed out casually is game over.
The pentest angle: who's holding the keys
Once I have any access to a cluster, ClusterRoleBindings are one of the first things I enumerate, because a single loose one can mean total control. The question is simple: who is bound to something powerful, especially cluster-admin?
Then I check my own effective access, which is the fastest way to know if I've landed somewhere useful:
# can I act on cluster-scoped resources?
kubectl auth can-i delete nodes
kubectl auth can-i '*' '*' # can I do everything?
# dump a subject's full reach without logging in as them
kubectl auth can-i --list --as=some-service-account
cluster-admin owns the cluster, full stop. Prefer namespaced Roles, or a ClusterRole reused via per-namespace RoleBindings, over a blanket ClusterRoleBinding. And treat the ability to create ClusterRoleBindings as just as dangerous as being cluster-admin, because it's a one-step path to it.The mental model I'm keeping
The mental model I'm walking away with: the resource's scope tells you which pair to use, and the binding's type tells you the real reach. Cluster-scoped thing? ClusterRole. Want it everywhere? ClusterRoleBinding. Want that same role in just one namespace? Bind it with a RoleBinding instead. I'm still fuzzy on how aggregation works, where a ClusterRole can pull in rules from other labelled ClusterRoles automatically, so if you've used aggregated roles in production I'd like to hear whether they're worth the complexity. Next I want to dig into service accounts and how pods get their own identity, because that's where a lot of real escalation actually starts.
If this made the Role vs ClusterRole thing finally click, come say hi on LinkedIn or the contact page, and tell me what you want next. More in the Kubernetes Journey.
Further reading
- Kubernetes docs: RBAC, Roles and ClusterRoles
- Kubernetes docs: default ClusterRoles
- Kubernetes docs: namespaced vs cluster-scoped resources
FAQ
What is the difference between a Role and a ClusterRole?
A Role grants permissions inside one namespace only. A ClusterRole is not tied to a namespace, so it can grant access to cluster-scoped resources like nodes and persistent volumes, or to namespaced resources across every namespace at once.
What are cluster-scoped resources in Kubernetes?
Cluster-scoped resources live outside any namespace: nodes, persistent volumes, namespaces themselves, and certificate signing requests. Run kubectl api-resources --namespaced=false to list them. A namespaced Role cannot control these, which is exactly why ClusterRoles exist.
Can a ClusterRole be limited to one namespace?
Yes. If you bind a ClusterRole with a RoleBinding instead of a ClusterRoleBinding, the permissions only apply inside that binding's namespace. The same ClusterRole bound with a ClusterRoleBinding applies across the whole cluster.
Related reading
- Topic 9: Authorization and RBAC (namespaced roles and bindings)
- Topic 8: Kubeconfig and API groups (groups, resources and verbs)
- Topic 6: Security primitives and authentication (who you are, before what you can do)
- Browse the whole Kubernetes Journey