使用 RBAC 授权

基于角色的访问控制 (RBAC) 是一种根据组织内各个用户的角色来 regulating 对计算机或网络资源的访问的方法。

RBAC 授权使用 rbac.authorization.k8s.io API 组 来驱动授权决策,允许您通过 Kubernetes API 动态配置策略。

要启用 RBAC,请使用设置为包含 RBAC 授权器的文件的 --authorization-config 标志启动 API 服务器;例如

apiVersion: apiserver.config.k8s.io/v1
kind: AuthorizationConfiguration
authorizers:
  ...
  - type: RBAC
  ...

或者,使用设置为包含 RBAC 的逗号分隔列表的 --authorization-mode 标志启动 API 服务器;例如

kube-apiserver --authorization-mode=...,RBAC --other-options --more-options

API 对象

RBAC API 声明了四种 Kubernetes 对象:角色集群角色角色绑定集群角色绑定。您可以使用 kubectl 等工具来描述或修改 RBAC 对象,就像任何其他 Kubernetes 对象一样。

角色和集群角色

RBAC 角色集群角色 包含代表一组权限的规则。权限是纯附加的(没有“拒绝”规则)。

角色始终在特定 命名空间 内设置权限;创建角色时,您必须指定它所属的命名空间。

相比之下,集群角色是非命名空间资源。这些资源具有不同的名称(角色和集群角色),因为 Kubernetes 对象始终必须是命名空间或非命名空间;它不能两者都是。

集群角色有多种用途。您可以使用集群角色来

  1. 定义命名空间资源的权限,并在单个命名空间内被授予访问权限
  2. 定义命名空间资源的权限,并在所有命名空间中被授予访问权限
  3. 定义集群范围资源的权限

如果要在命名空间内定义角色,请使用角色;如果要在集群范围内定义角色,请使用集群角色。

角色示例

以下是“default”命名空间中的一个角色示例,可用于授予对 Pod 的读取访问权限

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

集群角色示例

集群角色可用于授予与角色相同的权限。由于集群角色是集群范围的,您还可以使用它们来授予对

  • 集群范围资源(如 节点)的访问权限

  • 非资源端点(如 /healthz)的访问权限

  • 所有命名空间中的命名空间资源(如 Pod)的访问权限

    例如:您可以使用集群角色允许特定用户运行 kubectl get pods --all-namespaces

以下是一个集群角色示例,可用于授予对任何特定命名空间或所有命名空间(取决于它如何被绑定)中的 密钥 的读取访问权限

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Secret
  # objects is "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

角色或集群角色对象的名称必须是有效的 路径段名称

角色绑定和集群角色绑定

角色绑定将角色中定义的权限授予一个或一组用户。它包含一个_主体_列表(用户、组或服务帐户),以及对被授予角色的引用。角色绑定在特定命名空间内授予权限,而集群角色绑定在集群范围内授予访问权限。

角色绑定可以引用同一命名空间中的任何角色。或者,角色绑定可以引用集群角色并将该集群角色绑定到角色绑定的命名空间。如果要将集群角色绑定到集群中的所有命名空间,请使用集群角色绑定。

角色绑定或集群角色绑定对象的名称必须是有效的 路径段名称

角色绑定示例

以下是一个角色绑定示例,它将“pod-reader”角色授予“default”命名空间中的用户“jane”。这允许“jane”读取“default”命名空间中的 Pod。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
  name: jane # "name" is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" specifies the binding to a Role / ClusterRole
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

角色绑定还可以引用集群角色,以将该集群角色中定义的权限授予角色绑定命名空间内的资源。这种引用允许您在集群中定义一组通用角色,然后在多个命名空间中重用它们。

例如,即使以下角色绑定引用了集群角色,“dave”(主体,区分大小写)也只能读取“development”命名空间中的密钥,因为角色绑定的命名空间(在其元数据中)是“development”。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
# You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
  name: read-secrets
  #
  # The namespace of the RoleBinding determines where the permissions are granted.
  # This only grants permissions within the "development" namespace.
  namespace: development
subjects:
- kind: User
  name: dave # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

集群角色绑定示例

要授予整个集群的权限,您可以使用集群角色绑定。以下集群角色绑定允许“manager”组中的任何用户读取任何命名空间中的密钥。

apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

创建绑定后,您无法更改它引用的角色或集群角色。如果您尝试更改绑定的 roleRef,您将收到验证错误。如果您确实要更改绑定的 roleRef,则需要删除绑定对象并创建替换对象。

