Skip to content

RBAC

Control who can do what in your cluster using ServiceAccounts, Roles, and RoleBindings.

Time: ~10 minutes Difficulty: Intermediate

  • ServiceAccounts: identities for pods and automation
  • Roles: named sets of permissions (verbs on resources)
  • RoleBindings: connecting ServiceAccounts to Roles
  • Namespace-scoped (Role) vs cluster-scoped (ClusterRole) permissions
  • Testing permissions with kubectl auth can-i

Navigate to the demo directory:

Terminal window
cd demos/rbac
Terminal window
kubectl apply -f manifests/namespace.yaml
kubectl apply -f manifests/serviceaccounts.yaml
kubectl apply -f manifests/roles.yaml
kubectl apply -f manifests/rolebindings.yaml
kubectl apply -f manifests/test-pods.yaml

Two ServiceAccounts with different permission levels:

ServiceAccountRoleCan Do
pod-readerpod-readerGet, list, watch pods
pod-adminpod-adminGet, list, watch, create, delete pods and pod logs. Read services and deployments.
Terminal window
# pod-reader can list pods
kubectl auth can-i list pods \
--as=system:serviceaccount:rbac-demo:pod-reader -n rbac-demo
# pod-reader CANNOT delete pods
kubectl auth can-i delete pods \
--as=system:serviceaccount:rbac-demo:pod-reader -n rbac-demo
# pod-admin CAN delete pods
kubectl auth can-i delete pods \
--as=system:serviceaccount:rbac-demo:pod-admin -n rbac-demo
# pod-admin CANNOT create deployments
kubectl auth can-i create deployments \
--as=system:serviceaccount:rbac-demo:pod-admin -n rbac-demo
Terminal window
# pod-reader lists pods (works)
kubectl get pods -n rbac-demo \
--as=system:serviceaccount:rbac-demo:pod-reader
# pod-reader tries to delete a pod (denied)
kubectl delete pod -l app=sample-app -n rbac-demo \
--as=system:serviceaccount:rbac-demo:pod-reader
# pod-admin lists pods (works)
kubectl get pods -n rbac-demo \
--as=system:serviceaccount:rbac-demo:pod-admin
# pod-admin creates a pod (works)
kubectl run test-pod --image=busybox:1.36 --command -- sleep 10 \
-n rbac-demo --as=system:serviceaccount:rbac-demo:pod-admin
Terminal window
# pod-reader CANNOT list pods in default namespace (Role is namespace-scoped)
kubectl auth can-i list pods \
--as=system:serviceaccount:rbac-demo:pod-reader -n default
manifests/
namespace.yaml # rbac-demo namespace
serviceaccounts.yaml # pod-reader and pod-admin identities
roles.yaml # Permission definitions (verbs on resources)
rolebindings.yaml # Links ServiceAccounts to Roles
test-pods.yaml # Sample app to test against

RBAC model:

ServiceAccount ──> RoleBinding ──> Role
(who) (link) (what they can do)

A Role defines allowed operations:

rules:
- apiGroups: [""] # core API group
resources: ["pods"] # what resource
verbs: ["get", "list"] # what operations

A RoleBinding connects a subject (ServiceAccount, user, or group) to a Role. The binding is namespace-scoped, so pod-reader can only read pods in rbac-demo, not in other namespaces.

  1. List all permissions for a ServiceAccount:

    Terminal window
    kubectl auth can-i --list \
    --as=system:serviceaccount:rbac-demo:pod-admin -n rbac-demo
  2. Create a ClusterRole and ClusterRoleBinding for cluster-wide read access:

    Terminal window
    kubectl create clusterrole cluster-pod-reader \
    --verb=get,list,watch --resource=pods
    kubectl create clusterrolebinding cluster-pod-reader-binding \
    --clusterrole=cluster-pod-reader \
    --serviceaccount=rbac-demo:pod-reader
    # Now pod-reader can list pods in ANY namespace
    kubectl auth can-i list pods \
    --as=system:serviceaccount:rbac-demo:pod-reader -n default
  3. Clean up the cluster-scoped resources:

    Terminal window
    kubectl delete clusterrolebinding cluster-pod-reader-binding
    kubectl delete clusterrole cluster-pod-reader
Terminal window
kubectl delete namespace rbac-demo

See docs/deep-dive.md for a detailed explanation of the RBAC authorization model, aggregated ClusterRoles, the default ServiceAccount, token projection, and least-privilege patterns for production.

Move on to CRDs & Operators to learn how to extend Kubernetes with custom resources.