RBAC Basics
This section covers the four RBAC objects you will use every day - Roles, ClusterRoles, RoleBindings, and ClusterRoleBindings - and how to compose them into least-privilege access.
Prerequisites
- Kubernetes 1.36.2 cluster with the RBAC authorizer enabled (the default on all managed platforms).
kubectlconfigured with an identity that can create RBAC objects.- Basic familiarity with namespaces and the API server request model.
Quick check that RBAC is active and you can read your own permissions:
kubectl api-resources --api-group=rbac.authorization.k8s.io
kubectl auth can-i --listBasic Examples
1. A namespaced Role
A Role grants verbs on resources inside a single namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: payments
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]apiGroups: [""]is the core group, where pods, services, and configmaps live.- The Role only has meaning in the
paymentsnamespace. - It grants read-only access, no
createordelete. - A Role is inert until a binding references it.
2. A RoleBinding to a user
The RoleBinding connects the Role to a subject inside the namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: payments
name: read-pods
subjects:
- kind: User
name: dev-alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.iosubjectslists who gets the access - here a single user.roleRefpoints to the Role granting the permissions.- Both objects live in
payments, so the grant is namespace-scoped. roleRefis immutable, so change bindings by replacing, not editing.
3. A ClusterRole
A ClusterRole defines permissions that are not tied to one namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-viewer
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]- Nodes are cluster-scoped, so only a ClusterRole can grant access to them.
- The same ClusterRole can be reused across many namespaces.
- It carries no access on its own until bound.
4. A ClusterRoleBinding
A ClusterRoleBinding grants a ClusterRole across the whole cluster.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: view-nodes
subjects:
- kind: Group
name: sre-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: node-viewer
apiGroup: rbac.authorization.k8s.io- The
sre-teamgroup can list nodes in every namespace. - Binding to a Group scales access to everyone with that group claim.
- Use ClusterRoleBindings sparingly, since they are cluster-wide.
5. Reusing a ClusterRole in one namespace
A namespaced RoleBinding can reference a ClusterRole to scope shared permissions.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: payments
name: payments-edit
subjects:
- kind: Group
name: payments-devs
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io- The built-in
editClusterRole is defined once but bound per namespace. payments-devsget edit rights only insidepayments.- This is the standard way to give a team full control of their namespace.
6. Binding a ServiceAccount
Workloads authenticate as a ServiceAccount, which is a valid subject.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: payments
name: app-config-reader
subjects:
- kind: ServiceAccount
name: checkout
namespace: payments
roleRef:
kind: Role
name: config-reader
apiGroup: rbac.authorization.k8s.iokind: ServiceAccountrequires an explicitnamespace.- The
checkoutpod inherits exactly these permissions. - This is how you scope in-cluster API access for an app.
7. Testing permissions
Ask the API server what a subject can do before shipping.
kubectl auth can-i get pods --namespace payments
kubectl auth can-i list secrets --namespace payments \
--as system:serviceaccount:payments:checkoutcan-ireturnsyesornofrom the real authorizer.--asimpersonates any user, group, or ServiceAccount.- Use this in CI to assert least privilege.
Intermediate Examples
8. Aggregated ClusterRoles
Compose a ClusterRole from smaller labeled pieces.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-viewer
labels:
rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: ["monitoring.coreos.com"]
resources: ["prometheuses", "servicemonitors"]
verbs: ["get", "list", "watch"]- Any ClusterRole carrying the matching
aggregationRuleselector absorbs these rules automatically. - The built-in
view,edit, andadminroles grow the same way. - This keeps custom permissions modular and future-proof.
9. Narrowing to named resources
Restrict a rule to specific object names with resourceNames.
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["tls-cert"]
verbs: ["get"]- The subject can read only the
tls-certSecret, nothing else. resourceNamesdoes not supportlistorwatch, only name-addressable verbs.- Use it for tight, single-object grants.
10. Auditing effective access
Trace what a subject can actually do.
kubectl auth can-i --list --namespace payments \
--as system:serviceaccount:payments:checkout- Prints every resource and verb combination the subject is granted.
- Run it after changing bindings to confirm you did not over-grant.
- Pair it with quarterly reviews of high-risk verbs like
execandsecrets.
11. Granting a subresource
Some capabilities live on subresources, not the parent object.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: payments
name: pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]pods/logis the log subresource, separate frompodsitself.- Reading logs does not require any write verb on the pod.
- The same pattern applies to
pods/exec,pods/portforward, andpods/status, each grantable independently. - Keep
pods/execout of routine developer Roles, since it is interactive shell access.
12. Keeping RBAC least-privilege
A few habits keep grants tight as a cluster grows.
- Prefer a namespaced Role to a ClusterRole whenever the resource is namespaced.
- Enumerate verbs explicitly instead of using
verbs: ["*"]. - Bind to groups from your identity provider, not to individual users, so access follows directory membership.
- Reuse the built-in
view,edit, andadminClusterRoles before writing your own.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).