此限制有两个原因

  1. 使 roleRef 不可变允许授予某人对现有绑定对象的 update 权限,以便他们可以管理主体列表,而无需更改授予这些主体的角色。
  2. 对不同角色的绑定是根本不同的绑定。要求删除/重新创建绑定才能更改 roleRef 可确保绑定中的完整主体列表旨在被授予新角色(而不是启用或意外修改 roleRef 而不验证所有现有主体是否应被授予新角色的权限)。

kubectl auth reconcile 命令行实用程序创建或更新包含 RBAC 对象的清单文件,并在需要更改它们引用的角色时处理删除和重新创建绑定对象。有关更多信息,请参阅命令用法和示例

引用资源

在 Kubernetes API 中,大多数资源使用其对象名称的字符串表示形式来表示和访问,例如 Pod 的 pods。RBAC 使用与相关 API 端点的 URL 中出现的名称完全相同的名称来引用资源。一些 Kubernetes API 涉及_子资源_,例如 Pod 的日志。Pod 日志的请求如下所示

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

在这种情况下,pods 是 Pod 资源的命名空间资源,而 logpods 的子资源。要在 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 列表按名称引用某些请求的资源。指定后,请求可以限制为资源的单个实例。以下是一个示例,它将其主体限制为仅 getupdate 名为 my-configmap配置映射

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing ConfigMap
  # objects is "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

您可以使用通配符 * 符号来指代所有 资源apiGroupsverbs,而不是单独引用它们。对于 nonResourceURLs,您可以使用通配符 * 作为后缀通配符匹配。对于 resourceNames,空集表示允许所有内容。以下示例允许访问在 example.com API 组中的所有当前和未来资源上执行任何当前和未来操作。这类似于内置的 cluster-admin 角色。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: example.com-superuser # DO NOT USE THIS ROLE, IT IS JUST AN EXAMPLE
rules:
- apiGroups: ["example.com"]
  resources: ["*"]
  verbs: ["*"]

聚合集群角色

您可以将多个集群角色聚合到一个组合的集群角色中。作为集群控制平面一部分运行的控制器会监视设置了 aggregationRule 的集群角色对象。aggregationRule 定义了一个标签选择器,控制器使用该选择器来匹配应组合到此集群角色的 rules 字段中的其他集群角色对象。

这是一个聚合集群角色的示例

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # The control plane automatically fills in the rules

如果创建与现有聚合集群角色的标签选择器匹配的新集群角色,则该更改将触发将新规则添加到聚合集群角色中。以下示例通过创建另一个标记为 rbac.example.com/aggregate-to-monitoring: true 的集群角色,将规则添加到“monitoring”集群角色中。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-endpoints
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
# When you create the "monitoring-endpoints" ClusterRole,
# the rules below will be added to the "monitoring" ClusterRole.
rules:
- apiGroups: [""]
  resources: ["services", "endpointslices", "pods"]
  verbs: ["get", "list", "watch"]

默认面向用户的角色使用集群角色聚合。这使您作为集群管理员可以包含自定义资源的规则,例如由自定义资源定义或聚合 API 服务器提供的资源,以扩展默认角色。

例如:以下集群角色允许“admin”和“edit”默认角色管理名为 CronTab 的自定义资源,而“view”角色只能对 CronTab 资源执行读取操作。您可以假设 API 服务器看到的 URL 中的 CronTab 对象命名为 "crontabs"

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: aggregate-cron-tabs-edit
  labels:
    # Add these permissions to the "admin" and "edit" default roles.
    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:
    # Add these permissions to the "view" default role.
    rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch"]

角色示例

以下示例摘自角色或集群角色对象,仅显示 rules 部分。

允许读取核心API 组中的 "pods" 资源

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Pod
  # objects is "pods"
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

允许在 "apps" API 组中读取/写入部署(在 HTTP 级别:URL 的资源部分中包含 "deployments" 的对象)

rules:
- apiGroups: ["apps"]
  #
  # at the HTTP level, the name of the resource for accessing Deployment
  # objects is "deployments"
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取核心 API 组中的 Pod,以及读取或写入 "batch" API 组中的 Job 资源

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Pod
  # objects is "pods"
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
  #
  # at the HTTP level, the name of the resource for accessing Job
  # objects is "jobs"
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取名为“my-config”的 ConfigMap(必须与 RoleBinding 绑定以限制为单个命名空间中的单个 ConfigMap)

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing ConfigMap
  # objects is "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]

