Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Implement RBAC for Cluster Security

Learn to secure your Kubernetes cluster with Role-Based Access Control (RBAC). This hands-on tutorial covers roles, bindings, and best practices to enforce least-privilege access.

Focus: implement rbac for cluster security

Sponsored

Have you ever given a Kubernetes user or application more permissions than it needed, just to get things running quickly? That cluster-admin binding may feel convenient at first, but it opens a dangerous hole in your cluster's security. This lesson shows you how to implement Role-Based Access Control (RBAC) for cluster security—replacing dangerous blanket permissions with precise, least-privilege roles that protect your workloads and data.

The problem this lesson solves

Kubernetes, by default, places few restrictions on who can do what inside the cluster. Without RBAC, every authenticated user may have full access to pods, secrets, and cluster resources. In production, this means:

  • A compromised CI/CD token can destroy your entire namespace.
  • Developers can accidentally delete critical system components.
  • Auditors cannot trace who performed destructive actions.

RBAC solves these problems by defining exact who (user, group, service account) can do what (verb) to which resource (pod, secret, deployment, namespace). It is the standard authorization mechanism for Kubernetes clusters since v1.6.

Pro tip: RBAC is not an add-on—it is required by most managed Kubernetes services (EKS, AKS, GKE) and is enabled out of the box. Ignoring it means operating without any access control.

Core concept / mental model

Think of RBAC as an employee badge system for your cluster:

  • Roles are the job descriptions: "Can read logs, cannot delete pods."
  • RoleBindings are the badges pinned to individuals: "Alice gets the developer role."
  • Subject is the person (or service) wearing the badge.

The magic is that you never assign permissions directly to a subject. Instead, you create a Role and bind it to a subject with a RoleBinding (or ClusterRole / ClusterRoleBinding for cluster-scoped actions).

Key definitions

Term Description Example
Role Namespace-scoped set of rules get, list, watch pods in default namespace
ClusterRole Cluster-wide rules (or rules that apply to namespaced resources) get nodes, create persistentvolumes
RoleBinding Binds a Role to subjects in a namespace alicepod-reader Role in default namespace
ClusterRoleBinding Binds a ClusterRole to subjects cluster-wide cluster-admins group → cluster-admin ClusterRole
Subject User, group, or ServiceAccount system:serviceaccount:default:my-app

A ClusterRole can also be used with a regular RoleBinding to grant namespace-scoped permissions without creating a new Role. This is common for common patterns like view, edit, admin.

How it works step by step

RBAC works through the Kubernetes API server, which checks each request against the current set of bindings. The request flow is:

  1. Authentication – Who is making the request? (TLS certificate, token, OIDC, etc.)
  2. Authorization – Does the subject have a RoleBinding that allows this action?
  3. Admission control – Extra plugins (e.g., PodSecurityPolicy) further filter requests.

The RBAC evaluation follows these rules:

  • If a binding grants get pods, the subject can read pods in that namespace.
  • If no binding allows the action, it is denied. Kubernetes denies by default.
  • If a subject matches multiple bindings, the permissions union (OR logic) applies.
  • Deny rules do not exist in RBAC—you cannot explicitly deny a user; you simply do not grant the permission.

Creating a namespace-scoped Role and RoleBinding

  1. Define a Role with allowed verbs and resources.
  2. Identify the subject (user, group, or ServiceAccount).
  3. Create a RoleBinding that links subject to the Role.

Cluster-level permissions

For resources that are not namespaced (e.g., nodes, persistentvolumes, storageclasses) or if you want the binding to apply to all namespaces, use ClusterRole and ClusterRoleBinding.

Hands-on walkthrough

Let's create a safe environment: a read-only developer account in a test namespace.

Step 1: Create a namespace and a ServiceAccount

kubectl create namespace dev-team
kubectl create serviceaccount read-only-dev -n dev-team

Step 2: Define a Role for reading pods and logs

Save this as pod-reader-role.yaml:

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

Apply it:

kubectl apply -f pod-reader-role.yaml

Step 3: Bind the role to the ServiceAccount

Save as pod-reader-binding.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: dev-team
subjects:
- kind: ServiceAccount
  name: read-only-dev
  namespace: dev-team
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Apply it:

kubectl apply -f pod-reader-binding.yaml

Step 4: Test the permissions

# Get the token of the ServiceAccount
TOKEN=$(kubectl get secret $(kubectl get sa read-only-dev -n dev-team -o jsonpath='{.secrets[0].name}') -n dev-team -o jsonpath='{.data.token}' | base64 --decode)

# Test get pods (should succeed)
kubectl --token=$TOKEN get pods -n dev-team
# Expected output: No resources found in dev-team namespace.

# Test delete a pod (should fail)
kubectl --token=$TOKEN delete pod some-pod -n dev-team
# Expected output: Error from server (Forbidden): pods "some-pod" is forbidden: User "system:serviceaccount:dev-team:read-only-dev" cannot delete resource "pods" in API group "" in the namespace "dev-team"

