Kubernetes RBAC Role Based Access Control Explained
Kubernetes runs many workloads, and not everyone who touches the cluster should be able to do everything. A developer should deploy apps. A monitoring tool should only read metrics. A junior engineer should not delete production databases. RBAC (Role-Based Access Control) is the system that enforces these boundaries inside Kubernetes.
RBAC answers one question: Who can do what, on which resources?
The Real-World Problem RBAC Solves
Picture a hospital. Doctors read patient records. Nurses update medication logs. Receptionists book appointments. Nobody gets access to everything — only what their job requires. Kubernetes RBAC works the same way for your cluster.
Without RBAC, every user and every application inside the cluster would have the same level of access. One misconfigured script could wipe all deployments. RBAC prevents that.
The Four Building Blocks of RBAC
1. Subject — Who Is Asking?
A subject is the identity that wants to perform an action. Kubernetes recognises three types of subjects:
- User — A human administrator or developer who authenticates with the cluster.
- Group — A collection of users treated as one unit (e.g., the
developersgroup). - ServiceAccount — A non-human identity assigned to a Pod so the app itself can call the Kubernetes API.
2. Resource — What Is Being Touched?
Resources are the Kubernetes objects the subject wants to interact with — Pods, Deployments, ConfigMaps, Secrets, Services, Nodes, and so on.
3. Verb — What Action Is Requested?
Verbs describe the operation. The most common ones are:
get— Read a single resource.list— Read all resources of a type.watch— Stream changes to a resource.create— Make a new resource.update— Modify an existing resource.patch— Partially modify a resource.delete— Remove a resource.
4. Role / ClusterRole — The Permission Set
A Role bundles together a list of verbs on a list of resources. Think of it as a job description: "This role can get and list Pods."
RBAC Diagram: The Access Flow
┌─────────────────────────────────────────────────────┐ │ RBAC Access Check │ │ │ │ Subject Role Resource │ │ ─────── ──── ──────── │ │ [User: Alice] ──► [Role: Pod-Reader] ──► [Pods] │ │ verbs: get, list │ │ │ │ [ServiceAccount: │ │ │ app-backend] ──►[Role: Secret-Reader]─► [Secrets] │ │ verbs: get │ │ │ │ API Server checks: Does the binding exist? │ │ YES → Allow │ NO → 403 Forbidden │ └─────────────────────────────────────────────────────┘
Role vs ClusterRole: The Namespace Boundary
This is one of the most important distinctions in RBAC.
Role (Namespace-Scoped)
A Role only applies inside one specific namespace. If you create a Role in the production namespace, it has zero effect in the staging namespace.
Use a Role when you want to give someone access to resources inside one namespace and nowhere else.
ClusterRole (Cluster-Wide)
A ClusterRole applies across the entire cluster, across all namespaces. It also covers resources that do not belong to any namespace at all, such as Nodes, PersistentVolumes, and Namespaces themselves.
Use a ClusterRole for platform admins, monitoring agents, and any tool that needs to read resources in all namespaces.
Namespace-Scoped vs Cluster-Scoped ┌──────────────────────────────────────────────┐ │ CLUSTER │ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Namespace │ │ Namespace │ │ │ │ production │ │ staging │ │ │ │ │ │ │ │ │ │ [Role A] │ │ [Role B] │ │ │ │ ↕ only │ │ ↕ only │ │ │ │ here │ │ here │ │ │ └─────────────┘ └─────────────┘ │ │ │ │ [ClusterRole C] ──► affects ALL above │ │ + cluster-level resources (Nodes etc.) │ └──────────────────────────────────────────────┘
RoleBinding and ClusterRoleBinding: The Glue
Creating a Role does nothing on its own. A RoleBinding connects a subject to a Role. Without the binding, the Role is just a definition sitting unused.
- RoleBinding — Connects a subject to a Role or ClusterRole inside one namespace.
- ClusterRoleBinding — Connects a subject to a ClusterRole across the entire cluster.
A ClusterRole can also be referenced by a RoleBinding. This is a powerful pattern: define the permission set once as a ClusterRole, then reuse it in many namespaces via individual RoleBindings.
Writing Your First Role: A Practical Example
Scenario: A developer named Alice should be able to read Pods in the production namespace, but nothing else.
Step 1 — Create the Role
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: production name: pod-reader rules: - apiGroups: [""] # "" means the core API group resources: ["pods"] verbs: ["get", "list", "watch"]
The apiGroups: [""] field refers to the core Kubernetes API group, which contains Pods, Services, ConfigMaps, and Secrets. For other resources like Deployments, you use apps as the apiGroup.
Step 2 — Create the RoleBinding
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods-alice namespace: production subjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
Now Alice can run kubectl get pods -n production successfully. Any other action — like deleting a pod or reading Secrets — will return a 403 error.
ServiceAccounts: RBAC for Applications
When a Pod needs to call the Kubernetes API (for example, a monitoring agent that lists all running pods), it uses a ServiceAccount. RBAC applies to ServiceAccounts exactly the same way it applies to human users.
Every namespace gets a default ServiceAccount automatically. By default, this ServiceAccount has no RBAC permissions. You bind a Role to it when the application actually needs API access.
Example: Giving a Monitoring App Read Access to All Pods
# ClusterRole: read pods in all namespaces apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: pod-monitor rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] --- # Bind it to the ServiceAccount in the monitoring namespace apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: pod-monitor-binding subjects: - kind: ServiceAccount name: prometheus namespace: monitoring roleRef: kind: ClusterRole name: pod-monitor apiGroup: rbac.authorization.k8s.io
Aggregated ClusterRoles
Kubernetes ships with a set of default ClusterRoles. Three of the most important are:
- cluster-admin — Full access to everything. Reserve this for break-glass scenarios only.
- view — Read-only access to most resources in a namespace (no Secrets).
- edit — Read and write access to most resources; cannot modify RBAC rules.
- admin — Full namespace control including managing RoleBindings, but cannot touch cluster-level resources.
You can extend these built-in roles using aggregation rules. You create a ClusterRole with a special label, and Kubernetes automatically merges its permissions into the target built-in role. This lets operators extend the view or edit role for custom resources without touching the original definition.
Common RBAC Patterns in Production
Pattern 1: Namespace Isolation per Team
Each team owns one namespace. Each team's group gets the edit ClusterRole bound via a RoleBinding in their namespace only. No team can read or modify another team's namespace.
Pattern 2: Read-Only Access for CI Pipelines
A CI/CD pipeline needs to verify deployments but not change them. Bind the view ClusterRole to the pipeline's ServiceAccount.
Pattern 3: Least Privilege for Operators
Kubernetes operators (custom controllers) often need broad access. Scope their ClusterRole to only the resources they actually manage. Do not grant cluster-admin to operators.
Auditing and Debugging RBAC
Check What a User Can Do
# Can Alice delete pods in production? kubectl auth can-i delete pods --namespace=production --as=alice # Output: no
List All RoleBindings in a Namespace
kubectl get rolebindings -n production -o wide
Describe a Role to See Its Rules
kubectl describe role pod-reader -n production
Find Who Has Access to a Resource
# Install kubectl-who-can plugin kubectl who-can delete pods -n production
RBAC Pitfalls to Avoid
- Wildcard verbs and resources — Avoid
verbs: ["*"]orresources: ["*"]in production roles. List only what is needed. - Granting cluster-admin broadly — A compromised account with
cluster-admincan destroy the entire cluster. Use it only for emergency access. - Ignoring ServiceAccount permissions — Pods run as the default ServiceAccount unless specified otherwise. Keep the default ServiceAccount permission-free and create dedicated ServiceAccounts for apps that need API access.
- Not reviewing bindings regularly — Old bindings for departed employees or decommissioned tools accumulate. Audit bindings quarterly.
- Binding ClusterRole via ClusterRoleBinding when RoleBinding is enough — If access is only needed in one namespace, use a RoleBinding. A ClusterRoleBinding gives cluster-wide access unnecessarily.
RBAC and Secrets: A Special Case
The built-in view ClusterRole deliberately excludes Secrets. Secrets contain passwords, tokens, and certificates. Even if a user can read all other resources in a namespace, they cannot read Secrets unless you explicitly grant them get on the secrets resource.
Treat Secret access as a separately gated permission. Most developers do not need to read Secrets directly — they just need the app to use them via environment variables or volume mounts.
Key Points
- RBAC controls who (subject) can do what (verb) on which resources in Kubernetes.
- A Role scopes permissions to one namespace; a ClusterRole applies cluster-wide.
- Permissions take effect only when a RoleBinding or ClusterRoleBinding connects a subject to a role.
- ServiceAccounts give Pods an identity for API calls — bind roles to them just like human users.
- Always follow the principle of least privilege: grant only the verbs and resources an identity actually needs.
- Use
kubectl auth can-ito debug access issues quickly. - Audit bindings regularly and remove anything no longer needed.
