CKA — Roles & ClusterRoles

5 minute read

CKA Exam Domain

Cluster Architecture, Installation & Configuration — 25%

Roles and ClusterRoles are the foundation of Kubernetes RBAC. They define what actions are allowed on which resources. You’ll see these on the CKA exam — creating them both imperatively and declaratively.

What Is a Role?

A Role grants permissions within a specific namespace. It says: “In this namespace, you can do these things to these resources.”

If you don’t specify a namespace, a Role cannot exist — it’s namespace-scoped by design.

Here’s a Role that allows reading Pods in the dev namespace:

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

Let’s break it down:

  • apiGroups: [””] — The core API group (Pods, Services, ConfigMaps live here)
  • resources: [“pods”] — Which resources this rule applies to
  • verbs: [“get”, “list”, “watch”] — What actions are allowed

A Role can have multiple rules. Each rule is an independent permission grant:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: dev-role
  namespace: dev
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]

What Is a ClusterRole?

A ClusterRole grants permissions across the entire cluster — not limited to a single namespace.

Use ClusterRoles for:

  • Cluster-scoped resources like Nodes, PersistentVolumes, Namespaces
  • Permissions that should apply in all namespaces (when paired with a ClusterRoleBinding)
  • Aggregated roles that combine multiple ClusterRoles
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-reader
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

Notice: No namespace field — ClusterRoles are not namespaced.

Here’s another example granting access to PersistentVolumes and StorageClasses:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: storage-viewer
rules:
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
  resources: ["storageclasses"]
  verbs: ["get", "list", "watch"]

Role vs ClusterRole

Aspect Role ClusterRole
Scope Single namespace Cluster-wide
Use Case Namespace-specific permissions Cluster resources or cross-namespace
Binds With RoleBinding ClusterRoleBinding (or RoleBinding for namespace scope)
Example Resources Pods, Services, ConfigMaps Nodes, PVs, Namespaces
metadata.namespace Required Not applicable

Key insight for CKA: A ClusterRole can be bound with a RoleBinding to grant permissions in just one namespace. This is a very common pattern — define permissions once, apply per-namespace.

Defining Permissions

Verbs

Verbs define what you can do with a resource:

Verb Description HTTP Method
get Read a single resource GET
list List all resources of a type GET (collection)
watch Stream changes in real-time GET (watch)
create Create a new resource POST
update Replace an existing resource PUT
patch Partially modify a resource PATCH
delete Delete a single resource DELETE
deletecollection Delete multiple resources DELETE (collection)

Use "*" to grant all verbs — but be cautious with this in production.

API Groups

Resources belong to API groups:

API Group Resources
"" (core) pods, services, configmaps, secrets, namespaces, nodes, persistentvolumes
apps deployments, statefulsets, daemonsets, replicasets
batch jobs, cronjobs
rbac.authorization.k8s.io roles, clusterroles, rolebindings, clusterrolebindings
networking.k8s.io networkpolicies, ingresses
storage.k8s.io storageclasses

Exam tip: If you’re unsure about the API group, run kubectl api-resources — it shows the group for every resource.

Resource Names

You can restrict access to specific resources by name:

rules:
- apiGroups: [""]
  resources: ["pods"]
  resourceNames: ["my-pod", "your-pod"]
  verbs: ["get", "update"]

This limits the permission to only those specific Pods.

Common Role Patterns

Read-Only Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: read-only
  namespace: dev
rules:
- apiGroups: ["", "apps", "batch"]
  resources: ["pods", "deployments", "services", "jobs", "configmaps"]
  verbs: ["get", "list", "watch"]

Namespace Admin Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: namespace-admin
  namespace: dev
rules:
- apiGroups: ["", "apps", "batch"]
  resources: ["*"]
  verbs: ["*"]

Pod Exec Role

This is CKA-relevant — granting someone the ability to exec into Pods:

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

Note the sub-resource pods/exec — this is how Kubernetes handles exec, logs, and port-forward.

Aggregated ClusterRoles

Aggregated ClusterRoles automatically combine rules from other ClusterRoles using label selectors. Kubernetes uses this for its built-in roles.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-view
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
rules: []  # Rules are automatically filled by the controller

The monitoring ClusterRole will automatically include all rules from any ClusterRole with the label rbac.example.com/aggregate-to-monitoring: "true".

This is how the built-in admin, edit, and view ClusterRoles work.

kubectl Commands

# Create a Role imperatively
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n dev

# Create a ClusterRole imperatively
kubectl create clusterrole node-reader --verb=get,list,watch --resource=nodes

# List Roles in a namespace
kubectl get roles -n dev

# Describe a Role
kubectl describe role pod-reader -n dev

# List ClusterRoles (excluding system roles)
kubectl get clusterroles | grep -v system:

# View the YAML of a Role
kubectl get role pod-reader -n dev -o yaml

# Check which API group a resource belongs to
kubectl api-resources | grep deployments

Exam speed tip: Use kubectl create role to generate the object quickly, then modify with kubectl edit if needed.

Practice Questions

Q1. Create a Role named secret-reader in the finance namespace that allows get and list on Secrets.

Show Answer
kubectl create namespace finance
kubectl create role secret-reader --verb=get,list --resource=secrets -n finance

Or declaratively:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: secret-reader
  namespace: finance
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]

Q2. What is the difference between a Role and a ClusterRole?

Show Answer

A Role is namespace-scoped — it only grants permissions within a single namespace. A ClusterRole is cluster-wide — it can grant permissions on cluster-scoped resources (like Nodes) or be used across all namespaces.

Q3. Create a ClusterRole named pv-manager that allows all operations on PersistentVolumes.

Show Answer
kubectl create clusterrole pv-manager --verb='*' --resource=persistentvolumes

Or declaratively:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pv-manager
rules:
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["*"]

Q4. Create a Role that allows a user to exec into Pods in the debug namespace.

Show Answer
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-exec
  namespace: debug
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]

You need both the base pods resource (to find them) and the pods/exec sub-resource (to exec into them).

Q5. Which command shows the API group for a specific resource type?

Show Answer
kubectl api-resources | grep <resource-name>

For example:

kubectl api-resources | grep deployments
# Output: deployments   deploy   apps/v1   true   Deployment

The apps in apps/v1 is the API group. Use "" (empty string) in your Role for core resources that have no group prefix.

Updated: