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 本身就是 Kubernetes 的一个 API 对象,name
顾名思义,即是定义一个 Role 对象时为它命的名。
当然考虑到 namespace
为 Kubernetes 的资源对象提供了逻辑上的隔离空间,所以还需要指定该 Role 生效的 namespace
.
rule
字段就是权限定义的核心了,通过 apiGroups
与 resources
字段描述一个资源对象,并在 verbs
中规定针对该对象所能进行的操作。
实例 example-role 如下:
1 | kind: Role |
这段 yaml 文件定义了一个 Role,可以对 default
命名空间中的 Pod 进行 get
、watch
、list
的操作。
Subject 可以理解为我们要授权的对象,对这个对象的描述方式可以很灵活,kind
包括 Group
、 User
、ServiceAccount
.
你可以通过下述命令了解他们的信息:
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 | apiVersion: v1 |
在定义 Pod 时我们可以声明使用 ServiceAccount ,Pod 即具备该 ServiceAccount 所有权限:
1 | apiVersion: v1 |
为什么我平常都没有写这段?
如果一个 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 | kind: RoleBinding |
这段文件中,我们终于将上面列举的 example-role 和 cheese-sa 进行了关联。
如图所示,RoleBinding 对象在 Role 与 Subject 中建立了一个关联,使得 Subject 中定义的 User
、ServiceAccount
、Group
具备了 Role 中所定义的权限。
为什么要这么做?
Role 为资源对象的操作权限提供了统一的管理,subject 对权限的配置也就转化成了对 Role 的绑定,在获取相关权限时,只需要通过名称或标签之类更友好的方式进行授权,这也是“解耦”带来的价值。
Role 作为一个“角色”,只有在有人扮演这个“角色”时,才会发挥作用。就像一个“角色”可以由不同的“演员”来扮演,同时一个“演员”也可以扮演不同的“角色”,这也是 Role 与 Subject 之间的关系。
Reference
“基于角色的权限控制”,《深入剖析 Kubernetes》 ,张磊
Kubernetes 官方文档,https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles