Tech
Kubernetes RBAC Explained: Managing Access and Permissions Securely
Learn how Kubernetes RBAC works to secure your cluster with roles, bindings, and best practices for least-privilege access control.
June 2026 · 8 min read · 2 views · 0 hearts
Advertisement
Kubernetes RBAC Explained: Managing Access and Permissions Securely
You've deployed your first Kubernetes cluster. Pods are running, services are up, and everything looks fine. But then a developer accidentally deletes a production namespace, or a CI pipeline scrapes secrets it shouldn't have access to. Suddenly, you're not feeling so confident.
Access control in Kubernetes isn't optional—it's how you keep your cluster from becoming a security incident waiting to happen. RBAC (Role-Based Access Control) is Kubernetes' built-in mechanism for who can do what, and once you understand it, you'll sleep better at night.
What Is RBAC and Why Should You Care?
RBAC is Kubernetes' way of saying "you can't touch that." It's a declarative, fine-grained permission system baked directly into the API server. Every kubectl command, every API call, every automation tool hitting your cluster—it all goes through RBAC first.
The core idea is simple: subjects (users, service accounts, groups) are bound to roles (sets of permissions) via role bindings. No subject has any permissions by default. That's the zero-trust model Kubernetes embraces.
Without RBAC, any credential that reaches your cluster has root-level access. That's terrifying when you consider how many CI/CD tools, monitoring systems, and third-party services need to touch your cluster.
The Building Blocks
Roles and ClusterRoles
A Role defines what actions are allowed on which resources. But there's a catch—Roles are namespaced. They only apply within the namespace they're created in.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
This role lets someone read pods in the development namespace, but nothing else.
ClusterRoles are the same concept but cluster-wide. They can grant access to cluster-scoped resources like nodes, or to namespaced resources across all namespaces.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-monitor
rules:
- apiGroups: [""]
resources: ["nodes", "pods", "services"]
verbs: ["get", "list", "watch"]
Subjects: Who Gets Access
Subjects are the "who" in RBAC. They come in three flavors:
- ServiceAccounts – Non-human identities used by Pods and automation
- Users – Human identities (typically managed externally, e.g., via OpenID Connect)
- Groups – Collections of users or service accounts
ServiceAccounts are the most common subjects you'll manage directly in Kubernetes. Every namespace gets a default ServiceAccount, but never use it—always create dedicated ones for each application.
RoleBindings and ClusterRoleBindings
A RoleBinding ties a subject to a Role within a namespace. A ClusterRoleBinding does the same but cluster-wide.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: development
subjects:
- kind: ServiceAccount
name: my-app
namespace: development
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Here's where it gets interesting: you can bind a ClusterRole to a RoleBinding. That lets you reuse cluster-wide permissions but restrict them to a single namespace. It's one of the most practical patterns in RBAC.
The Four Real-World Patterns You'll Use Every Day
1. Namespace-Scoped App Permissions
Every application should get its own ServiceAccount and Role for exactly what it needs—nothing more.
apiVersion: v1
kind: ServiceAccount
metadata:
name: backend-service
namespace: backend
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: backend
name: backend-operator
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: backend-operator-binding
namespace: backend
subjects:
- kind: ServiceAccount
name: backend-service
namespace: backend
roleRef:
kind: Role
name: backend-operator
apiGroup: rbac.authorization.k8s.io
2. Read-Only Access for CI/CD or Monitoring
A monitoring system needs to see everything but change nothing. Use a ClusterRole bound to a namespace-scoped RoleBinding if you need cross-namespace visibility.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: readonly-global
rules:
- apiGroups: [""]
resources: ["pods", "services", "endpoints", "events", "nodes"]
verbs: ["get", "list", "watch"]
3. Aggregated Admin Roles
Rather than creating permissions for every possible resource, Kubernetes lets you aggregate ClusterRoles. This is how the built-in admin, edit, and view roles work.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: custom-admin
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules: [] # Inherits from aggregated roles
4. Conditional Access with SubjectAccessReview
Sometimes you need to check permissions programmatically. Kubernetes provides the SubjectAccessReview API for this.
kubectl auth can-i create deployments --as=system:serviceaccount:backend:backend-service
This tells you instantly whether that ServiceAccount has permission, without actually executing the action.
Common Pitfalls That Will Bite You
Using default ServiceAccounts: Every Pod in a namespace that doesn't explicitly specify a serviceAccountName gets the default one. That default has zero permissions, but if you accidentally bind roles to it, every Pod in that namespace inherits those permissions.
Overly broad verbs: ["*"] on verbs is tempting but dangerous. It includes delete, deletecollection, impersonate, and escalate. Give only the minimum verbs needed.
Forgetting about aggregation: The built-in Kubernetes roles are aggregated from many smaller roles. If you label your custom roles with rbac.authorization.k8s.io/aggregate-to-admin: "true", they automatically become part of the admin ClusterRole.
Not auditing regularly: Permissions accumulate over time as teams change and applications evolve. Run kubectl auth can-i --list --as=system:serviceaccount:namespace:name periodically to check what each identity actually has access to.
Authentication vs Authorization
One thing people often get wrong: Kubernetes does not manage user authentication. RBAC only handles authorization—what authenticated users can do.
To authenticate users, you need an external identity provider (like OIDC with Google, Azure AD, or Keycloak) or X.509 certificates. The API server validates the identity, and then RBAC decides whether that identity has permission for the requested action.
Testing Your RBAC Without Breaking Things
Before deploying RBAC changes to production, simulate them:
kubectl auth reconcile -f my-rbac.yaml
This shows you exactly what would change without actually creating or updating resources. It's your dry-run tool for access control changes.
The Bottom Line
RBAC enforces the principle of least privilege in Kubernetes. Every permission you grant should have a clear reason, and every identity should have exactly enough access to do its job—no more, no less.
Start small: one ServiceAccount per application, one Role per use case, and bind them explicitly. Audit regularly. And never, ever bind a ClusterRole to a ServiceAccount across all namespaces unless you're absolutely sure that's what you need.
Your cluster will thank you.
Advertisement
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.