← Back

2026

Kubernetes RBAC: Controlling Access to the API

A freshly created Kubernetes cluster will accept almost anything. RBAC is the mechanism that changes that. Here is how Roles, ClusterRoles, bindings and subjects compose into a permission model that keeps workloads and humans scoped to exactly what they need.

A freshly created Kubernetes cluster will accept almost anything you throw at it. Every user with a valid kubeconfig can read secrets, delete deployments, modify service accounts. That is a reasonable default for a local development cluster running on your laptop. In anything shared, it is a serious problem.

Role-Based Access Control is the mechanism Kubernetes uses to change that. It lets you define precisely what each identity is allowed to do with which resources. A developer can deploy to their namespace without being able to read the secrets in someone else's. A CI pipeline can update an image tag without being able to delete the deployment. An operator pod can watch the resources it manages without having any access to cluster configuration it should never touch.

RBAC in Kubernetes is built on four object types. Roles and ClusterRoles define what is permitted. RoleBindings and ClusterRoleBindings connect those permissions to identities. The rest is about understanding how those pieces compose.

Subjects: who is making the request

Every request to the Kubernetes API server comes from a subject. Kubernetes recognises three kinds. The important thing to understand about Users and Groups is that Kubernetes does not store them anywhere. There is no user database to query. The API server trusts whatever the authentication layer presents. The cluster administrator chooses which authentication methods are enabled. The method determines how identity is established on each request.

User

A human identity. Kubernetes does not manage user accounts directly. Users are strings that arrive in the request after the cluster's authentication layer has verified them. That could be a certificate CN field, a token claim or an OIDC subject. The cluster trusts whatever the authentication mechanism asserts.

Group

A collection of users. Groups arrive the same way Users do, through the authenticator. Certificate-based auth encodes group membership in the O field of the certificate subject. OIDC providers put groups in token claims. A binding to a group applies to every member of that group without listing each one individually.

ServiceAccount

A non-human identity for workloads. ServiceAccounts are actual Kubernetes objects that live in a namespace. When a pod runs, it mounts a token for its ServiceAccount automatically. Code running inside the pod uses that token to talk to the API server. This is how operators, controllers and in-cluster tooling authenticate.

Verbs: what the subject wants to do

Permissions in Kubernetes are expressed as verbs on resources. Every API request maps to a verb. When the authoriser checks whether a request is allowed, it looks for a rule that matches the combination of the verb, the resource type and the namespace. If no rule matches, the request is denied. RBAC is deny by default.

Verb
Meaning
get

Read a single named resource.

list

Read all resources of a type in a namespace.

watch

Subscribe to changes on a resource type. Controllers use this constantly.

create

Submit a new resource to the API server.

update

Replace an existing resource entirely.

patch

Modify specific fields of an existing resource without replacing the whole thing.

delete

Remove a resource.

deletecollection

Remove multiple resources at once. Rarely granted individually.

The wildcard * matches all verbs on all resources. It appears in the built-in cluster-admin ClusterRole and should not appear in anything you write for real workloads. When you write rules for a specific purpose, list the verbs explicitly. The discipline of listing them forces you to think about what the identity actually needs rather than what is convenient to grant.

The four RBAC object types

Role and ClusterRole objects contain rules. RoleBinding and ClusterRoleBinding objects connect rules to subjects. The scope of each object determines what it can cover. Namespace-scoped objects stop at the namespace boundary. Cluster-scoped objects do not.

Role

Namespaced

Grants permissions within a single namespace. A Role in the payments namespace can only describe what subjects are allowed to do to resources in that namespace. It cannot reach across namespace boundaries.

ClusterRole

Cluster-wide

Grants permissions across the entire cluster. Used for non-namespaced resources like Nodes and PersistentVolumes. Also used when you want a consistent set of permissions applied across all namespaces without creating a Role in each one.

RoleBinding

Namespaced

Attaches a Role to subjects within a namespace. Can also reference a ClusterRole, which lets you define permissions once as a ClusterRole and bind them per-namespace without duplicating the rules.

ClusterRoleBinding

Cluster-wide

Attaches a ClusterRole to subjects across the entire cluster. A subject bound this way has that role's permissions in every namespace simultaneously. Use with care — this is the mechanism that grants cluster-admin.

What the manifests look like

A Role lists rules. Each rule names an API group, the resources inside it and the verbs permitted. An empty string for the API group refers to the core group, which covers pods, services, configmaps, secrets and most of the resources you work with daily.

Role — namespace-scoped

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

name: pod-reader

namespace: payments

rules:

- apiGroups: [""]

resources: ["pods", "pods/log"]

verbs: ["get", "list", "watch"]

The RoleBinding references the Role by name. The subjects list contains the identities that receive those permissions. Multiple subjects can appear in the same binding.

RoleBinding — attaches Role to subjects

apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

name: read-pods

namespace: payments

subjects:

- kind: ServiceAccount

name: monitoring-agent

namespace: monitoring

roleRef:

apiGroup: rbac.authorization.k8s.io

kind: Role

name: pod-reader

Cross-namespace subjects

