KubernetesXIV · Namespace ArchitectureTenancy and isolation
RBAC and Roles per namespace — least privilege as tenancy boundary
What you'll learn
- Explain how Roles and RoleBindings scope RBAC to a namespace
- Distinguish Role from ClusterRole and RoleBinding from ClusterRoleBinding
- Apply the principle of least privilege per namespace
- Audit RBAC bindings for production safety
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
RBAC is the access-control mechanism that turns namespaces into real tenancy boundaries. This lesson covers Roles, RoleBindings, ClusterRoles, and ClusterRoleBindings; the production patterns for least-privilege per namespace; and the audit discipline.
Roles vs ClusterRoles
# Role: namespace-scoped
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
namespace: team-a-prod
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# ClusterRole: cluster-wide (or aggregated)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes", "nodes/metrics"]
verbs: ["get", "list", "watch"]
Two role kinds:
- Role: namespaced. Applies to resources within a single namespace. Cannot reference cluster-scoped resources.
- ClusterRole: cluster-scoped. Applies to cluster-scoped
resources (Nodes, ClusterRoles, etc.) or to all
namespaces (with a
ClusterRoleBinding).
For per-namespace access control, use Role. For cluster-wide access (operators, monitoring), use ClusterRole.
RoleBindings vs ClusterRoleBindings
# RoleBinding: grants a Role or ClusterRole in one namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-developers
namespace: team-a-prod
subjects:
- kind: Group
name: team-a-developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
# ClusterRoleBinding: grants a ClusterRole cluster-wide
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admins
subjects:
- kind: Group
name: cluster-admins
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Two binding kinds:
- RoleBinding: grants a Role (or ClusterRole) in a specific namespace.
- ClusterRoleBinding: grants a ClusterRole cluster-wide.
For per-namespace access, use RoleBinding.
The RBAC model
flowchart LR
SA[ServiceAccount / User / Group] --> Binding[RoleBinding / ClusterRoleBinding]
Binding --> Role[Role / ClusterRole]
Role --> Verbs["verbs: get, list, watch, create, update, patch, delete"]
Role --> Resources["resources: pods, services, ..."]
Role --> APIGroups["apiGroups: '', apps, batch, ..."]
Three concepts:
- Subject: who gets access (User, Group, ServiceAccount).
- Binding: the linkage between subject and role (RoleBinding or ClusterRoleBinding).
- Role: what access is granted (verbs on resources in apiGroups).
A request from a user is checked: the user must be in a subject that is bound to a role that grants the verb on the resource in the API group.
Production patterns
Per-team namespace with team-specific Role:
# Role for team-a developers (in team-a-prod)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
namespace: team-a-prod
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-developers
namespace: team-a-prod
subjects:
- kind: Group
name: team-a-developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
This setup:
- Team-a developers can create, update, and delete Pods,
Services, ConfigMaps, Secrets, Deployments, StatefulSets
in
team-a-prod. - Team-a developers cannot access other namespaces (no RoleBinding there).
- Team-a developers cannot access cluster-scoped resources (Nodes, ClusterRoles, etc.).
Read-only role for on-call:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: read-only
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps", "batch", "networking.k8s.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: on-call-readonly
subjects:
- kind: Group
name: on-call
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: read-only
apiGroup: rbac.authorization.k8s.io
The on-call group can read all resources cluster-wide but cannot modify anything. Useful for incident response without granting destructive access.
The principle of least privilege
For every binding, ask: does the subject need exactly this access?
- Don’t grant
*verbs: list specific verbs (get,list,create, etc.). - Don’t grant
*resources: list specific resources (pods, services, configmaps). - Don’t grant cluster-wide access: scope to a namespace when possible.
- Don’t include Secrets in developer roles: developers don’t need to read Secrets; the application reads them.
Production discipline: the smaller the role, the safer the cluster. A team that has cluster-admin is one bug away from disaster.
Aggregated ClusterRoles
Kubernetes has built-in ClusterRoles that aggregate other roles:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: admin
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", ...]
verbs: ["*"]
The rbac.authorization.k8s.io/aggregate-to-admin: "true"
label tells Kubernetes to merge this role’s rules into the
admin ClusterRole. Custom controllers can extend built-in
roles by adding aggregated ClusterRoles.
ServiceAccounts as subjects
Pods authenticate to the API server via ServiceAccounts. RBAC can grant a ServiceAccount a role:
apiVersion: v1
kind: ServiceAccount
metadata:
name: cert-manager
namespace: cert-manager
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cert-manager-controller
rules:
- apiGroups: ["cert-manager.io"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cert-manager-controller
subjects:
- kind: ServiceAccount
name: cert-manager
namespace: cert-manager
roleRef:
kind: ClusterRole
name: cert-manager-controller
apiGroup: rbac.authorization.k8s.io
The cert-manager Pod uses this ServiceAccount and gets the cert-manager-controller ClusterRole. Production discipline: ServiceAccounts are application identities; grant them exactly the access they need.
Auditing RBAC
# List all ClusterRoleBindings
kubectl get clusterrolebindings -o wide
# List all RoleBindings in a namespace
kubectl get rolebindings -n team-a-prod -o wide
# Check what access a user has
kubectl auth can-i create pods --as alice -n team-a-prod
# Check what access a ServiceAccount has
kubectl auth can-i list secrets --as system:serviceaccount:team-a-prod:default -n team-a-prod
# Find subjects with cluster-admin
kubectl get clusterrolebindings -o json | \
jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'
Production discipline: run kubectl auth can-i checks
regularly; audit RoleBindings and ClusterRoleBindings.
Cross-course references
- The Linux course part
XXVI-Linux-SSHcovers authentication and authorisation; RBAC is the cluster-level equivalent. - The Linux course part
XXVII-Linux-Authcovers identity management; ServiceAccounts are the cluster-level equivalent. - The Docker course part
XXXVIII-Docker-Secretscovers secret access patterns; Kubernetes RBAC for Secrets is the cluster-level equivalent.
Quiz
Knowledge check · 4 questions
Q1. Which combination is the right choice for granting team-a developers access to their own namespace only?
Q2. Production discipline says to grant the smallest role that lets the workload or user do their job.
Q3. An audit reveals that a developer has `cluster-admin` access via a direct RoleBinding. Walk through the risk and the fix.
A developer `alice` was granted cluster-admin to debug an issue six months ago. The issue was fixed; the access was never revoked. Alice is still in the `cluster-admin` ClusterRoleBinding. The audit tool flags this.
Q4. How do you grant a Pod's ServiceAccount access to read ConfigMaps in its own namespace?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Use Role + RoleBinding for namespace-scoped access. ClusterRole + ClusterRoleBinding is for cluster-wide only.
- Apply the principle of least privilege. List specific verbs and resources; exclude Secrets unless needed.
- Audit RBAC bindings regularly.
kubectl auth can-ichecks; review cluster-admin grants. - Use ServiceAccounts for application access. Pods authenticate as their ServiceAccount; grant that SA exactly what it needs.
- Revoke standing high-privilege access. Cluster-admin grants should be temporary, not standing.