Why can't every application in your cluster just have the same power as the admin? In the real world, that would be a security disaster — one buggy app could accidentally delete your entire database. Role-Based Access Control (RBAC) and ServiceAccounts solve this by giving each user and automated process only the precise permissions it needs to do its job, nothing more.
Jump to a section
A simple way to picture Role-Based Access Control (RBAC) and ServiceAccounts
Have you ever visited a friend in a large apartment building and wondered how the building manager keeps residents safe while letting delivery drivers, cleaners, and repair technicians do their jobs?
The building has a master key that opens every door — the landlord has this. Residents have keys that open their own apartment and the main entrance. The cleaner has a key that opens only the lobby and the cleaning supply closet. The electrician, visiting for a specific job, gets a temporary key that opens only the electrical room and expires at 5pm. Each key grants exactly the access needed, nothing more. If the cleaner loses their key, the landlord doesn't replace the building's entire lock system; they just make a new cleaning key. When a resident moves out, their key stops working, but no one else is affected.
This is Role-Based Access Control — the building manager (Kubernetes) assigns keys (permissions) based on who you are and what job you need to do. A ServiceAccount is like a delivery driver's uniform and ID badge — it's not a person, but an identity that an automated system (a delivery app or background service) uses to prove who it is and request access. Just as you wouldn't give the delivery driver a master key to every apartment, you create precise, limited permissions for each ServiceAccount.
Role-Based Access Control (RBAC) is a method of regulating access to resources based on the roles of individual users or automated processes. In Kubernetes, it is how you control who can do what within your cluster. Before RBAC, many systems used a simpler model: either you were an admin (full access) or you had no access. That approach is fragile and dangerous — one person with too much power can accidentally break everything. RBAC replaces that with a fine-grained, least-privilege approach.
At its heart, Kubernetes RBAC has four key components: Rules, Roles, Subjects, and RoleBindings. Let's define each.
A Rule is a single permission statement. It specifies an API group (the category of resource, like 'apps' for Deployments), a resource (like 'pods' or 'services'), and verbs (actions like 'get', 'list', 'create', 'delete'). For example, a rule might say: 'allow the get and list verbs on pods in the core API group'.
A Role is a collection of rules. You group related rules together into a single Role. There are two types of Roles in Kubernetes. A regular Role applies to a specific namespace (a virtual cluster within your cluster). A ClusterRole applies to the entire cluster, across all namespaces. For example, you might have a 'pod-reader' Role in the 'production' namespace that contains rules for reading pods and services. If you need to grant the same permissions across every namespace, you would use a ClusterRole.
A Subject is the entity that gets the permission. It can be a User (a real person), a Group (a collection of users), or a ServiceAccount (an identity for automated processes, like a running application). In Kubernetes, Users and Groups are often managed by an external system like Microsoft Entra ID, but ServiceAccounts are native Kubernetes objects that live inside the cluster.
A RoleBinding (or ClusterRoleBinding) is the link between a Role and a Subject. It says 'this role's permissions are now granted to this subject'. A RoleBinding works within a specific namespace, and a ClusterRoleBinding works cluster-wide. If you create a RoleBinding that attaches the 'pod-reader' Role to the 'my-service-account' ServiceAccount in the 'production' namespace, then that ServiceAccount can now get and list pods only in that namespace.
ServiceAccounts are a special kind of subject. They are not people; they are identities for workloads that run inside a pod. Every pod is automatically assigned a ServiceAccount (the 'default' ServiceAccount in its namespace) unless you specify a different one. You can create custom ServiceAccounts for different applications. For example, you might have a 'monitoring-serviceaccount' with read-only access to pods and services, and a 'build-serviceaccount' with permission to create and delete jobs.
When you create a pod and assign it a ServiceAccount, Kubernetes automatically mounts a token into the pod. This token is a secret credential that the application inside the pod uses to authenticate to the Kubernetes API server. The API server checks the token, identifies which ServiceAccount it belongs to, and then checks the RoleBindings to see if that ServiceAccount is allowed to perform the requested action. If the token does not have the right permissions, the API server denies the request with a '403 Forbidden' error.
The combination of Roles, RoleBindings, and ServiceAccounts gives you extremely fine-grained control. You can create a Role that allows only listing pods (no creating or deleting), bind it to only one ServiceAccount, and that ServiceAccount's applications are locked down. This is critical for security and reliability. If an application runs with a ServiceAccount that only has read access to its own namespace, even if the application is compromised, the attacker cannot touch other namespaces, cannot delete data, and cannot see other teams' secrets.
Kubernetes also supports aggregation of ClusterRoles, allowing you to build complex permission sets from smaller, reusable pieces. But for the CKAD exam, the fundamental workflow is: create a Role (or ClusterRole), create a ServiceAccount, then create a RoleBinding (or ClusterRoleBinding) to connect them. You will need to write YAML files that define these objects.
Remember: Roles are namespaced, ClusterRoles are not. RoleBindings bind namespaced roles to subjects within a namespace. ClusterRoleBindings bind cluster-scoped roles to subjects and apply to all namespaces. You can also bind a ClusterRole to a subject within a specific namespace using a RoleBinding — that is a common pattern to reuse a set of cluster-wide permissions but limit them to one namespace.
Identify the Subject
Determine who or what needs access: a human user, a group of users, or a ServiceAccount (an automated process running in a pod). This defines the 'subjects' field in the binding. For ServiceAccounts, you must create the ServiceAccount object first if it does not exist.
Define the Required Permissions
What specific actions does the subject need to perform? List the resources (e.g., pods, services, deployments) and the verbs (e.g., get, list, create, delete). Group these into a single set of rules. If the resources are namespaced and the permissions are only needed in one namespace, plan to use a Role. If permissions are needed across all namespaces or for cluster-scoped resources, plan a ClusterRole.
Create the Role or ClusterRole
Write a YAML manifest with kind: Role or kind: ClusterRole. Include the rules array with apiGroups (e.g., 'apps' for Deployments, '' for core resources), resources (e.g., 'pods', 'services'), and verbs. Apply it using kubectl apply -f file.yaml. Verify by describing the Role.
Create or Identify the ServiceAccount (if needed)
If the subject is a ServiceAccount, use 'kubectl create serviceaccount <name> -n <namespace>' or write a YAML manifest with kind: ServiceAccount. If the subject is a human user, you do not create them in Kubernetes; you just know their username as defined by your external identity provider.
Create the RoleBinding or ClusterRoleBinding
Write a YAML manifest that links the Role/ClusterRole to the Subject. The manifest includes: apiVersion (rbac.authorization.k8s.io/v1), kind (RoleBinding or ClusterRoleBinding), subjects array (with kind: ServiceAccount, User, or Group, and name), and roleRef (with kind: Role or ClusterRole, name, and apiGroup: rbac.authorization.k8s.io). Apply it. The binding grants the permission.
Test the Permissions
To verify, run a temporary pod using the ServiceAccount or authenticate as the user. Try to perform the allowed and disallowed actions. Use 'kubectl auth can-i' to check: for example, 'kubectl auth can-i get pods --as=system:serviceaccount:namespace:sa-name'. If the command returns 'yes', the binding works. This step confirms that your RBAC configuration is correct.
Imagine you work at a company called 'FinSave', a financial services startup that runs its applications on Kubernetes. The platform team manages three namespaces: 'production', 'staging', and 'developer-sandbox'. Each namespace runs microservices for different parts of the banking application. You, as a platform engineer, must ensure that developers can see logs and troubleshoot their own services, but cannot touch other teams' services or, most importantly, delete production data.
Here is how you use RBAC and ServiceAccounts in practice. First, you identify the different roles needed. - The 'development-team' role needs read-only access to pods and services in their own namespace, plus the ability to view logs. They should not be able to create or delete anything. - The 'ci-cd-pipeline' ServiceAccount needs permission to create and update Deployments and Services in the staging namespace, but only read access in production (to verify deployments succeeded). - The 'monitoring-system' ServiceAccount needs cluster-wide read access to metrics endpoints on pods and nodes, but nothing else. - The 'security-auditor' role (a person) needs read-only access to all namespaces, including access to Secrets (to check encryption) but no ability to modify them.
You start by creating ClusterRoles for the security auditor (cluster-wide read access) and the monitoring system (read-access to metrics). For the development team, you create a namespaced Role called 'developer-readonly' in each namespace. For the CI/CD pipeline, you create a namespaced Role in staging that permits create, update, and read on Deployments and Services. Then you create a separate Role in production with only read access.
Next, you create ServiceAccounts. For the CI/CD pipeline, you create a ServiceAccount called 'build-bot' in the 'staging' namespace. For monitoring, you create 'monitoring-agent' in the 'kube-system' namespace. For developers, you might create a ServiceAccount per team or use their user identities from Microsoft Entra ID.
Then you create the RoleBindings. You bind the 'developer-readonly' Role to the development team's user group (authenticated via Microsoft Entra ID) using a RoleBinding in each team's namespace. You bind the 'ci-cd-staging-role' to the 'build-bot' ServiceAccount in staging. You bind the 'ci-cd-production-readonly' Role to the same 'build-bot' ServiceAccount in production. You bind the 'monitoring-clusterrole' to the 'monitoring-agent' ServiceAccount using a ClusterRoleBinding. Finally, you bind the 'security-auditor-clusterrole' to the auditor's user identity using a ClusterRoleBinding.
After this setup, you test by trying to access the production API as the 'build-bot' token — you can list deployments, but a delete request returns a 403 error. The application is safe. Every automated process and human being has exactly the access it needs, and nothing more. If a new developer joins, you just add them to the correct group in Microsoft Entra ID, and the existing RoleBindings automatically grant the correct permissions. If a developer leaves, you remove them from the group — no manual cleanup needed.
This is day-to-day work for a Kubernetes administrator and a critical skill for the CKAD exam. You must be comfortable writing YAML manifests that define Roles, RoleBindings, ServiceAccounts, and understanding how they connect.
The CKAD exam tests your ability to configure RBAC and ServiceAccounts in a real cluster environment (not multiple choice). You will be given a set of tasks and must write or modify YAML manifests to achieve the desired access control. The exam environment is a live Kubernetes cluster, and you need to create, apply, and verify your changes.
Exam topics that frequently appear:
Creating a ServiceAccount and binding it to a specific Role using a RoleBinding. For example: 'Create a ServiceAccount named monitoring-sa in the default namespace. Create a Role that allows get, list, and watch on pods. Bind the Role to the ServiceAccount.'
Using a ClusterRole to grant cluster-wide permissions, then using a RoleBinding to limit those permissions to a specific namespace. This is a common pattern: create a ClusterRole for reading pods, then use a RoleBinding to bind it to a ServiceAccount in a specific namespace. The exam expects you to know that you can reference a ClusterRole in a RoleBinding.
Understanding the difference between Role and ClusterRole, and between RoleBinding and ClusterRoleBinding. Traps often involve using a Role when a ClusterRole is needed, or vice versa. For instance, if the task says 'grant access to nodes', you must use a ClusterRole because nodes are cluster-scoped resources, not namespaced.
The concept of 'verbs' — the actions you are allowed to perform. You must know the common verbs: get, list, watch, create, update, patch, delete. The exam may ask you to specify 'get' and 'list' for read access, and 'create' and 'delete' for write access.
The 'apiGroups' field. Many beginners forget to specify the correct API group. For example, to grant access to Deployments, you need the apiGroup 'apps'. To grant access to pods, you need the apiGroup '' (empty string, which means the core group). For custom resources, you may use '*' to match any API group.
The 'resourceNames' field for limiting access to specific named resources within a type. For example, you can create a Role that allows updating only a specific Pod named 'my-pod'. This is less common but appears on the exam.
Common traps:
Creating a RoleBinding but forgetting to specify the namespace in the YAML metadata. The RoleBinding must be in the same namespace as the Role (if the Role is namespaced) or the binding targets. Otherwise, the binding will fail or bind to the wrong scope.
Confusing Subjects with RoleRefs. In the YAML for a RoleBinding, you have a 'subjects' field (an array listing users, groups, or ServiceAccounts) and a 'roleRef' field (a single reference to a Role or ClusterRole). If you put the Role under 'subjects', it will not work.
Using 'subjects.kind: User' when you actually need 'subjects.kind: ServiceAccount'. ServiceAccounts are native Kubernetes objects, while Users are usually external. If you are binding a ServiceAccount, always use kind: ServiceAccount.
Forgetting to de-escalate permissions. The exam may ask you to create a ServiceAccount with limited access. Beginners sometimes copy an existing manifest that has too many permissions. Always read the question carefully — it will specify exactly which resources and verbs are allowed.
The default ServiceAccount. Every namespace has a default ServiceAccount that pods automatically use unless you specify a different one. The default ServiceAccount has no permissions beyond the default (which is often very limited or none). You may be asked to modify the default ServiceAccount or create a new one.
What you should memorise: the exact YAML structure for a Role, RoleBinding, ServiceAccount, ClusterRole, and ClusterRoleBinding. You will not have internet access during the exam, so you must know the fields: apiVersion (rbac.authorization.k8s.io/v1), kind, metadata, rules, subjects, roleRef. Also remember that the apiVersion for ServiceAccount is v1. Practise writing these manifests from scratch without autocompletion.
RBAC in Kubernetes uses four core objects: Rules (individual permissions), Roles (groups of rules), Subjects (users, groups, or ServiceAccounts), and RoleBindings (links between Roles and Subjects).
A Role is namespaced and can only grant access to resources within that namespace; a ClusterRole is cluster-wide and can grant access to cluster-scoped resources like Nodes.
A RoleBinding binds a Role to a Subject within a specific namespace; a ClusterRoleBinding binds a ClusterRole to a Subject across all namespaces.
ServiceAccounts are identities for automated processes (pods), not human users, and they are created as Kubernetes objects in a namespace.
Every pod is assigned a ServiceAccount — by default the 'default' ServiceAccount in its namespace — but that default has no permissions until you bind a Role to it.
You can reuse a ClusterRole in multiple namespaces by creating separate RoleBindings in each namespace that reference the same ClusterRole.
The YAML apiVersion for RBAC objects is 'rbac.authorization.k8s.io/v1' and for ServiceAccounts is 'v1'.
Common verbs in a rule are: get, list, watch, create, update, patch, delete — know them exactly for the exam.
These come up on the exam all the time. Here's how to tell them apart.
Role
Namespaced: applies only to resources in one specified namespace
Cannot grant access to cluster-scoped resources like Nodes or PersistentVolumes
Defined with kind: Role and lives within a namespace
ClusterRole
Cluster-scoped: applies to resources across all namespaces
Can grant access to both namespaced and cluster-scoped resources
Defined with kind: ClusterRole and exists at the cluster level, not in a namespace
RoleBinding
Binds a Role (or ClusterRole) to subjects within a specific namespace
Limits the effect of the bound Role or ClusterRole to that single namespace only
Must be created in the same namespace as the Role (if binding a namespaced Role)
ClusterRoleBinding
Binds a ClusterRole to subjects across all namespaces
Grants permissions cluster-wide, affecting all namespaces simultaneously
Cannot bind a namespaced Role; only works with ClusterRoles
ServiceAccount
Native Kubernetes object created with kubectl or YAML
Used by automated processes running in pods; token is mounted automatically
Has an associated secret token used for authentication to the API server
User (human)
Managed externally (e.g., Microsoft Entra ID, X.509 certificates, static token file)
Exists as an identity for human operators or external systems
Not created with kubectl; you bind permissions to them by name, but no Kubernetes object represents them
Default ServiceAccount
Automatically created in every namespace with zero permissions
Used by any pod that does not specify a serviceAccountName
Cannot be deleted permanently; Kubernetes recreates it if removed
Custom ServiceAccount
Created manually for specific applications or workloads
Typically bound to a Role or ClusterRole with precisely needed permissions
Can be deleted and recreated as needed; not automatically managed
Verbs (get, list, watch)
Used for read-only access to resources
'get' retrieves a single resource; 'list' retrieves a collection; 'watch' streams updates
Safe for monitoring and read-only dashboards without risk of data modification
Verbs (create, update, patch, delete)
Used for write or destructive operations on resources
'create' adds new resources; 'update/patch' modifies existing ones; 'delete' removes them
Dangerous if granted excessively; should be limited to specific ServiceAccounts or users
Mistake
ServiceAccounts and Users are the same thing; both need to be created inside Kubernetes.
Correct
ServiceAccounts are Kubernetes-native objects created with kubectl create serviceaccount. Users are typically managed externally (e.g., via Microsoft Entra ID or X.509 certificates). Kubernetes does not have a User API object. You can bind permissions to external users by name, but you cannot create them inside the cluster.
Because the kubectl command 'create serviceaccount' exists, beginners assume there is a parallel 'create user' command. Kubernetes delegates user management to external identity systems.
Mistake
Creating a Role automatically grants that role to everyone in the namespace until you delete it.
Correct
A Role is just a set of rules. Permissions are only granted when you explicitly bind a Role to a Subject using a RoleBinding or ClusterRoleBinding. Without a binding, a Role does nothing.
The term 'Role' sounds like a job title that comes with inherent permissions (like 'Manager'). In Kubernetes, a Role is inert until attached.
Mistake
If you create a RoleBinding with a ClusterRole, the permissions apply to all namespaces.
Correct
If you bind a ClusterRole to a subject using a RoleBinding (not a ClusterRoleBinding), the permissions are limited to the namespace where the RoleBinding exists. This is a common pattern to reuse a broad set of rules but restrict them to one namespace.
The word 'ClusterRole' sounds like it always applies to the whole cluster. Beginners miss that a RoleBinding scopes it down.
Mistake
The default ServiceAccount in each namespace has full admin access to that namespace.
Correct
The default ServiceAccount is created automatically but has no permissions assigned by default. In many clusters, it may have no access at all unless explicitly bound to a Role. If a pod uses the default ServiceAccount without any binding, it cannot do anything via the API server.
The name 'default' sounds like it comes with default permissions. In reality, it is a placeholder with zero permissions for security reasons.
Mistake
Roles and ClusterRoles are identical except for the name.
Correct
Roles are namespaced resources — they exist within a specific namespace and cannot reference cluster-scoped resources like Nodes or PersistentVolumes. ClusterRoles are cluster-scoped and can reference both namespaced and cluster-scoped resources.
The YAML structure looks similar, so beginners assume the only difference is the 'kind' field. The functional difference in what resources they can govern is critical.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
A Role applies to resources within a single namespace. A ClusterRole applies to resources across all namespaces and also to cluster-scoped resources like Nodes, PersistentVolumes, and Namespaces themselves. You use a Role for namespaced access and a ClusterRole for cluster-wide or cluster-scoped access.
Yes. Use a RoleBinding (not a ClusterRoleBinding) that references the ClusterRole in the 'roleRef' field. The RoleBinding will limit the ClusterRole's permissions to the namespace where the RoleBinding is created.
Use 'kubectl create serviceaccount my-sa -n my-namespace' or write a YAML manifest with kind: ServiceAccount and apiVersion: v1. Then, in your pod specification, set the 'serviceAccountName' field to 'my-sa'. If you do not set it, the pod uses the 'default' ServiceAccount in its namespace.
The pod's ServiceAccount lacks the necessary permissions. You need to create a Role (or ClusterRole) with the 'list' verb on 'pods' in the correct apiGroup, and then bind that Role to the ServiceAccount using a RoleBinding (or ClusterRoleBinding). The default ServiceAccount has no permissions.
It specifies which API group the resource belongs to. For example, Deployments are in the 'apps' group, so apiGroups: ['apps']. Core resources like Pods and Services are in the core group, which is represented by an empty string: apiGroups: ['']. You can use apiGroups: ['*'] to match any group.
Technically yes, but Kubernetes will automatically recreate it. It is better to leave it and create your own ServiceAccounts for pods that need specific permissions. Do not rely on the default ServiceAccount for anything other than pods that need no API access.
You've finished Role-Based Access Control (RBAC) and ServiceAccounts. Continue through the CKAD study guide to build a complete picture of the exam.
Done with this chapter?