权限管理RBAC

RBAC(Role-Based Access Contrd,基于角色的访问控制)使用 rbac.authorization.k8s.io API组来推动授权决策,允许管理员通过Kubernetes API动态配置策略。

RBAC API声明了4种Kubernetes对象:RoleClusterRoleRoleBindingClusterRoleBinding,可以像使用其他API资源一样使用kubectl API调用这些资源对象。例如通过文件创建一个RBAC:kubectl create –f (resource).yml

Role和ClusterRole

RBAC 的 Role ClusterRole 包含一组代表相关权限的规则。这些权限是纯粹累加的(不存在拒绝某操作的规则)。

  • Role 总是用来在某个命名空间内设置访问权限;在创建 Role 时,必须指定该 Role 所属的名字空间

  • 与之相对,ClusterRole是一个集群作用域的资源

    ClusterRole 有若干用法:

    • 定义对某命名空间域对象的访问权限,并将在个别命名空间内被授予访问权限;

    • 为命名空间作用域的对象设置访问权限,并被授予跨所有命名空间的访问权限;

    • 为集群作用域的资源定义访问权限。

如果你希望在命名空间内定义角色,应该使用 Role; 如果你希望定义集群范围的角色,应该使用 ClusterRole。

提示:

这两种资源的名字不同(Role 和 ClusterRole) 是因为 Kubernetes 对象要么是命名空间作用域的,要么是集群作用域的,不可两者兼具。

Role 示例

下面是一个位于 "default" 名字空间的 Role 的示例,可用来授予对 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"]

ClusterRole 示例

ClusterRole 同样可以用于授予 Role 能够授予的权限。 因为 ClusterRole 属于集群范围,所以它也可以为以下资源授予访问权限:

  • 集群范围资源(比如节点(Node))

  • 非资源端点(比如 /healthz)

  • 跨命名空间访问的命名空间作用域的资源(如 Pod)

    比如,你可以使用 ClusterRole 来允许某特定用户执行 kubectl get pods --all-namespaces

下面是一个 ClusterRole 的示例,可用来为任一特定命名空间中的 Secret 授予读访问权限, 或者跨命名空间的访问权限(取决于该角色是如何绑定的):

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"]

RoleBinding 和 ClusterRoleBinding

角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。

  • 它包含若干主体(Subject)(用户、组或服务账户)的列表和对这些主体所获得的角色的引用。

  • RoleBinding 在指定的命名空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权

  • 一个 RoleBinding 可以引用同一的命名空间中的任何 Role。或者,一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的命名空间

如果你希望将某 ClusterRole 绑定到集群中所有命名空间,你要使用 ClusterRoleBinding。

RoleBinding 示例

下面的例子中的 RoleBinding 将 "pod-reader" Role 授予在 "default" 命名空间中的用户 "jane"。 这样,用户 "jane" 就具有了读取 "default" 命名空间中所有 Pod 的权限。

apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "jane" 读取 "default" 命名空间中的 Pod
# 你需要在该命名空间中有一个名为 “pod-reader” 的 Role
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 中定义的访问权限授予 RoleBinding 所在命名空间的资源。这种引用使得你可以跨整个集群定义一组通用的角色, 之后在多个命名空间中复用。

例如,尽管下面的 RoleBinding 引用的是一个 ClusterRole"dave"(这里的主体, 区分大小写)只能访问 "development" 命名空间中的 Secret 对象,因为 RoleBinding 所在的命名空间(由其 metadata 决定)是 "development"

apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定使得用户 "dave" 能够读取 "development" 命名空间中的 Secret
# 你需要一个名为 "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

ClusterRoleBinding 示例

要跨整个集群完成访问权限的授予,你可以使用一个 ClusterRoleBinding下面的 ClusterRoleBinding 允许 "manager" 组内的所有用户访问任何命名空间中的 Secret。