允许读取核心组中的资源 "nodes"(因为节点是集群范围的,所以这必须在与 ClusterRoleBinding 绑定的 ClusterRole 中才能生效)

rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Node
  # objects is "nodes"
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

允许向非资源端点 /healthz 及其所有子路径发送 GET 和 POST 请求(必须在与 ClusterRoleBinding 绑定的 ClusterRole 中才能生效)

rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # '*' in a nonResourceURL is a suffix glob match
  verbs: ["get", "post"]

引用主体

RoleBinding 或 ClusterRoleBinding 将角色绑定到主体。主体可以是组、用户或服务帐户

Kubernetes 将用户名表示为字符串。这些可以是:普通名称,例如“alice”;电子邮件样式的名称,例如“[email protected]”;或表示为字符串的数字用户 ID。作为集群管理员,您需要配置身份验证模块,以便身份验证以您想要的格式生成用户名。

在 Kubernetes 中,身份验证器模块提供组信息。与用户一样,组也表示为字符串,并且该字符串没有格式要求,只是前缀 system: 是保留的。

服务帐户的名称以 system:serviceaccount: 为前缀,并属于名称以 system:serviceaccounts: 为前缀的组。

角色绑定示例

以下示例是仅显示 subjects 部分的 RoleBinding 摘录。

对于名为 [email protected] 的用户

subjects:
- kind: User
  name: "[email protected]"
  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

默认角色和角色绑定

API 服务器创建一组默认的 ClusterRole 和 ClusterRoleBinding 对象。其中许多都以 system: 为前缀,这表明该资源由集群控制平面直接管理。所有默认的 ClusterRole 和 ClusterRoleBinding 都标有 kubernetes.io/bootstrapping=rbac-defaults

自动协调

在每次启动时,API 服务器都会使用任何缺失的权限更新默认集群角色,并使用任何缺失的主题更新默认集群角色绑定。 这允许集群修复意外的修改,并有助于在 Kubernetes 新版本中权限和主题发生变化时使角色和角色绑定保持最新。

要选择退出此协调,请将默认集群角色或默认集群角色绑定上的 `rbac.authorization.kubernetes.io/autoupdate` 注释设置为 `false`。 请注意,缺少默认权限和主题可能导致集群无法正常工作。

如果 RBAC 授权器处于活动状态,则默认情况下启用自动协调。

API 发现角色

默认集群角色绑定授权未经身份验证和已通过身份验证的用户读取被认为可以公开访问的 API 信息(包括 CustomResourceDefinitions)。 要禁用匿名未经身份验证的访问,请将 `--anonymous-auth=false` 标志添加到 API 服务器配置中。

要通过 `kubectl` 运行查看这些角色的配置

kubectl get clusterroles system:discovery -o yaml
Kubernetes RBAC API 发现角色
默认 ClusterRole默认 ClusterRoleBinding描述
system:basic-usersystem:authenticated允许用户对其自身的基本信息进行只读访问。 在 v1.14 之前,此角色也绑定到system:unauthenticated默认情况下。
system:discoverysystem:authenticated允许对发现和协商 API 级别所需的 API 发现端点进行只读访问。 在 v1.14 之前,此角色也绑定到system:unauthenticated默认情况下。
system:public-info-viewersystem:authenticatedsystem:unauthenticated允许对有关集群的非敏感信息进行只读访问。 在 Kubernetes v1.14 中引入。

面向用户的角色

某些默认 ClusterRole 没有 `system:` 前缀。 这些角色旨在面向用户。 它们包括超级用户角色(`cluster-admin`)、旨在使用 ClusterRoleBinding 在集群范围内授予的角色,以及旨在使用 RoleBinding 在特定命名空间内授予的角色(`admin`、`edit`、`view`)。

面向用户的 ClusterRole 使用ClusterRole 聚合来允许管理员在这些 ClusterRole 上包含自定义资源的规则。 要将规则添加到 `admin`、`edit` 或 `view` 角色,请创建一个具有以下一个或多个标签的 ClusterRole

metadata:
  labels:
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"

