kubernetes RBAC 入门
tags: 对象
文章目录
1. 简介
2. API 对象
2.1 角色(Role)
2.2 集群角色(ClusterRole)
2.3 角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding)
3. 对资源的引用
4. 聚合的 ClusterRole
5. Role 示例
6. 对主体的引用
7. RoleBinding 示例
8. 默认 Roles 和 Role Bindings
9. 面向用户的角色
10. 核心组件角色
11. 其他组件角色
12. 内置控制器的角色
13. 对角色绑定创建或更新的限制
14. 命令行工具
14.1 kubectl create role
14.2 kubectl create clusterrole
14.3 kubectl create rolebinding
14.4 kubectl create clusterrolebinding
14.5 kubectl auth reconcile
15. 服务账号权限
16. 宽松的 RBAC 权限
17. 示例
容器网络接口(CNI)weavework
1. 简介
RBAC(Role-Based Access Control,基于角色的访问控制)在Kubernetes的1.5版本中引入,在1.6版本时升级为Beta版本,在1.8版本时升级为GA。作为kubeadm安装方式的默认选项,足见其重要程度。相对于其他访问控制方式,新的RBAC具有如下优势。
◎ 对集群中的资源和非资源权限均有完整的覆盖。
◎ 整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作。
◎ 可以在运行时进行调整,无须重新启动API Server。要使用RBAC授权模式,需要在API Server的启动参数中加上--authorization-mode=RBAC。
kube-apiserver --authorization-mode=Example,RBAC --<其他选项> --<其他选项>
下面对RBAC的原理和用法进行说明。
2. API 对象
2. API 对象
RBAC API 声明了四种 Kubernetes 对象:Role、ClusterRole、RoleBinding 和 ClusterRoleBinding。你可以像使用其他 Kubernetes 对象一样, 通过类似 kubectl 这类工具 描述对象, 或修补对象。
2.1 角色(Role)
一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则。在一个命名空间中,可以用角色来定义一个角色,如果是集群级别的,就需要使用ClusterRole了。角色只能对命名空间内的资源进行授权,在下面例子中定义的角色具备读取Pod的权限:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-reader rules: - apiGroups: [""] # "" 标明 core API 组 resources: ["pods"] verbs: ["get", "watch", "list"]
rules中的参数说明如下。
◎ apiGroups:支持的API组列表,例如“apiVersion:batch/v1”“apiVersion: extensions:v1beta1”“apiVersion: apps/v1beta1”等,
详细的API组说明参见第9章的说明。
◎ resources:支持的资源对象列表,例如pods、deployments、
jobs等。
◎ verbs:对资源对象的操作方法列表,例如get、watch、list、delete、replace、patch等,详细的操作方法说明参见第9章的说明。
2.2 集群角色(ClusterRole)
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围,还可以用于以下特殊元素的授权。
◎ 集群范围的资源,例如Node。
◎ 非资源型的路径,例如“/healthz”。
◎ 包含全部命名空间的资源,例如pods(用于kubectl get pods –
all-namespaces这样的操作授权)。
下面的集群角色可以让用户有权访问任意一个或所有命名空间的secrets(视其绑定方式而定):
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: # "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制 name: secret-reader rules: - apiGroups: [""] # 在 HTTP 层面,用来访问 Secret 对象的资源的名称为 "secrets" resources: ["secrets"] verbs: ["get", "watch", "list"]
2.3 角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding)
角色绑定或集群角色绑定用来把一个角色绑定到一个目标上,绑定目标可以是User(用户)、Group(组)或者Service Account。使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。
RoleBinding可以引用Role进行授权。下面的例子中的RoleBinding将在default命名空间中把pod-reader角色授予用户jane,这一操作可以让jane读取default命名空间中的Pod:
apiVersion: rbac.authorization.k8s.io/v1 # 此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pods kind: RoleBinding metadata: name: read-pods namespace: default subjects: # 你可以指定不止一个“subject(主体)” - kind: User name: jane # "name" 是不区分大小写的 apiGroup: rbac.authorization.k8s.io roleRef: # "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系 kind: Role # 此字段必须是 Role 或 ClusterRole name: pod-reader # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配 apiGroup: rbac.authorization.k8s.io
RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。一种常见的做法是集群管理员为集群范围预先定义好一组ClusterRole,然后在多个命名空间中重复使用这些ClusterRole。例如,在下面的例子中,虽然secret-reader是一个集群角色,但是因为使用了RoleBinding,所以dave只能读取development命名空间中的secret:
apiVersion: rbac.authorization.k8s.io/v1 # 此角色绑定使得用户 "dave" 能够读取 "default" 名字空间中的 Secrets # 你需要一个名为 "secret-reader" 的 ClusterRole kind: RoleBinding metadata: name: read-secrets # RoleBinding 的名字空间决定了访问权限的授予范围。 # 这里仅授权在 "development" 名字空间内的访问权限。 namespace: development subjects: - kind: User name: dave # 'name' 是不区分大小写的 apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
集群角色绑定中的角色只能是集群角色,用于进行集群级别或者对所有命名空间都生效的授权。下面的例子允许manager组的用户读取任意Namespace中的secret:
apiVersion: rbac.authorization.k8s.io/v1 # 此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 secrets kind: ClusterRoleBinding metadata: name: read-secrets-global subjects: - kind: Group name: manager # 'name' 是不区分大小写的 apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
创建了绑定之后,你不能再修改绑定对象所引用的 Role 或 ClusterRole。 试图改变绑定对象的 roleRef 将导致合法性检查错误。 如果你想要改变现有绑定对象中 roleRef 字段的内容,必须删除重新创建绑定对象。
这种限制有两个主要原因:
针对不同角色的绑定是完全不一样的绑定。要求通过删除/重建绑定来更改 roleRef,
这样可以确保要赋予绑定的所有主体会被授予新的角色(而不是在允许修改 roleRef的情况下导致所有现有主体胃镜验证即被授予新角色对应的权限)。
将 roleRef 设置为不可以改变,这使得可以为用户授予对现有绑定对象的 update 权限,这样可以让他们管理主体列表,同时不能更改被授予这些主体的角色。
命令 kubectl auth reconcile 可以创建或者更新包含 RBAC 对象的清单文件, 并且在必要的情况下删除和重新创建绑定对象,以改变所引用的角色。 更多相关信息请参照命令用法和示例
3. 对资源的引用
多数资源可以用其名称的字符串来表达,也就是Endpoint中的URL相对路径,例如pods。然而,某些Kubernetes API包含下级资源,例如Pod的日志(logs)。Pod日志的Endpoint是GET/api/v1/namespaces/{namespace}/pods/{name}/log。
在这个例子中,Pod是一个命名空间内的资源,log就是一个下级资源。要在一个RBAC角色中体现,就需要用斜线“/”来分隔资源和下级资源。若想授权让某个主体同时能够读取Pod和Pod log,则可以配置resources为一个数组:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-and-pod-logs-reader rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list"]
对于某些请求,也可以通过 resourceNames 列表按名称引用资源。 在指定时,可以将请求限定为资源的单个实例。 下面的例子中限制可以 “get” 和 “update” 一个名为 my-configmap 的 ConfigMap:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: configmap-updater rules: - apiGroups: [""] # 在 HTTP 层面,用来访问 ConfigMap 的资源的名称为 "configmaps" resources: ["configmaps"] resourceNames: ["my-configmap"] verbs: ["update", "get"]
可想而知,resourceName这种用法对list、watch、create或deletecollection操作是无效的,这是因为必须要通过URL进行鉴权,而资源名称在list、watch、create deletecollection请求中只是请求Body数据的一部分。
4. 聚合的 ClusterRole
你可以将若干 ClusterRole 聚合(Aggregate) 起来,形成一个复合的 ClusterRole。 某个控制器作为集群控制面的一部分会监视带有 aggregationRule 的 ClusterRole 对象集合。aggregationRule 为控制器定义一个标签 选择算符供后者匹配 应该组合到当前 ClusterRole 的 roles 字段中的 ClusterRole 对象。
下面是一个聚合 ClusterRole 的示例:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: monitoring aggregationRule: clusterRoleSelectors: - matchLabels: rbac.example.com/aggregate-to-monitoring: "true" rules: [] # 控制面自动填充这里的规则
如果你创建一个与某现有聚合 ClusterRole 的标签选择算符匹配的 ClusterRole, 这一变化会触发新的规则被添加到聚合 ClusterRole 的操作。 下面的例子中,通过创建一个标签同样为 rbac.example.com/aggregate-to-monitoring: true 的 ClusterRole,新的规则可被添加到 “monitoring” ClusterRole 中。
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: monitoring-endpoints labels: rbac.example.com/aggregate-to-monitoring: "true" # 当你创建 "monitoring-endpoints" ClusterRole 时, # 下面的规则会被添加到 "monitoring" ClusterRole 中 rules: - apiGroups: [""] resources: ["services", "endpoints", "pods"] verbs: ["get", "list", "watch"]
默认的面向用户的角色 使用 ClusterRole 聚合。 这使得作为集群管理员的你可以为扩展默认规则,包括为定制资源设置规则, 比如通过 CustomResourceDefinitions 或聚合 API 服务器提供的定制资源。
例如,下面的 ClusterRoles 让默认角色 “admin” 和 “edit” 拥有管理自定义资源 “CronTabs” 的权限, “view” 角色对 CronTab 资源拥有读操作权限。 你可以假定 CronTab 对象在 API 服务器所看到的 URL 中被命名为 “crontabs”。
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: aggregate-cron-tabs-edit labels: # 添加以下权限到默认角色 "admin" 和 "edit" 中 rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rules: - apiGroups: ["stable.example.com"] resources: ["crontabs"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: aggregate-cron-tabs-view labels: # 添加以下权限到 "view" 默认角色中 rbac.authorization.k8s.io/aggregate-to-view: "true" rules: - apiGroups: ["stable.example.com"] resources: ["crontabs"] verbs: ["get", "list", "watch"]
5. Role 示例
以下示例均为从 Role 或 CLusterRole 对象中截取出来,我们仅展示其 rules 部分。
允许读取在核心 API 组下的 “Pods”:
rules: - apiGroups: [""] # 在 HTTP 层面,用来访问 Pod 的资源的名称为 "pods" resources: ["pods"] verbs: ["get", "list", "watch"]
允许读/写在 “extensions” 和 “apps” API 组中的 Deployment(在 HTTP 层面,对应 URL 中资源部分为 “deployments”):
rules: - apiGroups: ["extensions", "apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
允许读取核心 API 组中的 “pods” 和读/写 “batch” 或 “extensions” API 组中的 “jobs”:
rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] - apiGroups: ["batch", "extensions"] resources: ["jobs"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
允许读取名称为 “my-config” 的 ConfigMap(需要通过 RoleBinding 绑定以 限制为某名字空间中特定的 ConfigMap):
rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-config"] verbs: ["get"]
允许读取在核心组中的 “nodes” 资源(因为 Node 是集群作用域的,所以需要 ClusterRole 绑定到 ClusterRoleBinding 才生效):
rules: - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"]
允许针对非资源端点 /healthz
和其子路径上发起 GET 和 POST 请求 (必须在 ClusterRole 绑定 ClusterRoleBinding 才生效):
rules: - nonResourceURLs: ["/healthz", "/healthz/*"] # nonResourceURL 中的 '*' 是一个全局通配符 verbs: ["get", "post"]
6. 对主体的引用
RoleBinding 或者 ClusterRoleBinding 可绑定角色到某 *主体(Subject)*上。 主体可以是组,用户或者 服务账号。
Kubernetes 用字符串来表示用户名。 用户名可以是普通的用户名,像 “alice”;或者是邮件风格的名称,如 “bob@example.com”, 或者是以字符串形式表达的数字 ID。 你作为 Kubernetes 管理员负责配置 身份认证模块 以便后者能够生成你所期望的格式的用户名。
注意: 前缀 system: 是 Kubernetes 系统保留的,所以你要确保 所配置的用户名或者组名不能出现上述 system: 前缀。
除了对前缀的限制之外,RBAC 鉴权系统不对用户名格式作任何要求。