Kubernetes RABC 权限控制

API Server 作为 Kubernetes 的核心组件,接收包括用户和集群内部资源对象发来的请求,在处理这些请求之前,API Server 会通过凭证来认证请求是否有相应的权限。

早期版本的 Kubernetes 中,集群内以 token 作为身份认证的手段,这也意味着,如果以某种方式获取了这个 token 之后,就可以在 Kubernetes 中运行任意的 pod.

针对权限管理这个问题,Kubernetes 提出了插件形式的授权方法,包括基于角色的权限控制 ( RBAC , Role-Based Access Control ) 、基于属性的权限控制 ( ABAC , Attribute-Based Access Control )、 WebHook 插件以及自定义插件。

RBAC 作为 Kubernetes 的 GA (通用可用性) 级别的资源对象,在集群中是默认开启的,本文将介绍 RBAC 在 Kubernetes 中的利用。

RBAC 模式

我们在许多地方都可以看到权限管理的影子,路由协议中的 ACL (控制访问列表) ,Linux 中的 Capability ,还有这里要介绍的 Kubernetes 中的 RBAC 。

RBAC 一个很重要的思想就是将对象的权限与需要授权的对象进行解耦,这显然是符合 Kubernetes 设计思想的。

关于 RBAC 在 Kubernetes 中的使用,你可以直接去看官方文档。以下的内容可以一定程度上帮助你更好地理解官方文档中的内容。


Role & Subject

为了将 “API 对象的使用权限” 与 “API 对象的使用者” 进行接耦,Kubernetes RBAC 抽象出这样两个概念:

  • Role : 即角色,用来描述对 Kubernetes API Objects 的操作权限 ;
  • Subject : 待授权的对象。

为了便于理解,我用下面这张图来描述这两个概念的一些属性。

Role&Subject

Role 本身就是 Kubernetes 的一个 API 对象,name 顾名思义,即是定义一个 Role 对象时为它命的名。

当然考虑到 namespace 为 Kubernetes 的资源对象提供了逻辑上的隔离空间,所以还需要指定该 Role 生效的 namespace .

rule 字段就是权限定义的核心了,通过 apiGroupsresources 字段描述一个资源对象,并在 verbs 中规定针对该对象所能进行的操作。

实例 example-role 如下:

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: example-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]

这段 yaml 文件定义了一个 Role,可以对 default 命名空间中的 Pod 进行 getwatchlist 的操作。


Subject 可以理解为我们要授权的对象,对这个对象的描述方式可以很灵活,kind 包括 GroupUserServiceAccount .

你可以通过下述命令了解他们的信息:

1
$ kubectl explain RoleBinding.subjects.kind

这里出现了一个资源对象 RoleBinding ,你可能从名称上就对它的作用有了一些猜想,不过不要急,首先还是需要了解下 subject 该如何定义。


User

Kubernetes 中的 User 只是授权系统中的概念,可以由外部的认证服务 (如 Keystone) 提供,或是在 API Server 中通过用户/密码文件指定。

这里顺便提下 User-facing roles ,包括 Kubernetes 的超级用户 cluster-admin 在内的几个角色 :

Default ClusterRole Default ClusterRoleBinding Description
cluster-admin system:masters 通过 ClusterRoleBinding 进行绑定,该用户拥有对集群内所有资源对象的操作权限,可以执行任意动作。
admin None 通过 RoleBinding 进行绑定,该用户允许对 namespace 内大部分资源对象进行读写操作
edit None 允许对 namespace 内大部分对象读写,无法查看或修改 role/role binding 资源,但可以访问 Secrete 或将 ServiceAccount 与 Pod 进行绑定。
view None 对 namespace 中大部分资源对象拥有只读权限。无法查看 Secrets .

ClusterRole 的作用范围包括整个集群,所有的 namespaces .

Role 的作用范围仅限于 namespace 内,因此需要在定义中加上 namespace: 字段。

因此,对于一些 “Non-namespaced 对象” (如 Node) 或对 “集群全局的资源” 进行统一配置的时候,我们就需要用到 ClusterRole .


ServiceAccount

当然在大多数情况下,用到的还是 Kubernetes 的 “内置用户” —— ServiceAccount。

ServiceAccount 本身就是一个资源对象,可以定义一个最简单的 ServiceAccount .

cheese-sa:

1
2
3
4
5
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: cheese
name: cheese-sa

在定义 Pod 时我们可以声明使用 ServiceAccount ,Pod 即具备该 ServiceAccount 所有权限:

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Pod
metadata:
namespace: cheese
name: sa-token-test
spec:
containers:
- name: nginx
image: nginx:1.7.9
serviceAccountName: cheese-sa

为什么我平常都没有写这段?

如果一个 Pod 没有声明 serviceAccount: Name,Kubernetes 会自动在它的 namespace 下创建一个名叫 default 的默认 ServiceAccount,然后分配给这个 Pod。


Group

用户组,与 User 相同,如果配置了外部认证服务的话,“用于组”也会由外部认证服务提供。

而在 Kubernetes 的语境下,我们只需要了解:

kind name Description
Group system:serviceaccounts 所有 namespace 中的所有 ServiceAccounts
Group system:serviceaccounts:kube-system kube-system 命名空间下所有的 ServiceAccounts
User system:serviceaccount:cheese:default cheese 命名空间下的默认 ServiceAccount

从上述的表达方式 (主要是 name) 中,大致可以体会到 ServiceAccount 与 User/Group 的对应关系,由此可以自己定义一些字段来描述特定的对象。


RoleBinding

上面 ServiceAccount 的部分,我们举了个简单的声明 ServiceAccount 的例子,但这个 ServiceAccount 显然还并没有与“权限”产生任何关联。

下面这个文件要做的,就是为这个 ServiceAccount 分配权限:

1
2
3
4
5
6
7
8
9
10
11
12
13
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-rolebinding
namespace: cheese
subjects:
- kind: ServiceAccount
name: cheese-sa
namespace: cheese
roleRef:
kind: Role
name: example-role
apiGroup: rbac.authorization.k8s.io

这段文件中,我们终于将上面列举的 example-rolecheese-sa 进行了关联。

RoleBinding

如图所示,RoleBinding 对象在 Role 与 Subject 中建立了一个关联,使得 Subject 中定义的 UserServiceAccountGroup 具备了 Role 中所定义的权限。


为什么要这么做?

Role 为资源对象的操作权限提供了统一的管理,subject 对权限的配置也就转化成了对 Role 的绑定,在获取相关权限时,只需要通过名称或标签之类更友好的方式进行授权,这也是“解耦”带来的价值。

更灵活的授权方式

Role 作为一个“角色”,只有在有人扮演这个“角色”时,才会发挥作用。就像一个“角色”可以由不同的“演员”来扮演,同时一个“演员”也可以扮演不同的“角色”,这也是 Role 与 Subject 之间的关系。


Reference