默认 ClusterRole默认 ClusterRoleBinding描述
cluster-adminsystem:masters允许超级用户访问对任何资源执行任何操作。 在 ClusterRoleBinding 中使用时,它可以完全控制集群中所有命名空间中的每个资源。 在 RoleBinding 中使用时,它可以完全控制角色绑定命名空间中的每个资源,包括命名空间本身。
admin允许管理员访问,旨在使用 RoleBinding 在命名空间内授予。

如果在 RoleBinding 中使用,则允许对命名空间中的大多数资源进行读/写访问,包括在命名空间内创建角色和角色绑定的能力。 此角色不允许对资源配额或命名空间本身进行写访问。 此角色也不允许对使用 Kubernetes v1.22+ 创建的集群中的 EndpointSlices(或 Endpoints)进行写访问。 更多信息可在“EndpointSlices 和 Endpoints 的写访问权限”部分中找到。

edit允许对命名空间中的大多数对象进行读/写访问。

此角色不允许查看或修改角色或角色绑定。 但是,此角色允许访问 Secrets 并以命名空间中任何 ServiceAccount 的身份运行 Pod,因此它可用于获取命名空间中任何 ServiceAccount 的 API 访问级别。 此角色也不允许对使用 Kubernetes v1.22+ 创建的集群中的 EndpointSlices(或 Endpoints)进行写访问。 更多信息可在“EndpointSlices 和 Endpoints 的写访问权限”部分中找到。

view允许只读访问以查看命名空间中的大多数对象。 它不允许查看角色或角色绑定。

此角色不允许查看 Secrets,因为读取 Secrets 的内容可以访问命名空间中的 ServiceAccount 凭据,这将允许以命名空间中任何 ServiceAccount 的身份进行 API 访问(一种权限提升形式)。

核心组件角色

默认 ClusterRole默认 ClusterRoleBinding描述
system:kube-schedulersystem:kube-scheduler 用户允许访问调度程序组件所需的资源。
system:volume-schedulersystem:kube-scheduler 用户允许访问 kube-scheduler 组件所需的卷资源。
system:kube-controller-managersystem:kube-controller-manager 用户允许访问控制器管理器组件所需的资源。各个控制器所需的权限在控制器角色中有详细说明。
system:node允许访问 kubelet 所需的资源,包括对所有 secrets 的读取访问权限以及对所有 pod 状态对象的写入访问权限

您应该使用节点授权器NodeRestriction 准入插件而不是system:node角色,并允许根据计划在其上运行的 Pod 授予 kubelet API 访问权限。

system:node角色仅存在是为了与从 v1.8 之前的版本升级的 Kubernetes 集群兼容。

system:node-proxier系统:kube-proxy 用户允许访问 kube-proxy 组件所需的资源。

其他组件角色

