Kubernetes RBAC is less about granting permissions and more about defining what actions are allowed on which resources for whom.
Let’s see it in action. Imagine a Developer role that can only get, list, and watch Pods within a specific namespace, but can also create and update Deployments.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: pod-and-deployment-manager
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["create", "update", "get", "list", "watch"]
This Role defines the permissions. Now, we need to bind a user, let’s say alice, to this Role within the development namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: alice-dev-binding
namespace: development
subjects:
- kind: User
name: alice # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-and-deployment-manager # Name of the Role defined above
apiGroup: rbac.authorization.k8s.io
Here, alice can now perform the defined actions on Pods and Deployments in development. If alice tries to delete a Pod, the request will be denied because delete is not in the verbs list for Pods in this Role.
The system solves the problem of granular, secure access control in a multi-tenant or team-based Kubernetes environment. Without RBAC, everyone might have broad access, leading to accidental or malicious modification of resources. RBAC allows you to enforce the principle of least privilege, ensuring users and service accounts can only do what they absolutely need to do.
The core components are Roles (or ClusterRoles for cluster-wide permissions) and RoleBindings (or ClusterRoleBindings). Roles define a set of permissions. RoleBindings grant those permissions to specific subjects (users, groups, or service accounts) within a namespace. ClusterRoles are similar to Roles but apply across all namespaces, and ClusterRoleBindings link ClusterRoles to subjects cluster-wide.
Think of it like this: a Role is a job description, and a RoleBinding is assigning a person to that job. A ClusterRole is a global policy, and a ClusterRoleBinding is assigning someone to that global policy.
The difference between Roles and ClusterRoles is crucial. Roles are namespace-scoped. If you define a Role in the kube-system namespace, it only applies to resources within kube-system. ClusterRoles, however, are cluster-scoped. A ClusterRole granting cluster-admin privileges applies to all namespaces. You can also use ClusterRoles to grant permissions to non-namespaced resources like nodes or namespaces themselves.
When a user makes an API request, the Kubernetes API server intercepts it. It checks the user’s identity and then consults the RBAC rules defined in Roles, ClusterRoles, and their corresponding bindings. If a matching rule allows the requested action on the specified resource, the request proceeds. Otherwise, it’s denied with a Forbidden error.
For example, if alice tries to get a Pod in the production namespace, but her RoleBinding only grants access in the development namespace, the API server will deny the request.
A common pitfall is confusing Roles and ClusterRoles or mismanaging namespaces in RoleBindings. For instance, creating a Role in namespace-a but then trying to bind it to a user for namespace-b using a RoleBinding in namespace-b won’t work; the Role must exist in the same namespace as the RoleBinding.
The apiGroups field is fundamental. If it’s [""], it refers to the core Kubernetes API group (e.g., Pods, Services, Namespaces). Other common apiGroups include apps (Deployments, StatefulSets), batch (Jobs, CronJobs), networking.k8s.io (Ingresses, NetworkPolicies), and storage.k8s.io (StorageClasses). You can specify multiple apiGroups in a single rule.
When you apply a RoleBinding, the subjects field can refer to User, Group, or ServiceAccount. For User and Group, the names are typically tied to your authentication provider (e.g., OIDC, cert-manager). For ServiceAccount, the name is the name of the ServiceAccount in the same namespace as the RoleBinding.
The roleRef field within a RoleBinding must accurately point to the Role (or ClusterRole) you want to bind. It requires kind (either Role or ClusterRole), name, and apiGroup.
A subtle but powerful aspect is the ability to bind ClusterRoles to RoleBindings within a specific namespace. This allows you to grant cluster-wide permissions (defined in a ClusterRole) but restrict their application to a particular namespace. This is often used for operators or controllers that need broad access but are confined to managing resources within a single namespace.
The next hurdle is often managing RBAC at scale, especially when dealing with many namespaces and users, which leads to exploring tools like OPA Gatekeeper or the Kyverno policy engines.