flowchart LR S["Subject<br/>User / Group / ServiceAccount"] --> B["RoleBinding<br/>(in namespace dev)"] B --> R["Role pod-reader<br/>get, list, watch pods"] S2["Group ops"] --> CB["ClusterRoleBinding"] CB --> CR["ClusterRole cluster-admin"]
| Object | Scope |
|---|---|
Role |
Rights on resources inside one namespace |
ClusterRole |
Shared rights, cluster-scoped resources (nodes, PVs) and non-resource URLs (/healthz) |
RoleBinding |
Grants a Role or a ClusterRole to subjects, effective only in the binding namespace |
ClusterRoleBinding |
Grants a ClusterRole across the whole cluster |
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { namespace: dev, name: pod-reader }
rules:
- apiGroups: [""] # "" = core group (pods, services…)
resources: ["pods"]
verbs: ["get", "list", "watch"]
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n dev
kubectl create rolebinding ci-read --role=pod-reader --serviceaccount=dev:ci -n dev
Common traps
- Using a ClusterRoleBinding when you only want rights in one namespace → too much access in every namespace. To reuse a ClusterRole in one namespace, point a RoleBinding at it.
roleRefcannot be changed after creation; delete and recreate the binding.- Core resources use
apiGroups: [""]; Deployments belong toapps. - A ServiceAccount subject is written
--serviceaccount=NAMESPACE:NAME.
| Command | Meaning |
|---|---|
kubectl get roles,rolebindings -n dev |
Roles and bindings in dev |
kubectl get clusterrolebindings |
Who has cluster-wide rights |
Built-in user-facing roles
| ClusterRole | Typical grant |
|---|---|
view |
Read most objects in a namespace, but not Secrets |
edit |
Create and change most objects, including reading Secrets, but not Roles or bindings |
admin |
Full control of a namespace, including RBAC inside it |
cluster-admin |
Everything, everywhere |
Binding these through a RoleBinding in each team's namespace covers most needs without writing custom roles.
Aggregated ClusterRoles
A ClusterRole with an aggregationRule collects rules from other ClusterRoles that carry a matching label. The built-in view, edit, and admin roles are aggregated, so when you install a CRD you can add a small ClusterRole labelled rbac.authorization.k8s.io/aggregate-to-edit: "true" and every existing edit user automatically gains rights on the new resource.
Rules with names and subresources
rules:
- apiGroups: ["apps"]
resources: ["deployments", "deployments/scale"]
resourceNames: ["web"]
verbs: ["get", "patch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
resourceNames limits a rule to specific objects, here only the web Deployment, but it cannot restrict create or list, because the name is not known in advance.
Escalation protection
You cannot create a Role or binding that grants more than you hold yourself, unless you have the escalate or bind verbs. Treat these verbs, plus impersonate, create pods in privileged namespaces, and write access to RBAC objects, as admin-level rights.
Managing RBAC as code
Keep Roles and bindings in Git next to each team's manifests, bind groups from the identity provider instead of individual users, and give each CI pipeline its own ServiceAccount limited to its namespace. kubectl get rolebindings,clusterrolebindings -A -o wide combined with kubectl auth can-i --list makes periodic reviews practical.