Role vs ClusterRole

Key Differences in Kubernetes

A Role defines permissions within a single namespace — it can only grant access to resources in the namespace where it is created. A ClusterRole defines permissions cluster-wide and can grant access to cluster-scoped resources (nodes, namespaces), non-resource endpoints, or be reused across multiple namespaces via RoleBindings.

Side-by-Side Comparison

DimensionRoleClusterRole
ScopeSingle namespace onlyCluster-wide or reusable across namespaces
Namespaced ResourcesCan grant access to Pods, Services, ConfigMaps, etc. in one namespaceCan grant access to namespaced resources in all namespaces (via ClusterRoleBinding)
Cluster-Scoped ResourcesCannot grant access to nodes, namespaces, PersistentVolumes, etc.Can grant access to cluster-scoped resources
Binding TypeBound via RoleBinding (namespace-scoped)Bound via ClusterRoleBinding (cluster-wide) or RoleBinding (namespace-scoped)
ReusabilityOnly usable in its own namespaceCan be referenced by RoleBindings in any namespace
Non-Resource URLsCannot grant access to API endpoints like /healthzCan grant access to non-resource URLs

Detailed Breakdown

Role — Namespace-Scoped Permissions

A Role can only reference resources within its namespace:

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

This Role allows reading Pods and their logs, but only in the development namespace. It cannot be used in any other namespace.

To grant this Role to a user, you create a RoleBinding:

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

ClusterRole — Cluster-Wide Permissions

A ClusterRole can grant access to everything a Role can, plus cluster-scoped resources:

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

This grants read access to nodes (cluster-scoped), PersistentVolumes (cluster-scoped), and the /healthz endpoint (non-resource URL). None of these can be expressed in a Role.

ClusterRoleBinding — Cluster-Wide Grant

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-nodes-global
subjects:
  - kind: Group
    name: developers
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: node-reader
  apiGroup: rbac.authorization.k8s.io

This grants the node-reader ClusterRole to all users in the developers group, across the entire cluster.

The Reusable ClusterRole Pattern

One of the most powerful RBAC patterns is defining a ClusterRole once and binding it per-namespace with RoleBindings. This avoids duplicating Role definitions:

# Define once as a ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: deployment-manager
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
# Bind in team-a namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: team-a-deployment-manager
  namespace: team-a
subjects:
  - kind: Group
    name: team-a-devs
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: deployment-manager
  apiGroup: rbac.authorization.k8s.io
# Bind in team-b namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: team-b-deployment-manager
  namespace: team-b
subjects:
  - kind: Group
    name: team-b-devs
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: deployment-manager
  apiGroup: rbac.authorization.k8s.io

Even though deployment-manager is a ClusterRole, binding it with a RoleBinding restricts the permissions to that specific namespace. Team A can manage Deployments in team-a but not in team-b, and vice versa.

Built-in ClusterRoles

Kubernetes ships with several default ClusterRoles:

kubectl get clusterroles | grep -E "^(admin|edit|view|cluster-admin)"
  • cluster-admin — full access to everything (superuser)
  • admin — full access within a namespace (when bound with RoleBinding)
  • edit — read/write access to most namespace resources (no RBAC modification)
  • view — read-only access to most namespace resources (no Secrets)

These are designed to be bound per-namespace. For example, granting admin to a team lead in their namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: team-lead-admin
  namespace: production
subjects:
  - kind: User
    name: alice
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io

Service Account Permissions

RBAC applies to ServiceAccounts the same way. If a Pod needs to list other Pods (e.g., for leader election), you create a Role and bind it to the ServiceAccount:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-lister
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-app-pod-lister
  namespace: production
subjects:
  - kind: ServiceAccount
    name: my-app
    namespace: production
roleRef:
  kind: Role
  name: pod-lister
  apiGroup: rbac.authorization.k8s.io

Principle of Least Privilege

The security best practice is:

  1. Start with Roles (namespace-scoped) unless you specifically need cluster-scoped access
  2. Use ClusterRoles with RoleBindings for reusable permission sets
  3. Only use ClusterRoleBindings for truly cluster-wide needs (monitoring, node management)
  4. Never grant cluster-admin to application ServiceAccounts
  5. Use resourceNames to restrict access to specific resources when possible
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["app-secret"]  # Only this specific Secret
    verbs: ["get"]

Use Role when...

  • You need to grant access to resources in a single namespace only
  • You want to enforce strict namespace-level isolation
  • Team-specific permissions that should not leak across namespaces
  • Following the principle of least privilege for namespace-scoped work

Use ClusterRole when...

  • You need to grant access to cluster-scoped resources (nodes, PVs, namespaces)
  • You want to define a reusable set of permissions applied per-namespace via RoleBindings
  • You're granting read access across all namespaces (e.g., monitoring tools)
  • You need to grant access to non-resource URLs like /healthz or /metrics
  • You're defining admin, edit, or view roles used across the organization

Model Interview Answer

A Role is namespace-scoped — it grants permissions to resources like Pods, Services, and ConfigMaps within a single namespace and is bound to subjects via a RoleBinding. A ClusterRole is cluster-scoped — it can grant access to cluster-wide resources like nodes and PersistentVolumes, non-resource endpoints like /healthz, and namespaced resources across all namespaces. A useful pattern is defining a ClusterRole once and binding it in specific namespaces with RoleBindings. For example, you create a ClusterRole called 'pod-reader' and then create a RoleBinding in each team's namespace to grant that role, avoiding duplication.

Related Comparisons