When I was doing PaaS platform development, I was involved in tenant privilege management, and considering that Kubernetes provides RBAC (role-based access control) mechanism by default, I thought how to make good use of RBAC of Kubernetes to achieve it. However, when I started to learn this knowledge, I encountered some problems, such as Role and ClusterRole, Role Binding and ClusterRoleBinding, and many concepts are rather vague.

As we learn more about them and practice, we can sort out the relationship between them. This article is to share what we have learned during this period.

What is RBAC?

RBAC (Role-Based Access Control)

RBAC, Role-Based Access Control, or Role-Based Access Control, is achieved by customizing a Role with certain specific Permissions and then associating the Role with a specific Subject (user, group, serviceaccounts…) The purpose of access control is achieved by customizing a Role with certain Permissions and then associating the Role with a specific Subject (user, group, serviceaccounts…).

There are three important concepts in RBAC.

  • Role: Role, which is essentially a collection of a set of rule permissions. Note: In RBAC, a Role only declares grant permissions, not negative rules.
  • Subject: the acted upon, including user, group, which in layman’s terms is the user identified in the authentication mechanism.
  • RoleBinding: defines the binding relationship between “Role” and “Subject”, that is, the user and the operation privileges are bound.

RBAC actually binds the subject to the role by creating a role through RoleBinding. The following diagram shows several types of binding relationships in RBAC.

several types of binding relationships in RBAC

Kubernetes RBAC

Now let’s take a fresh look at the RBAC implementation from a Kubernetes perspective.

The whole process of RBAC role creation and role binding in Kubernetes is relatively clear, and the RBAC configuration is presented to the administrator in the form of a resource configuration, so we only need to define some configuration files. First, let’s look at the RBAC configuration relationship diagram in Kubernetes.

Kubernetes RBAC

As you can see in the figure, the process of implementing a custom RBAC for Kubernetes involves several concepts that were actually mentioned at the beginning, but which are defined more specifically in Kubernetes, and which are the focus of attention.

Subject

Subjects in kubernetes include User, Group, and Service Account, the first two are well understood, Service Account is actually the difference between User Account, resources in Kubernetes can also be treated as a Subject, such as a Pod For example, when a Pod needs to operate cluster resources, it uses a Service Account.

Kubernetes does not implement direct management of User Accounts, and requires administrators to create User Accounts manually.

Role

A role is essentially a collection of rule permissions that are bound to a specific Subject, thus giving the Subject a corresponding set of permissions.

In Kubernetes, Roles are divided into two categories.

  • Role: Role, which can be understood as a Namespace Role. A Role is defined by specifying the Namespace, that is, the Role is defined inside the Namespace, so the set of rule permissions it defines is also for the resources under the Namespace where it is defined.
  • As the name implies, this type of Role is defined under the entire Cluster, and there is no need to specify a specific Namespace when defining a Cluster Role.

Role Example.

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: ns-a  # 定义于 namespace 下
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole Example.

1
2
3
4
5
6
7
8
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

Note: ClusterRole does not mean that the scope of permission control is the entire Cluster, but also has a relationship with the type of Binding to be discussed later, where ClusterRole should be understood as a global quantity that can be applied under a Namespace (to play the role of reuse) and can be applied under the scope of the Cluster.

The key step in the definition of each Role is to specify the rules that the Role has, and the permission rules in Kubernetes need to be specified as follows.

  • apiGroups: resource groups, "" defaults to core group resources, others such as apps, etc.
  • resources: resources, such as pods, deployments, services, secrets, etc.
  • verbs: action verbs, such as get, list, watch, create, delete, update, etc.

Binding

Binding, conceptually well understood, is the binding of a Role with defined rule permissions to a specified Subject, thus giving the Subject a set of permissions.

Binding in kubernetes is divided into two types.

  • RoleBinding: Binding a Role/ClusterRole to a Subject, which takes effect on a specific Namespace scope resource.
  • ClusterRoleBinding: Binding a ClusterRole to a Subject, which takes effect on the Cluster scope resource.

Again.

The scope of permission control (Namespace/Cluster) in Kubernetes is determined by the type of Binding, not by Role and ClusterRole, which is important to remember.

Analysis of RBAC schemes acting on Namespace scope

Method 1: Combination of Role + RoleBinding

Combination of Role + RoleBinding

As you can see above, this approach is more intuitive, because as I said before, a Role in Kubernetes should be understood as a Namespace Role, which is defined under the Namespace, so if you want to implement binding between Subjects and Roles in the Namespace scope, it’s just a matter of configuring a RoleBinding.

Configuration example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pods-reader-binding
  namespace: ns-a
subjects:
- kind: User
  name: yingchi
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Combination of ClusterRole + RoleBinding (recommended)

Once you hear ClusterRole, many people will subconsciously think that it is about cluster-wide permission control, but in fact, the scope of permission control is not directly related to the type of Role, ClusterRole, which is essentially a role defined globally, can act under Namespace, can be reused by multiple Namespaces, and can also Cluster.

We now need to implement the binding of Subject & Role in the scope of Namespace, that is, to control the scope of authority of ClusterRole at the level of Namespace, so use RoleBinding to bind Subject to ClusterRole can be achieved.

Configuration example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pods-reader-binding
  namespace: ns-a
subjects:
- kind: User
  name: yingchi
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

method analysis

Why do you recommend using the combination of ClusterRole + RoleBinding?

Let’s think about a problem. If a PodReader Role is designed to have the permission to get/list/watch the Pods under the current Namespace, how should it be designed if both namespaces need such a Role?

Using the first approach described above, each namespace would need to define a PodReader Role.

combination of ClusterRole + RoleBinding

There is an obvious drawback to this: the rules permissions of PodReader are actually the same under each Namespace, but due to the limitations of Role, it must be defined separately under each Namespace, which is a waste of resources and an inelegant process, so how can we reuse PodReader as a Role? So, there is the second method.

reuse PodReader as a Role

As shown in the figure, that is, the PodReader is defined as a ClusterRole, and then different Subjects are bound to the same ClusterRole under different Namespaces through RoleBinding.

Summary

If a custom Role is used in many Namespaces, then it is recommended to use the combination of ClusterRole + RoleBinding to achieve the reuse of the Role, if a Namespace really has to define a separate private Role, then use the combination of Role + RoleBinding, but If a Namespace has to define a separate private Role, then use the combination of Role + RoleBinding, but then the Role will be more limited.

Analysis of cluster-wide RBAC scenarios

There is only one solution, which is via ClusterRoleBinding + ClusterRole.

ClusterRoleBinding + ClusterRole

Note where I drew ClusterRoleBinding in the diagram. When I introduced the concept of Binding earlier, I mentioned that the scope of permission control (Namespace/Cluster) in Kubernetes is determined by the type of Binding, not by Role and ClusterRole** . If you want to implement cluster-wide RBAC, you must use ClusterRoleBinding, and note that when you bind by ClusterRoleBinding, you are only allowed to bind to the ClusterRole role, which can be simply interpreted as a global method that can only use the global amount of ClusterRole.

Example configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: cluster-admin-biding
subjects:
- kind: User
  name: yingchi
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

Summary

To learn about the Kubernetes RBAC mechanism, we must first start with the basic RBAC concept and understand the essence of the RBAC permission management mechanism, i.e., the relationship between subject-role-permission, and on this basis, learn the implementation of RBAC for Kubernetes. Then, we will understand the difference between RoleBinding and ClusterRoleBinding, remembering that the scope of permission control in Kubernetes RBAC is not determined by Role, but by the type of Remember that the scope of permission control in Kubernetes RBAC is not determined by the Role, but by the type of Binding.