20.2 Role and ClusterRole: Defining Permissions
Right, let’s talk about the two ways you tell Kubernetes who can do what. We have Role and ClusterRole. The difference is in the scope, and it’s the single most important concept to grasp here. If you mess this up, you’ll either be locked out of your own cluster or you’ll accidentally give the testing namespace the keys to the kingdom. Let’s avoid both outcomes.
Think of it like this: a Role is a set of permissions for a specific neighborhood (a namespace), like being able to lock and unlock every door on Main Street. A ClusterRole is the same set of permissions, but for the entire city (the whole cluster), like being a master keyholder for every street. You wouldn’t give the master city key to someone who just needs to water the plants in one building. Kubernetes feels the same way.
Role: Your Namespace-Specific Rulebook
A Role is namespace-scoped. This means it only has power within the namespace where you define it. This is your go-to for 99% of application-level permissions. You want your frontend pod in the web namespace to be able to talk to the backend service? You define a Role in the web namespace that grants get, list, and watch on services.
Here’s what a simple, useful Role looks like. We’re letting someone see what pods are up to in a specific namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: my-app-namespace # The crucial part: the jail cell for these permissions.
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group. No, it's not a mistake, it's just quirky.
resources: ["pods"] # The thing you want access to.
verbs: ["get", "list", "watch"] # The actions you're allowed to perform on the thing.
Why apiGroups: [""]? Because Kubernetes API endpoints are organized into groups. The most fundamental ones—like pods, services, nodes (though you can’t Role for nodes, more on that later)—live in the core group, which is designated by an empty string. It’s a bit of syntactic oddity you just have to accept. For newer stuff like Deployments (in the apps group), you’d use apiGroups: ["apps"].
ClusterRole: The Master Key
Now, meet its bigger, scarier sibling: ClusterRole. This is cluster-scoped. It applies to every namespace and to cluster-scoped resources themselves (like Nodes, PersistentVolumes, or the cluster-wide Namespace resource). You use a ClusterRole for two main jobs:
- Governing cluster-scoped resources: You can’t grant access to a
Nodewith a regularRolebecause aNodeisn’t in a namespace. You must use aClusterRole. - Defining reusable permission sets: You can define a common set of permissions (e.g., “pod-reader”) once as a
ClusterRoleand then use aRoleBindingto grant it within a specific namespace. This is way better than copy-pasting the sameRoledefinition across 20 namespaces.
Here’s a ClusterRole that gives someone the ability to see everything. A terrifyingly powerful concept, used here for good (hopefully).
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# Notice the lack of a 'namespace' field. That's the whole point. It's free-range.
name: super-secret-global-reader
rules:
- apiGroups: ["*"] # The asterisk means "all API groups". Of course.
resources: ["*"] # The asterisk means "all resources". Obviously.
verbs: ["get", "list", "watch"] # The least dangerous verbs, but on the most dangerous scale.
The Verbs That Matter
You can’t just say “I want to access pods.” You have to say what you want to do to them. The common verbs are mostly self-explanatory: get, list, watch, create, update, patch, delete. But here are the sneaky ones:
deletecollection: This is exactly as dangerous as it sounds. It allows mass deletion. Grant this with extreme prejudice.use: This is a special verb used only forPodSecurityPolicy(deprecated) andPodSecurityStandardresources. It’s an oddball.escalateandbind: These are for RBAC itself. You almost never grant these to anyone who isn’t a cluster admin. Giving a userbindon a powerfulClusterRoleis like giving them a blank check with the cluster’s signature.
The Weird Bits and Best Practices
Let’s get into the nitty-gritty that usually bites you at 2 AM.
apiGroupsandresourcesare lists for a reason. You can define multiple rules in one block. This is valid and keeps your YAML cleaner:rules: - apiGroups: [""] resources: ["pods", "services", "configmaps"] verbs: ["get", "list"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list"]- ResourceNames: You can lock a rule down to a specific instance of a resource. This is incredibly powerful for precision security but a nightmare to manage. Use it sparingly.
rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-super-secret-config"] # Only THIS configmap. verbs: ["get"] # And you can only look at it, not list all of them. - Non-Resource URLs: This is where
ClusterRolegets esoteric. You can grant access to non-resource endpoints like the healthz API or even the general/apiand/apisendpoints. This is primarily for system-level components and not something you’ll likely touch.rules: - nonResourceURLs: ["/healthz", "/api", "/api/*"] verbs: ["get"]
The golden rule: Start with a Role. Only reach for a ClusterRole when you have a proven, specific need for cluster-scoped permissions. Your default posture should be namespace isolation. A ClusterRole is a powerful tool, and like all powerful tools, it’s easiest to hurt yourself with it.