apiVersion: rbac.authorization.k8s.io/v1
# 此集群角色绑定允许 “manager” 组中的任何人访问任何命名空间中的 Secret 资源
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

对资源的引用

在 Kubernetes API 中,大多数资源都是使用对象名称的字符串表示来呈现与访问的。 例如,对于 Pod 应使用 "pods"。 RBAC 使用对应 API 端点的 URL 中呈现的名字来引用资源。 有一些 Kubernetes API 涉及子资源(subresource),例如 Pod 的日志。 对 Pod 日志的请求看起来像这样:

GET /api/v1/namespaces/{namespace}/pods/{name}/log

在这里,pods 对应命名空间作用域的 Pod 资源,而 log 是 pods 的子资源。 在 RBAC 中表达子资源时,使用斜线(/)来分隔资源和子资源。 要允许某主体读取 pods 同时访问这些 Pod 的 log 子资源,你可以这样写:

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"]

说明:

不能使用资源名字来限制 create 或者 deletecollection 请求。对于 create 请求而言,这是因为在鉴权时可能还不知道新对象的名字。

可以使用通配符 * 批量引用所有的 resources、apiGroups 和 verbs 对象,无需逐一引用。

对于 nonResourceURLs,你可以将通配符 * 作为后缀实现全局通配。

对于 resourceNames,空集表示没有任何限制。

下面的示例对 example.com API 组中所有当前和未来资源执行所有动作。 这类似于内置的 cluster-admin。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: example.com-superuser # 此角色仅作示范,请勿使用
rules:
- apiGroups: ["example.com"]
  resources: ["*"]
  verbs: ["*"]

注意:

在 resources 和 verbs 条目中使用通配符会为敏感资源授予过多的访问权限。例如,如果添加了新的资源类型、新的子资源或新的自定义动词, 通配符条目会自动授予访问权限,用户可能不希望出现这种情况。

应该执行最小特权原则, 使用具体的 resources 和 verbs 确保仅赋予工作负载正常运行所需的权限。

聚合的 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", "endpointslices", "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"]

对主体的引用

RoleBinding 或者 ClusterRoleBinding 可绑定角色到某主体(Subject)上。 主体可以是组,用户或者服务账户。

Kubernetes 用字符串来表示用户名

  • 用户名可以是普通的用户名,像 "alice";

  • 或者是邮件风格的名称,如 "bob@example.com";

  • 或者是以字符串形式表达的数字 ID。

Kubernetes 管理员负责配置身份认证模块, 以便后者能够生成你所期望的格式的用户名。

注意:

前缀 system: 是 Kubernetes 系统保留的,所以你要确保所配置的用户名或者组名不能出现上述 system: 前缀。

除了对前缀的限制之外,RBAC 鉴权系统不对用户名格式作任何要求。

在 Kubernetes 中,身份认证(Authenticator)模块提供用户组信息。与用户名一样,用户组名也用字符串来表示,而且对该字符串没有格式要求, 只是不能使用保留的前缀 system:。

服务账户(ServiceAccount) 的用户名前缀为 system:serviceaccount:,属于前缀为 system:serviceaccounts: 的用户组。

  • system:serviceaccount: (单数)是用于服务账户用户名的前缀;

  • system:serviceaccounts: (复数)是用于服务账户组名的前缀。

RoleBinding 示例

下面示例是 RoleBinding 中的片段,仅展示其 subjects 的部分。

对于名称为 alice@example.com 的用户:

subjects:
- kind: User
  name: "alice@example.com"
  apiGroup: rbac.authorization.k8s.io

对于名称为 frontend-admins 的用户组:

subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io

对于 kube-system 名字空间中的默认服务账户:

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

对于 "qa" 名称空间中的所有服务账户:

subjects:
- kind: Group
  name: system:serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io

对于在任何名字空间中的服务账户:

subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

对于所有已经过身份认证的用户:

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io

对于所有未通过身份认证的用户:

subjects:
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

对于所有用户:

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

最后更新于