Articles

Kubernetes RBAC Explained

Kubernetes RBAC controls who can do what in a cluster using Roles, ClusterRoles, and bindings. How the pieces fit together, with a worked example.

Chisato Chisato · · 4 min read
Kubernetes helm-wheel logo illustration

RBAC (Role-Based Access Control) is the standard authorization system in Kubernetes, controlling which users, groups, and service accounts can perform which actions on which resources. It works through four API objects — Role, ClusterRole, RoleBinding, and ClusterRoleBinding — that together define permissions and grant them to identities. Nearly every managed Kubernetes cluster has RBAC enabled by default, which means understanding these four objects is a prerequisite for running anything beyond a toy cluster safely.

Roles: defining permissions

A Role defines a set of permissions scoped to a single namespace. It doesn’t grant access to anyone by itself — it just describes what actions are possible, expressed as rules combining API groups, resources, and verbs:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: staging
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]

This rule says: within the staging namespace, whoever holds this role can read pods — but not create, edit, or delete them, and not touch anything outside that namespace.

ClusterRoles: cluster-wide or reusable permissions

A ClusterRole is the same idea but not tied to a namespace. It’s used two ways: to grant permissions across the entire cluster (like managing nodes or non-namespaced resources), or to define a reusable permission set that gets applied to specific namespaces via a RoleBinding — letting you define “viewer” or “editor” once and bind it wherever needed instead of duplicating the same Role in every namespace.

Bindings: granting the permissions

Roles and ClusterRoles are inert until bound to an identity — a user, a group, or a service account. That’s what RoleBinding and ClusterRoleBinding do.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods-staging
  namespace: staging
subjects:
  - kind: User
    name: jane
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

The four objects at a glance

ObjectScopePurpose
RoleSingle namespaceDefines permissions within that namespace
ClusterRoleCluster-wideDefines permissions across the cluster, or a reusable set
RoleBindingSingle namespaceGrants a Role or ClusterRole to subjects, scoped to that namespace
ClusterRoleBindingCluster-wideGrants a ClusterRole to subjects across the entire cluster

The key subtlety: a ClusterRole bound via a RoleBinding grants those permissions only within that binding’s namespace — the permission set is cluster-scoped in definition, but the grant is namespace-scoped. Only a ClusterRoleBinding extends a ClusterRole’s permissions cluster-wide.

A worked example

Say you want a CI pipeline to be able to deploy to the staging namespace but read-only everywhere else. You’d define a Role in staging with create, update, and delete verbs on deployments and services, bind it to the CI system’s service account with a RoleBinding scoped to staging, and separately bind a built-in, more limited view ClusterRole to that same service account via a RoleBinding in any other namespace it needs read access to. Nothing in this setup gives the CI identity permissions outside the namespaces it’s explicitly bound in.

Service accounts and RBAC

Most RBAC subjects in a running cluster aren’t human users at all — they’re service accounts, the identity a Pod uses to talk to the Kubernetes API. Every namespace has a default service account, and any Pod that doesn’t specify one uses it automatically. That default account typically has no permissions bound to it out of the box, which is the safe default — permissions should be granted explicitly to a dedicated service account per workload, not inherited implicitly.

Common mistakes

  • Overly broad ClusterRoleBindings. Binding cluster-admin to a service account “to make something work” is the single most common RBAC misconfiguration, and it hands that workload unrestricted control over the entire cluster, including Secrets in every namespace.
  • Wildcard verbs and resources. verbs: ["*"] or resources: ["*"] are tempting shortcuts during development that often survive into production, silently granting far more than intended.
  • Forgetting namespace scope. A RoleBinding referencing a ClusterRole only grants access in its own namespace — a common source of confusion when someone expects a binding in staging to also apply in production.
  • Not auditing bindings regularly. RBAC permissions accumulate over time as teams add exceptions; periodically listing all ClusterRoleBindings (kubectl get clusterrolebindings) surfaces grants nobody remembers making.

Checking what a subject can actually do

Because permissions in RBAC are assembled from potentially many RoleBindings and ClusterRoleBindings scattered across a cluster, it’s rarely obvious just from reading YAML what a given user or service account can actually do. kubectl has a built-in check for exactly this: kubectl auth can-i create pods --namespace staging --as system:serviceaccount:staging:ci-deployer answers the question directly, evaluating every binding that applies to that identity rather than requiring you to trace the bindings by hand. Running this check as part of onboarding a new service account, or during a periodic access review, is a much faster way to catch an over-broad grant than reading raw manifests.

RBAC vs other access-control models

Kubernetes RBAC is a pure role-based model: permissions attach to roles, roles attach to subjects. It doesn’t natively support conditions based on request attributes — like time of day or resource labels — the way ABAC does, though newer admission-control mechanisms in Kubernetes can layer attribute-based logic on top of RBAC’s coarser role grants for teams that need finer-grained policy.

The takeaway

Kubernetes RBAC grants permissions through two layers: Role/ClusterRole define what’s possible, and RoleBinding/ClusterRoleBinding grant that to a subject, scoped to a namespace or the whole cluster respectively. The practical discipline is the same as any access-control system — grant the narrowest role that does the job, prefer per-workload service accounts over the default one, avoid wildcard verbs, and audit ClusterRoleBindings periodically, since a single over-broad one can undo every other restriction in the cluster.

Chisato Chisato · · 4 min read

Kubernetes Network Policies Explained

Kubernetes NetworkPolicies control which pods can talk to which, at the network layer. Here's how they work and why pods are open by default.

#Kubernetes #Cloud #DevOps
Chisato Chisato · · 5 min read

Kubernetes Admission Controllers, Explained

Admission controllers intercept requests to the Kubernetes API server after authentication, validating or mutating objects before they're persisted.

#Kubernetes #DevOps #Security