默认 ClusterRole默认 ClusterRoleBinding描述
system:auth-delegator允许委派的认证和授权检查。这通常由附加组件 API 服务器用于统一认证和授权。
system:heapsterHeapster 组件的角色(已弃用)。
system:kube-aggregatorkube-aggregator 组件的角色。
system:kube-dnskube-system 命名空间中的 kube-dns 服务帐户kube-dns 组件的角色。
system:kubelet-api-admin允许完全访问 kubelet API。
system:node-bootstrapper允许访问执行 kubelet TLS 引导 所需的资源。
system:node-problem-detectornode-problem-detector 组件的角色。
system:persistent-volume-provisioner允许访问大多数 动态卷供应器 所需的资源。
system:monitoringsystem:monitoring允许读取控制平面监控端点(即 kube-apiserver 活跃性和就绪性端点(/healthz, /livez, /readyz),各个健康检查端点(/healthz/*, /livez/*, /readyz/*)以及/metrics)。请注意,各个健康检查端点和指标端点可能会暴露敏感信息。

内置控制器的角色

Kubernetes 控制器管理器 运行 Kubernetes 控制平面内置的 控制器。当使用 --use-service-account-credentials 调用时,kube-controller-manager 会使用单独的服务帐户启动每个控制器。每个内置控制器都有相应的角色,前缀为 system:controller:。如果控制器管理器未通过 --use-service-account-credentials 启动,它将使用自己的凭据运行所有控制循环,该凭据必须被授予所有相关角色。这些角色包括

  • system:controller:attachdetach-controller
  • system:controller:certificate-controller
  • system:controller:clusterrole-aggregation-controller
  • system:controller:cronjob-controller
  • system:controller:daemon-set-controller
  • system:controller:deployment-controller
  • system:controller:disruption-controller
  • system:controller:endpoint-controller
  • system:controller:expand-controller
  • system:controller:generic-garbage-collector
  • system:controller:horizontal-pod-autoscaler
  • system:controller:job-controller
  • system:controller:namespace-controller
  • system:controller:node-controller
  • system:controller:persistent-volume-binder
  • system:controller:pod-garbage-collector
  • system:controller:pv-protection-controller
  • system:controller:pvc-protection-controller
  • system:controller:replicaset-controller
  • system:controller:replication-controller
  • system:controller:resourcequota-controller
  • system:controller:root-ca-cert-publisher
  • system:controller:route-controller
  • system:controller:service-account-controller
  • system:controller:service-controller
  • system:controller:statefulset-controller
  • system:controller:ttl-controller

权限提升预防和引导

RBAC API 可防止用户通过编辑角色或角色绑定来提升权限。由于这是在 API 级别强制执行的,因此即使 RBAC 授权器未在使用中,它也适用。

角色创建或更新的限制

仅当满足以下至少一个条件时,您才能创建/更新角色

  1. 您已拥有角色中包含的所有权限,并且权限范围与正在修改的对象相同(对于 ClusterRole,范围为集群范围;对于 Role,范围为同一命名空间内或集群范围)。
  2. 您已被授予在 rbac.authorization.k8s.io API 组中的 rolesclusterroles 资源上执行 escalate 动词的显式权限。

例如,如果 user-1 没有在集群范围内列出 Secret 的能力,则他们无法创建包含该权限的 ClusterRole。要允许用户创建/更新角色

  1. 授予他们一个角色,允许他们根据需要创建/更新 Role 或 ClusterRole 对象。
  2. 授予他们在其创建/更新的角色中包含特定权限的权限
    • 隐式地,通过授予他们这些权限(如果他们尝试创建或修改具有他们自己未被授予的权限的 Role 或 ClusterRole,则 API 请求将被禁止)
    • 或者通过授予他们在 rbac.authorization.k8s.io API 组中的 rolesclusterroles 资源上执行 escalate 动词的权限,显式地允许在 RoleClusterRole 中指定任何权限

角色绑定创建或更新的限制

仅当您已拥有引用的角色中包含的所有权限(与角色绑定的范围相同)_或_您已被授权对引用的角色执行 bind 动词时,您才能创建/更新角色绑定。例如,如果 user-1 没有在集群范围内列出 Secret 的能力,则他们无法创建到授予该权限的角色的 ClusterRoleBinding。要允许用户创建/更新角色绑定

  1. 授予他们一个角色,允许他们根据需要创建/更新 RoleBinding 或 ClusterRoleBinding 对象。
  2. 授予他们绑定特定角色所需的权限
    • 隐式地,通过授予他们角色中包含的权限。
    • 显式地,通过授予他们对特定 Role(或 ClusterRole)执行 bind 动词的权限。

例如,此 ClusterRole 和 RoleBinding 将允许 user-1 在命名空间 user-1-namespace 中授予其他用户 admineditview 角色

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-grantor
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["rolebindings"]
  verbs: ["create"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["clusterroles"]
  verbs: ["bind"]
  # omit resourceNames to allow binding any ClusterRole
  resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: role-grantor-binding
  namespace: user-1-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: role-grantor
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: user-1

在引导第一个角色和角色绑定时,初始用户必须授予他们尚不具备的权限。要引导初始角色和角色绑定

  • 使用具有“system:masters”组的凭据,该组通过默认绑定绑定到“cluster-admin”超级用户角色。

命令行实用程序

kubectl create role (创建角色)

创建定义单个命名空间内权限的 Role 对象。例子

  • 创建一个名为“pod-reader”的 Role,允许用户对 Pod 执行 getwatchlist 操作

    kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
    
  • 创建指定 resourceNames 的名为“pod-reader”的 Role

    kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
    
  • 创建指定 apiGroups 的名为“foo”的 Role

    kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
    
  • 创建具有子资源权限的名为“foo”的 Role

    kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
    
  • 创建名为“my-component-lease-holder”的 Role,具有获取/更新具有特定名称的资源的权限

    kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
    

kubectl create clusterrole (创建集群角色)

创建 ClusterRole。例子

  • 创建一个名为“pod-reader”的 ClusterRole,允许用户对 Pod 执行 getwatchlist 操作

    kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
    
  • 创建指定 resourceNames 的名为“pod-reader”的 ClusterRole

    kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
    
  • 创建指定 apiGroups 的名为“foo”的 ClusterRole

    kubectl create clusterrole foo --verb=get,list,watch --resource=replicasets.apps
    
  • 创建具有子资源权限的名为“foo”的 ClusterRole

    kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
    
  • 创建指定 nonResourceURL 的名为“foo”的 ClusterRole

    kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
    
  • 创建指定 aggregationRule 的名为“monitoring”的 ClusterRole

    kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"
    

kubectl create rolebinding (创建角色绑定)

在特定命名空间内授予 Role 或 ClusterRole。例子

  • 在“acme”命名空间内,将“admin”ClusterRole 中的权限授予名为“bob”的用户

    kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
    
  • 在“acme”命名空间内,将“view”ClusterRole 中的权限授予“acme”命名空间中名为“myapp”的服务帐户

    kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
    
  • 在“acme”命名空间内,将“view”ClusterRole 中的权限授予“myappnamespace”命名空间中名为“myapp”的服务帐户

    kubectl create rolebinding myappnamespace-myapp-view-binding --clusterrole=view --serviceaccount=myappnamespace:myapp --namespace=acme
    

kubectl create clusterrolebinding (创建集群角色绑定)

在整个集群(所有命名空间)中授予 ClusterRole。例子

  • 在整个集群中,将“cluster-admin”ClusterRole 中的权限授予名为“root”的用户

    kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
    
  • 在整个集群中,将“system:node-proxier”ClusterRole 中的权限授予名为“system:kube-proxy”的用户

    kubectl create clusterrolebinding kube-proxy-binding --clusterrole=system:node-proxier --user=system:kube-proxy
    
  • 在整个集群中,将“view”ClusterRole 中的权限授予“acme”命名空间中名为“myapp”的服务帐户

    kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
    

kubectl auth reconcile (协调)

从清单文件创建或更新 rbac.authorization.k8s.io/v1 API 对象。

将创建缺少的对象,如果需要,将为命名空间对象创建包含命名空间。

将更新现有角色以包含输入对象中的权限,如果指定了 --remove-extra-permissions,则将删除额外的权限。

将更新现有绑定以包含输入对象中的主体,如果指定了 --remove-extra-subjects,则将删除额外的主体。

例子

  • 测试应用 RBAC 对象的清单文件,显示将进行的更改

    kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client
    
  • 应用 RBAC 对象的清单文件,保留任何额外权限(在角色中)和任何额外主体(在绑定中)

    kubectl auth reconcile -f my-rbac-rules.yaml
    
  • 应用 RBAC 对象的清单文件,删除任何额外权限(在角色中)和任何额外主体(在绑定中)

    kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions
    

ServiceAccount 权限

默认 RBAC 策略向控制平面组件、节点和控制器授予范围权限,但_不_向 kube-system 命名空间之外的服务帐户授予任何权限(API 发现角色 授予的权限除外)。

这允许您根据需要向特定 ServiceAccount 授予特定角色。细粒度的角色绑定提供了更高的安全性,但需要更多的管理工作。更广泛的授权可以向 ServiceAccount 提供不必要的(并且可能升级)API 访问权限,但更容易管理。

从最安全到最不安全的顺序,方法如下

  1. 将角色授予特定于应用程序的服务帐户(最佳实践)

    这要求应用程序在其 Pod 规范中指定 serviceAccountName,并创建服务帐户(通过 API、应用程序清单、kubectl create serviceaccount 等)。

    例如,将“my-namespace”内的只读权限授予“my-sa”服务帐户

    kubectl create rolebinding my-sa-view \
      --clusterrole=view \
      --serviceaccount=my-namespace:my-sa \
      --namespace=my-namespace
    
  2. 将角色授予命名空间中的“default”服务帐户

    如果应用程序未指定 serviceAccountName,则它将使用“default”服务帐户。

    例如,将“my-namespace”内的只读权限授予“default”服务帐户

    kubectl create rolebinding default-view \
      --clusterrole=view \
      --serviceaccount=my-namespace:default \
      --namespace=my-namespace
    

    许多附加组件kube-system 命名空间中以“default”服务帐户身份运行。要允许这些附加组件以超级用户访问权限运行,请将集群管理员权限授予 kube-system 命名空间中的“default”服务帐户。

    kubectl create clusterrolebinding add-on-cluster-admin \
      --clusterrole=cluster-admin \
      --serviceaccount=kube-system:default
    
  3. 将角色授予命名空间中的所有服务帐户

    如果您希望命名空间中的所有应用程序都具有一个角色,无论它们使用什么服务帐户,都可以将角色授予该命名空间的服务帐户组。

    例如,将“my-namespace”内的只读权限授予该命名空间中的所有服务帐户

    kubectl create rolebinding serviceaccounts-view \
      --clusterrole=view \
      --group=system:serviceaccounts:my-namespace \
      --namespace=my-namespace
    
  4. 将受限角色授予所有集群范围的服务帐户(不推荐)

    如果您不想按命名空间管理权限,可以将集群范围的角色授予所有服务帐户。

    例如,将所有命名空间的只读权限授予集群中的所有服务帐户

    kubectl create clusterrolebinding serviceaccounts-view \
      --clusterrole=view \
     --group=system:serviceaccounts
    
  5. 将超级用户访问权限授予所有集群范围的服务帐户(强烈不推荐)

    如果您根本不关心权限划分,则可以将超级用户访问权限授予所有服务帐户。

    kubectl create clusterrolebinding serviceaccounts-cluster-admin \
      --clusterrole=cluster-admin \
      --group=system:serviceaccounts
    

EndpointSlices 和 Endpoints 的写入访问权限

在 Kubernetes v1.22 之前创建的 Kubernetes 集群在聚合的“edit”和“admin”角色中包含对 EndpointSlices(和 Endpoints)的写入访问权限。作为对 CVE-2021-25740 的缓解措施,此访问权限不是使用 Kubernetes v1.22 或更高版本创建的集群中聚合角色的一部分。

已升级到 Kubernetes v1.22 的现有集群将不受此更改的影响。CVE 公告 包括有关限制现有集群中此访问权限的指南。

如果您希望新集群在聚合角色中保留此访问级别,则可以创建以下 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    kubernetes.io/description: |-
      Add endpoints write permissions to the edit and admin roles. This was
      removed by default in 1.22 because of CVE-2021-25740. See
      https://issue.k8s.io/103675. This can allow writers to direct LoadBalancer
      or Ingress implementations to expose backend IPs that would not otherwise
      be accessible, and can circumvent network policies or security controls
      intended to prevent/isolate access to those backends.
      EndpointSlices were never included in the edit or admin roles, so there
      is nothing to restore for the EndpointSlice API.      
  labels:
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
  name: custom:aggregate-to-edit:endpoints # you can change this if you wish
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "deletecollection", "patch", "update"]

从 ABAC 升级

最初运行较旧 Kubernetes 版本的集群通常使用宽松的 ABAC 策略,包括向所有服务帐户授予完全 API 访问权限。

默认 RBAC 策略向控制平面组件、节点和控制器授予范围权限,但_不_向 kube-system 命名空间之外的服务帐户授予任何权限(API 发现角色 授予的权限除外)。

虽然安全性更高,但这可能会破坏预期自动接收 API 权限的现有工作负载。以下是管理此过渡的两种方法

并行授权器

同时运行 RBAC 和 ABAC 授权器,并指定包含 旧版 ABAC 策略 的策略文件

--authorization-mode=...,RBAC,ABAC --authorization-policy-file=mypolicy.json

详细解释第一个命令行选项:如果较早的授权器(例如 Node)拒绝请求,则 RBAC 授权器将尝试授权 API 请求。如果 RBAC 也拒绝该 API 请求,则运行 ABAC 授权器。这意味着允许由 *RBAC 或 ABAC 策略*允许的任何请求。

当 kube-apiserver 为 RBAC 组件以 5 或更高级别运行日志级别(--vmodule=rbac*=5--v=5)时,您可以在 API 服务器日志中看到 RBAC 拒绝(以 RBAC 为前缀)。您可以使用该信息来确定需要向哪些用户、组或服务帐户授予哪些角色。

在您向服务帐户授予角色并且工作负载在服务器日志中没有 RBAC 拒绝消息的情况下运行后,您可以删除 ABAC 授权器。

宽松的 RBAC 权限

您可以使用 RBAC 角色绑定复制宽松的 ABAC 策略。

过渡到使用 RBAC 后,您应该调整集群的访问控制,以确保这些控制满足您的信息安全需求。

上次修改时间:2024 年 10 月 18 日下午 3:31 PST:KEP-3221:将 StructuredAuthorizationConfiguration 提升为 GA (32aad9dd3f)