A RoleBinding in the payments namespace can reference a ServiceAccount from the monitoring namespace, as shown above. The binding is scoped to payments. The ServiceAccount lives in monitoring. This is how a centralised agent gets read access to resources across multiple namespaces without a ClusterRoleBinding that would grant access everywhere.

Aggregated ClusterRoles

Kubernetes has a mechanism for composing ClusterRoles out of smaller pieces using label selectors. You mark contributing ClusterRoles with a specific label. An aggregated ClusterRole watches for that label and automatically inherits the rules from any matching role. Operators use this to extend built-in roles like view or edit with rules for their custom resources without modifying those roles directly.

Extending the built-in view role

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRole

metadata:

name: my-operator-view

labels:

rbac.authorization.k8s.io/aggregate-to-view: "true"

rules:

- apiGroups: ["myoperator.io"]

resources: ["widgets"]

verbs: ["get", "list", "watch"]

Anyone bound to the built-in view ClusterRole in the cluster now also has read access to widgets. The aggregated ClusterRole is picked up automatically. No existing bindings need to change.

Checking what is allowed

kubectl auth can-i lets you verify what a subject can do without reading through every Role and binding by hand. It is the first tool to reach for when a workload is being denied access it should have, or when you want to verify that a new binding is doing what you expect.

kubectl auth can-i get pods --namespace payments

Check whether your current identity can list pods in the payments namespace.

kubectl auth can-i create deployments --as system:serviceaccount:payments:my-sa --namespace payments

Check whether a specific ServiceAccount can create deployments. The --as flag impersonates the given subject.

kubectl auth can-i '*' '*' --all-namespaces

Check whether the current identity effectively has cluster-admin. Returns yes if there is a wildcard ClusterRoleBinding in effect.

kubectl auth whoami

Show the identity the API server has resolved for your current kubeconfig credentials. Useful when you are not sure which user a certificate maps to.

kubectl get rolebindings,clusterrolebindings --all-namespaces -o wide

List all bindings in the cluster with their subjects visible. A broad view of what is connected to what.

Common patterns

Most RBAC configurations in real clusters converge on a handful of patterns. The specifics vary but the structure stays the same: narrow subjects, explicit verbs, namespace scope wherever possible.

Read-only namespace access

A ClusterRole with get, list and watch on pods, deployments, services and related resources, bound per-namespace via RoleBinding. Teams get visibility into their namespace without being able to change anything.

ServiceAccount with minimal scope

A ServiceAccount granted only the verbs its workload actually needs. An operator that reconciles ConfigMaps gets read and update on ConfigMaps in its namespace. Nothing more. If the pod is compromised, the blast radius stops at the namespace boundary.

Developer self-service namespace

A RoleBinding that gives a team full control over their own namespace while keeping cluster-level resources off limits. They can deploy, scale and delete workloads without touching node configuration or cluster-scoped resources.

CI/CD pipeline token

A dedicated ServiceAccount with create and update on deployments in a specific namespace. The pipeline authenticates using the token and can update images. It cannot touch secrets it does not need, cannot delete the deployment accidentally, cannot reach other namespaces.

Things that go wrong

RBAC problems usually fall into one of two categories. Either a workload is being denied access it needs and nothing is working, or something has been granted more access than it should have because the original setup optimised for silence over correctness.

Wildcard grants

Granting verbs: ["*"] or resources: ["*"] is common when debugging permissions quickly. It fixes the immediate problem but is rarely reverted. Audit for wildcards before a production cluster sees real workloads.

ClusterRoleBinding when RoleBinding is enough

A ClusterRoleBinding gives the same permissions in every namespace at once. If a workload only needs access in one namespace, a RoleBinding scoped to that namespace is always the right choice.

Binding to cluster-admin

Binding a ServiceAccount or a user to the cluster-admin ClusterRole gives unrestricted access to everything in the cluster. It should exist for a small number of human administrators through time-limited credentials.

Forgetting the roleRef is immutable

Once a RoleBinding or ClusterRoleBinding is created, its roleRef field cannot be changed. To point a binding at a different Role, delete it and recreate it. This catches people off guard during refactors.

Where it fits

RBAC is the foundation of access control in Kubernetes but it does not operate alone. NetworkPolicies restrict which pods can talk to each other at the network level. PodSecurity standards constrain what containers are allowed to do at the host level. Admission controllers like Kyverno add a policy layer on top of everything the API server has already accepted. RBAC handles the question of who can make which API requests. The rest handle what happens after those requests succeed.

ServiceAccounts deserve particular attention because they are where cluster security most commonly goes wrong in practice. Every pod gets a ServiceAccount. Unless you specify one, it gets the default ServiceAccount in its namespace. If the default ServiceAccount has been granted broad permissions, every pod in that namespace inherits them without anyone making a conscious decision about it. Explicit ServiceAccounts with minimal permissions are the right default for any workload that talks to the Kubernetes API.

Tools like Argo CD and operators that manage cluster state all rely on RBAC to scope their access to what they genuinely need. The ClusterRoles they install during setup reflect exactly what resources they watch. Reading those roles tells you precisely what the tool can do on your cluster, which is worth knowing before you hand it a ClusterRoleBinding.