Kubernetes RBAC has Role, ClusterRole, RoleBinding and ClusterRoleBinding. Explain the scoping matrix — which combinations are legal and what each one actually grants — and what aggregated ClusterRoles are for.
answer
- Role+RoleBinding, CR+RoleBinding, CR+ClusterRoleBinding; Role+CRB illegal
- ClusterRole + RoleBinding = define once, scope down per namespace
- cluster-scoped rules go inert under a RoleBinding
- roleRef is immutable — delete and recreate
- aggregationRule: controller fills rules from labelled ClusterRoles
basics
~20 sRole + RoleBinding = permissions in one namespace. ClusterRole + ClusterRoleBinding = cluster-wide, including cluster-scoped resources. ClusterRole + RoleBinding = the ClusterRole's rules applied only inside the binding's namespace — the reuse pattern. Role + ClusterRoleBinding is illegal. Aggregated ClusterRoles merge in other ClusterRoles by label selector.
solid answer
~60 s**The matrix** | Rules in | Bound by | Effect | |---|---|---| | Role (ns X) | RoleBinding (ns X) | Permissions in namespace X only | | ClusterRole | RoleBinding (ns X) | Those rules, **scoped down** to namespace X | | ClusterRole | ClusterRoleBinding | Cluster-wide, all namespaces + cluster-scoped resources | | Role | ClusterRoleBinding | **Not allowed** — a RoleBinding is the only thing that may reference a Role, and only in its own namespace | The third row is the important one: define `pod-reader` once as a ClusterRole and bind it with a RoleBinding in each team namespace. That is exactly how the built-in `view`, `edit` and `admin` ClusterRoles are used. When a ClusterRole is bound via RoleBinding, its rules for **cluster-scoped** resources (nodes, PVs, namespaces) grant nothing — there is no namespace to confine them to. **Aggregated ClusterRoles** have an empty `rules` block and an `aggregationRule` with label selectors; the controller manager continuously fills `rules` from every ClusterRole matching those labels. Adding a CRD's permissions to `view` is then just labelling a small ClusterRole `rbac.authorization.k8s.io/aggregate-to-view: "true"` — no editing of the built-in role.
code
yaml · 22 linesapiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: workload-reader
rules:
- apiGroups: ["", "apps"]
resources: ["pods", "pods/log", "deployments", "replicasets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-read
namespace: team-a
subjects:
- kind: Group
name: team-a
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: workload-reader
apiGroup: rbac.authorization.k8s.iogo deeper
Reproduce the matrix and know that ClusterRole plus RoleBinding is how the built-in view and edit roles are granted per namespace.
Explain why Role plus ClusterRoleBinding is illegal, that cluster-scoped rules go inert under a RoleBinding, and what aggregation does.
Design with it: one canonical ClusterRole per persona bound per namespace to groups, aggregation labels for CRDs, and auditing ClusterRoleBindings as the highest-risk objects.
Discuss RBAC as an org model — personas mapped to identity-provider groups, delegation boundaries per namespace, review process for aggregation labels and cluster-wide bindings, and the drift that comes from per-namespace copies.
## Two axes, not one Kubernetes separates **where the rules are defined** from **where they apply**. Role/ClusterRole is the definition axis; RoleBinding/ClusterRoleBinding is the application axis. That is why there are four objects and only three legal combinations. **Role** is a namespaced object. Its rules can only ever concern resources inside its own namespace, and it can only be referenced by a RoleBinding in that same namespace. **ClusterRole** is cluster-scoped. It is a *definition* of permissions — writing one grants nothing until it is bound. It is the only place you can express permissions over cluster-scoped resources (nodes, persistentvolumes, namespaces, clusterroles, storageclasses), over non-resource URLs (`/healthz`, `/metrics`), and the only definition reusable across namespaces. **RoleBinding** is namespaced and grants its `roleRef` inside its own namespace. It may reference either a Role in that namespace or any ClusterRole. **ClusterRoleBinding** is cluster-scoped, may reference only a ClusterRole, and grants those rules everywhere. ## The matrix in detail **Role + RoleBinding.** The straightforward case: rules written for and applied to one namespace. Use it when the permission set is genuinely specific to that namespace, for instance a rule with `resourceNames` naming that team's Secrets. **ClusterRole + RoleBinding — the scoped-down pattern.** You define the permission set once, cluster-wide, then bind it per namespace. The binding's namespace confines the grant. This avoids copying the same Role into forty namespaces and having them drift. Two subtleties: - Rules in the ClusterRole covering **cluster-scoped** resources are silently inert under a RoleBinding, because those objects have no namespace to be confined to. A ClusterRole granting `nodes` bound via RoleBinding gives no node access. - Rules covering **non-resource URLs** are likewise inert. **ClusterRole + ClusterRoleBinding.** Cluster-wide grant across every namespace, present and future, plus cluster-scoped resources. Reserve it for genuine cluster-wide roles: platform operators, monitoring agents that must list pods everywhere, controllers. Binding `cluster-admin` this way is the ultimate grant, and `kubectl get clusterrolebindings` is the first place to audit. **Role + ClusterRoleBinding.** Rejected by the API server. If it were allowed, a namespace-scoped object would be projecting authority outside its namespace — anyone with write access to a namespace's Roles could grant themselves cluster-wide power. The asymmetry is a deliberate security property. ## Subjects All four binding shapes carry the same `subjects` list: `User`, `Group` (opaque strings from the authenticator — Kubernetes stores no user objects) and `ServiceAccount` (a real object, referenced with name plus namespace, so a RoleBinding in namespace A can bind a ServiceAccount from namespace B). Group bindings are how you scale: bind an OIDC or certificate group, manage membership in the identity provider, and never touch RBAC again for joiners and leavers. `roleRef` is **immutable**. Retargeting a binding means delete-and-recreate; controllers that manage RBAC must handle that. ## Aggregated ClusterRoles A ClusterRole may declare an `aggregationRule` instead of writing rules directly: ```yaml kind: ClusterRole metadata: name: view aggregationRule: clusterRoleSelectors: - matchLabels: rbac.authorization.k8s.io/aggregate-to-view: "true" rules: [] # filled in by the controller manager ``` A controller in kube-controller-manager watches ClusterRoles, unions the rules of every ClusterRole matching the selectors, and writes the result into `rules`. Anything you hand-write into an aggregated role's `rules` is overwritten on the next reconcile. The built-in `view`, `edit` and `admin` are aggregated, which is what makes them extensible. When you install a CRD, you ship a tiny ClusterRole granting read on your custom resource, labelled `rbac.authorization.k8s.io/aggregate-to-view: "true"`, and every existing `view` binding in the cluster immediately gains that read — no edits to a built-in object that an upgrade would revert, and no per-namespace changes. `admin` and `edit` aggregate transitively (`aggregate-to-edit` labels also flow into `admin`), so labelling for edit generally covers admin too. The operational caution is blast radius: labelling a ClusterRole for aggregation instantly widens permissions for every subject already bound to the aggregate, cluster-wide. Aggregation labels deserve the same review as a binding change. ## Checking the result `kubectl auth can-i <verb> <resource> -n <ns> --as <user>` for a single question, `kubectl auth can-i --list --as <user> -n <ns>` for the effective set, and `kubectl describe clusterrole view` to see the aggregated rules the controller actually assembled.
- You bind a ClusterRole that grants get and list on nodes using a RoleBinding in namespace team-a. What can the subject do?Nothing with nodes. A RoleBinding confines the granted rules to its own namespace, and nodes are a cluster-scoped resource with no namespace to be confined to, so those rules are inert. The subject gets only whatever namespaced rules the ClusterRole also contains. Node access requires a ClusterRoleBinding.
- Why is Role plus ClusterRoleBinding forbidden?It would let a namespaced object project authority outside its namespace. Anyone able to create Roles in their own namespace could then have a cluster-wide binding point at one, effectively escalating to cluster scope. Keeping cluster-wide grants referencable only from cluster-scoped ClusterRoles means the definition of any cluster-wide permission lives in an object that only cluster administrators can write.
- How would you give every existing 'view' user read access to a new custom resource without editing the built-in view ClusterRole?Create a small ClusterRole granting get, list and watch on your custom resource and label it rbac.authorization.k8s.io/aggregate-to-view: "true". The aggregation controller in kube-controller-manager unions it into the built-in view role automatically, so every subject already bound to view gains the access. Editing view directly would be reverted on the next reconcile or cluster upgrade.
A ClusterRole is a job description filed centrally; a RoleBinding hires someone into that job for one department, while a ClusterRoleBinding hires them for the whole company.
saying these in an interview costs you the question
- Thinking a ClusterRole grants anything before it is bound
- Expecting a ClusterRole bound by a RoleBinding to still grant node or PV access
- Believing Role can be referenced by a ClusterRoleBinding
- Hand-editing the rules of an aggregated ClusterRole and expecting them to persist
- Copying the same Role into every namespace instead of binding one ClusterRole per namespace