The deletion attempt shows exactly how RBAC rejects unauthorized actions with a clear 403 Forbidden error.

Step 5: Create a ClusterRole to read nodes

Save as node-reader-clusterrole.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-reader
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list"]

Apply it and bind to your ServiceAccount:

kubectl apply -f node-reader-clusterrole.yaml
kubectl create clusterrolebinding node-reader-binding --clusterrole=node-reader --serviceaccount=dev-team:read-only-dev

Now the ServiceAccount can also list nodes.

Compare options / when to choose what

Approach When to use Example
Role + RoleBinding Permissions only in one namespace Developer accessing only their team namespace
ClusterRole + ClusterRoleBinding Cluster-wide permissions Admin viewing all nodes
ClusterRole + RoleBinding Reuse a common role in many namespaces but limit per namespace view ClusterRole bound to many namespaces

Key insight: Prefer namespace-scoped Roles for most users. Use ClusterRoles only when necessary (e.g., monitoring tools that need to read cluster-wide metrics).

Troubleshooting & edge cases

Problem 1: Your role exists but the user gets "forbidden"

Possible cause: The binding is missing, incorrect namespace, or subject name does not match.

Check:

kubectl describe rolebinding <binding-name> -n <namespace>
kubectl auth can-i --list --as=system:serviceaccount:dev-team:read-only-dev -n dev-team

Problem 2: A ServiceAccount inherits too many permissions

Possible cause: ClusterRoleBinding applies to all subjects in a group. Review all bindings:

kubectl get clusterrolebindings --all-namespaces
kubectl describe clusterrolebinding <name>

Problem 3: You need to give a third-party Helm chart minimal permissions

Most charts ship with their own RBAC templates. Override them by installing with --set rbac.create=false and create your own minimal Role/ClusterRole before installing.

Edge case: Group-level bindings

Kuberentes does not have first-class groups, but you can bind to groups from external identity providers:

subjects:
- kind: Group
  name: "devops-team"
  apiGroup: rbac.authorization.k8s.io

Common mistake: Forgetting that RoleBinding cannot bind to a subject outside its namespace. Use ClusterRoleBinding for cluster-wide subjects.

What you learned & what's next

You now understand how to implement RBAC for cluster security by: - Distinguishing between Roles, ClusterRoles, RoleBindings, and ClusterRoleBindings. - Creating concrete Role definitions and binding them to users or ServiceAccounts. - Testing permissions with kubectl auth can-i and live API calls. - Troubleshooting common RBAC permission errors.

Next step: In the following lesson, you will learn how to audit RBAC configurations and build a least-privilege strategy using tools like kubectl rbac-lookup and custom validation webhooks.

Practice recap

Now apply your understanding: create a new ServiceAccount called deployer in a prod namespace, then write a Role that allows get, list, watch on deployments and create on pods. Bind it to the ServiceAccount and verify that deleting a deployment is rejected. This exercise reinforces how granular permissions prevent accidental production changes.

Common mistakes

  • Binding a Role directly to a user or ServiceAccount without a RoleBinding—the binding object is required.
  • Using a RoleBinding with a ClusterRole from a different namespace—RoleBindings must be in the same namespace as the Role.
  • Forgetting to include the apiGroups field for non-core resources (e.g., apps/v1 for deployments).
  • Assigning cluster-wide ClusterRoleBindings to ServiceAccounts that only need namespace-scoped access.
  • Not testing permissions with kubectl auth can-i before deploying into production.

Variations

  1. Use Kubernetes RBAC aggregration (aggregationRule) to combine multiple ClusterRoles into one.
  2. Leverage external authorization webhooks (e.g., OPA Gatekeeper) for fine-grained policy beyond RBAC.
  3. Use kubectl create role and kubectl create rolebinding shorthand commands to avoid YAML.

Real-world use cases

  • A CI/CD pipeline only needs get, list, watch on pods in a staging namespace—create a dedicated ServiceAccount with a RoleBinding.
  • Cluster-wide monitoring tool (e.g., Prometheus) must read pod and node metrics across all namespaces—use a ClusterRole + ClusterRoleBinding.
  • A multi-tenant SaaS platform isolates each customer into a separate namespace with its own admin RoleBinding granting full control only within that namespace.

Key takeaways

  • RBAC is Kubernetes' primary authorization mechanism—always enabled by default, never disable it.
  • RoleBindings apply to a specific namespace; ClusterRoleBindings apply cluster-wide.
  • Verbs (get, list, create, delete, watch) are the actions a role permits—map them explicitly to match your security needs.
  • Test any RBAC change with kubectl auth can-i before depending on it in production.
  • Use ServiceAccount tokens for workloads (pods), not human users; combine with kubectl for manual testing.
  • Prefer namespace-scoped Roles over ClusterRoles to follow the principle of least privilege.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.