使用 RBAC 授权
基于角色的访问控制(Role-based access control, RBAC)是一种根据组织内各个用户的角色来调节对计算机或网络资源的访问的方法。
RBAC 授权使用 `rbac.authorization.k8s.io` API 组来驱动授权决策,允许你通过 Kubernetes API 动态配置策略。
要启用 RBAC,启动 API 服务器时,将 `authorization-config` 标志设置为包含 `RBAC` 授权器的文件;例如:
apiVersion: apiserver.config.k8s.io/v1
kind: AuthorizationConfiguration
authorizers:
...
- type: RBAC
...
或者,启动 API 服务器时,将 `authorization-mode` 标志设置为逗号分隔的列表,其中包含 `RBAC`;例如:
kube-apiserver --authorization-mode=...,RBAC --other-options --more-options
API 对象
RBAC API 声明了四种 Kubernetes 对象:**Role**、**ClusterRole**、**RoleBinding** 和 **ClusterRoleBinding**。你可以使用 `kubectl` 等工具描述或修改 RBAC 对象,就像操作任何其他 Kubernetes 对象一样。
注意
这些对象在设计上施加了访问限制。如果你在学习过程中修改集群,请参阅权限提升预防和引导,以了解这些限制如何阻止你进行某些更改。Role 和 ClusterRole
RBAC **Role** 或 **ClusterRole** 包含表示一组权限的规则。权限是纯粹叠加的(没有“拒绝”规则)。
Role 始终在特定的命名空间中设置权限;当你创建 Role 时,必须指定其所属的命名空间。
相比之下,ClusterRole 是一种非命名空间资源。这些资源具有不同的名称(Role 和 ClusterRole),因为 Kubernetes 对象始终必须是命名空间的或非命名空间的;它不能两者兼具。
ClusterRole 有多种用途。你可以使用 ClusterRole 来
- 定义对命名空间资源的权限,并授予对单个命名空间(或多个命名空间)的访问权限
- 定义对命名空间资源的权限,并授予对所有命名空间的访问权限
- 定义对集群范围资源的权限
如果你想在命名空间内定义一个角色,请使用 Role;如果你想在集群范围定义一个角色,请使用 ClusterRole。
角色示例
这里是一个“default”命名空间中的 Role 示例,可用于授予对 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"]
ClusterRole 示例
ClusterRole 可以用于授予与 Role 相同的权限。由于 ClusterRole 是集群范围的,你还可以使用它们来授予对以下资源的访问权限
集群范围的资源(如 节点)
非资源端点(如 `healthz`)
所有命名空间中的命名空间资源(如 Pod)
例如:你可以使用 ClusterRole 允许特定用户运行 `kubectl get pods --all-namespaces`
以下是一个 ClusterRole 示例,可用于授予对任何特定命名空间或所有命名空间中 Secret 的读访问权限(取决于其绑定方式)
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"]
Role 或 ClusterRole 对象的名称必须是有效的路径段名称。
RoleBinding 和 ClusterRoleBinding
角色绑定将角色中定义的权限授予一个或一组用户。它包含一个**主体**(用户、组或服务账号)列表,以及对所授予角色的引用。RoleBinding 授予特定命名空间内的权限,而 ClusterRoleBinding 授予集群范围的访问权限。
RoleBinding 可以引用同一命名空间中的任何 Role。或者,RoleBinding 可以引用 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的命名空间。如果你想将 ClusterRole 绑定到集群中的所有命名空间,则使用 ClusterRoleBinding。
RoleBinding 或 ClusterRoleBinding 对象的名称必须是有效的路径段名称。
RoleBinding 示例
以下是一个 RoleBinding 示例,它在“default”命名空间中授予用户“jane” “pod-reader” Role。这允许“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
RoleBinding 还可以引用 ClusterRole,以将该 ClusterRole 中定义的权限授予 RoleBinding 命名空间内的资源。这种引用方式允许你在集群中定义一组通用角色,然后在多个命名空间中重用它们。
例如,即使下面的 RoleBinding 引用了一个 ClusterRole,"dave"(主体,区分大小写)也只能在 "development" 命名空间中读取 Secret,因为 RoleBinding 的命名空间(在其元数据中)是 "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
ClusterRoleBinding 示例
要授予整个集群的权限,你可以使用 ClusterRoleBinding。以下 ClusterRoleBinding 允许“manager”组中的任何用户读取任何命名空间中的 Secret。
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
创建绑定后,你无法更改其引用的 Role 或 ClusterRole。如果你尝试更改绑定的 `roleRef`,你将收到验证错误。如果你确实想更改绑定的 `roleRef`,你需要删除绑定对象并重新创建。
此限制有两个原因
- 使 `roleRef` 不可变允许授予某人对现有绑定对象的 `update` 权限,以便他们可以管理主体列表,而无法更改授予这些主体的角色。
- 绑定到不同角色本质上是一个完全不同的绑定。要求删除/重新创建绑定以更改 `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 资源的命名空间资源,而 `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: [""]
#
# at the HTTP level, the name of the resource for accessing ConfigMap
# objects is "configmaps"
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
注意
你不能通过资源名称限制 `create` 或 `deletecollection` 请求。对于 `create`,此限制是因为在授权时可能无法知道新对象的名称。如果你通过 resourceName 限制 `list` 或 `watch`,客户端必须在它们的 `list` 或 `watch` 请求中包含一个 `metadata.name` 字段选择器,该选择器与指定的 resourceName 匹配才能获得授权。例如,`kubectl get configmaps --field-selector=metadata.name=my-configmap`除了引用单个 `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 # DO NOT USE THIS ROLE, IT IS JUST AN EXAMPLE
rules:
- apiGroups: ["example.com"]
resources: ["*"]
verbs: ["*"]
注意
在资源和动词条目中使用通配符可能会导致对敏感资源授予过高的权限。例如,如果添加了新的资源类型,或者添加了新的子资源,或者检查了新的自定义动词,通配符条目会自动授予访问权限,这可能是不可取的。应该采用最小权限原则,使用特定的资源和动词来确保只应用工作负载正常运行所需的权限。聚合 ClusterRole
你可以将多个 ClusterRole **聚合**为一个组合的 ClusterRole。作为集群控制平面一部分运行的控制器会监视设置了 `aggregationRule` 的 ClusterRole 对象。`aggregationRule` 定义一个标签选择器,控制器使用该选择器来匹配应组合到该 ClusterRole 的 `rules` 字段中的其他 ClusterRole 对象。
注意
控制平面会覆盖你在聚合 ClusterRole 的 `rules` 字段中手动指定的任何值。如果你想更改或添加规则,请在由 `aggregationRule` 选择的 `ClusterRole` 对象中进行。这是一个聚合 ClusterRole 的示例
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
如果你创建一个与现有聚合 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"
# 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"]
默认用户可见角色使用 ClusterRole 聚合。这允许你作为集群管理员,为自定义资源(例如由 CustomResourceDefinitions 或聚合 API 服务器提供)包含规则,以扩展默认角色。
例如:以下 ClusterRole 允许“admin”和“edit”默认角色管理名为 CronTab 的自定义资源,而“view”角色只能对 CronTab 资源执行读取操作。你可以假设 CronTab 对象在 API 服务器可见的 URL 中名为 `"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"]
角色示例
以下示例是 Role 或 ClusterRole 对象的节选,仅显示 `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 组中读/写 Deployments(在 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`(因为节点是集群范围的,这必须在一个 ClusterRole 中,并通过 ClusterRoleBinding 绑定才能生效)
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 将角色绑定到主体。主体可以是组、用户或 ServiceAccount。
Kubernetes 将用户名表示为字符串。这些可以是:普通名称,如“alice”;电子邮件样式名称,如“bob@example.com”;或表示为字符串的数字用户 ID。作为集群管理员,你需要配置身份验证模块,以便身份验证产生你想要的用户名格式。
注意
`system:` 前缀保留用于 Kubernetes 系统使用,因此你应该确保你的用户或组的名称不会意外地以 `system:` 开头。除了这个特殊前缀,RBAC 授权系统对用户名没有其他格式要求。在 Kubernetes 中,身份验证模块提供组信息。与用户一样,组也表示为字符串,并且该字符串没有格式要求,除了 `system:` 前缀被保留。
ServiceAccounts 的名称前缀为 `system:serviceaccount:`,并且属于名称前缀为 `system:serviceaccounts:` 的组。
注意
- `system:serviceaccount:`(单数)是 Service Account 用户名的前缀。
- `system:serviceaccounts:`(复数)是 Service Account 组的前缀。
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
默认角色和角色绑定
API 服务器会创建一组默认的 ClusterRole 和 ClusterRoleBinding 对象。其中许多都带有 `system:` 前缀,这表明该资源由集群控制平面直接管理。所有默认的 ClusterRole 和 ClusterRoleBinding 都带有 `kubernetes.io/bootstrapping=rbac-defaults` 标签。
注意
修改带有 `system:` 前缀的 ClusterRole 和 ClusterRoleBinding 时请务必小心。对这些资源的修改可能导致集群无法正常运行。自动协调
在每次启动时,API 服务器会更新默认集群角色中任何缺失的权限,并更新默认集群角色绑定中任何缺失的主体。这允许集群修复意外修改,并有助于在新的 Kubernetes 版本中权限和主体发生变化时保持角色和角色绑定保持最新。
要选择退出此协调,请在默认集群角色或默认集群 RoleBinding 上将 `rbac.authorization.kubernetes.io/autoupdate` 注解设置为 `false`。请注意,缺失默认权限和主体可能导致集群无法正常运行。
如果 RBAC 授权器处于活动状态,则默认启用自动协调。
API 发现角色
默认集群角色绑定授权未经验证和已验证的用户读取被认为可以公开访问的 API 信息(包括 CustomResourceDefinitions)。要禁用匿名未经验证的访问,请在 API 服务器配置中添加 `--anonymous-auth=false` 标志。
要通过 `kubectl` 查看这些角色的配置,请运行
kubectl get clusterroles system:discovery -o yaml
注意
如果你编辑该 ClusterRole,你的更改将在 API 服务器重启时通过自动协调被覆盖。为了避免被覆盖,要么不要手动编辑角色,要么禁用自动协调。默认 ClusterRole | 默认 ClusterRoleBinding | 描述 |
---|---|---|
system:basic-user | **system:authenticated** 组 | 允许用户对其自身的基本信息进行只读访问。在 v1.14 之前,此角色默认也绑定到system:unauthenticated默认情况下。 |
system:discovery | **system:authenticated** 组 | 允许对发现和协商 API 级别所需的 API 发现端点进行只读访问。在 v1.14 之前,此角色也绑定到system:unauthenticated默认情况下。 |
system:public-info-viewer | **system:authenticated** 和 **system: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-admin | **system:masters** 组 | 允许超级用户访问以对任何资源执行任何操作。当用于 **ClusterRoleBinding** 时,它赋予对集群中所有资源和所有命名空间的完全控制。当用于 **RoleBinding** 时,它赋予对角色绑定命名空间中所有资源的完全控制,包括命名空间本身。 |
admin | 无 | 允许管理员访问权限,旨在通过 **RoleBinding** 在命名空间内授予。 如果用于 **RoleBinding**,允许对命名空间中的大多数资源进行读/写访问,包括在命名空间内创建角色和角色绑定的能力。此角色不允许对资源配额或命名空间本身进行写访问。此角色也不允许对使用 Kubernetes v1.22+ 创建的集群中的 EndpointSlice 进行写访问。更多信息请参见“EndpointSlice 的写访问”部分。 |
edit | 无 | 允许对命名空间中的大多数对象进行读/写访问。 此角色不允许查看或修改角色或角色绑定。但是,此角色允许访问 Secret 并以命名空间中任何 ServiceAccount 的身份运行 Pod,因此它可用于获取命名空间中任何 ServiceAccount 的 API 访问级别。此角色也不允许对使用 Kubernetes v1.22+ 创建的集群中的 EndpointSlice 进行写访问。更多信息请参见“EndpointSlice 的写访问”部分。 |
view | 无 | 允许只读访问以查看命名空间中的大多数对象。它不允许查看角色或角色绑定。 此角色不允许查看 Secret,因为读取 Secret 的内容会允许访问命名空间中的 ServiceAccount 凭据,这将允许以命名空间中任何 ServiceAccount 的身份进行 API 访问(一种权限提升形式)。 |
核心组件角色
默认 ClusterRole | 默认 ClusterRoleBinding | 描述 |
---|---|---|
system:kube-scheduler | **system:kube-scheduler** 用户 | 允许访问 调度器组件所需的资源。 |
system:volume-scheduler | **system:kube-scheduler** 用户 | 允许访问 kube-scheduler 组件所需的卷资源。 |
system:kube-controller-manager | **system:kube-controller-manager** 用户 | 允许访问 控制器管理器 组件所需的资源。各个控制器所需的权限在控制器角色中详述。 |
system:node | 无 | 允许访问 kubelet 所需的资源,**包括对所有 Secret 的读访问权限和对所有 Pod 状态对象的写访问权限**。 你应该使用 节点授权器 和 NodeRestriction 准入插件 来代替system:node角色,并允许基于计划在其上运行的 Pod 向 kubelet 授予 API 访问权限。 该system:node角色仅为了与从 v1.8 之前版本升级的 Kubernetes 集群兼容而存在。 |
system:node-proxier | **system:kube-proxy** 用户 | 允许访问 kube-proxy 组件所需的资源。 |
其他组件角色
默认 ClusterRole | 默认 ClusterRoleBinding | 描述 |
---|---|---|
system:auth-delegator | 无 | 允许委托身份验证和授权检查。这通常用于插件 API 服务器的统一身份验证和授权。 |
system:heapster | 无 | Heapster 组件的角色(已弃用)。 |
system:kube-aggregator | 无 | kube-aggregator 组件的角色。 |
system:kube-dns | **kube-system** 命名空间中的 **kube-dns** 服务账号 | kube-dns 组件的角色。 |
system:kubelet-api-admin | 无 | 允许完全访问 kubelet API。 |
system:node-bootstrapper | 无 | 允许访问执行 kubelet TLS 引导所需的资源。 |
system:node-problem-detector | 无 | node-problem-detector 组件的角色。 |
system:persistent-volume-provisioner | 无 | 允许访问大多数动态卷供应器所需的资源。 |
system:monitoring | **system:monitoring** 组 | 允许对控制平面监控端点(即 kube-apiserver 的活跃度和就绪度端点(/healthz, /livez, /readyz)、各个健康检查端点(/healthz/*, /livez/*, /readyz/*), /metrics)进行读访问,并使 kube-apiserver 遵循请求中提供的 traceparent 头部以进行跟踪。请注意,各个健康检查端点和指标端点可能会暴露敏感信息。 |
内置控制器角色
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 授权器也适用。
角色创建或更新的限制
只有在满足以下至少一个条件时,你才能创建/更新角色:
- 你已拥有该角色中包含的所有权限,并且作用域与正在修改的对象相同(ClusterRole 为集群范围,Role 为相同命名空间或集群范围)。
- 你被明确授予对 `rbac.authorization.k8s.io` API 组中 `roles` 或 `clusterroles` 资源执行 `escalate` 动词的权限。
例如,如果 `user-1` 没有列出集群范围内 Secret 的能力,他们就不能创建一个包含该权限的 ClusterRole。要允许用户创建/更新角色:
- 根据需要,授予他们一个允许他们创建/更新 Role 或 ClusterRole 对象的角色。
- 授予他们权限,使其能够在其创建/更新的角色中包含特定权限。
- 隐式地,通过赋予他们这些权限(如果他们尝试创建或修改一个包含他们自己未被授予权限的 Role 或 ClusterRole,API 请求将被禁止)。
- 或者通过授予他们对 `rbac.authorization.k8s.io` API 组中 `roles` 或 `clusterroles` 资源执行 `escalate` 动词的权限,明确允许在 `Role` 或 `ClusterRole` 中指定任何权限。
角色绑定创建或更新的限制
只有在你已拥有引用角色中包含的所有权限(与角色绑定范围相同),或者你已获授权对引用角色执行 `bind` 动词时,你才能创建/更新角色绑定。例如,如果 `user-1` 没有列出集群范围内 Secret 的能力,他们就不能创建 ClusterRoleBinding 到授予该权限的角色。要允许用户创建/更新角色绑定:
- 根据需要,授予他们一个允许他们创建/更新 RoleBinding 或 ClusterRoleBinding 对象的角色。
- 授予他们绑定特定角色所需的权限
- 隐式地,通过赋予他们角色中包含的权限。
- 明确地,通过授予他们对特定 Role(或 ClusterRole)执行 `bind` 动词的权限。
例如,这个 ClusterRole 和 RoleBinding 将允许 `user-1` 在命名空间 `user-1-namespace` 中授予其他用户 `admin`、`edit` 和 `view` 角色。
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 执行 `get`、`watch` 和 `list` 操作。
kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
创建一个名为 "pod-reader" 的 Role,并指定 resourceNames。
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
创建一个名为 "foo" 的 Role,并指定 apiGroups。
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 执行 `get`、`watch` 和 `list` 操作。
kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
创建一个名为 "pod-reader" 的 ClusterRole,并指定 resourceNames。
kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
创建一个名为 "foo" 的 ClusterRole,并指定 apiGroups。
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
创建一个名为 "foo" 的 ClusterRole,并指定 nonResourceURL。
kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
创建一个名为 "monitoring" 的 ClusterRole,并指定 aggregationRule。
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 策略授予控制平面组件、节点和控制器作用域权限,但除了API 发现角色授予的权限外,**不授予** `kube-system` 命名空间之外的服务账号任何权限。
这允许你根据需要向特定的 ServiceAccounts 授予特定的角色。细粒度的角色绑定提供了更高的安全性,但管理起来需要更多精力。更广泛的授权可能会授予 ServiceAccounts 不必要(且可能升级)的 API 访问权限,但管理起来更容易。
从最安全到最不安全,方法如下:
向特定于应用程序的服务账号授予角色(最佳实践)
这要求应用程序在其 Pod Spec 中指定 `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
向命名空间中的“default”服务账号授予角色
如果应用程序未指定 `serviceAccountName`,则使用“default”服务账号。
注意
授予“default”服务账号的权限可供命名空间中任何未指定 `serviceAccountName` 的 Pod 使用。例如,授予“my-namespace”中“default”服务账号只读权限。
kubectl create rolebinding default-view \ --clusterrole=view \ --serviceaccount=my-namespace:default \ --namespace=my-namespace
许多附加组件以 `kube-system` 命名空间中的“default”服务账号运行。为了允许这些附加组件以超级用户权限运行,请向 `kube-system` 命名空间中的“default”服务账号授予 cluster-admin 权限。
注意
启用此功能意味着 `kube-system` 命名空间包含的 Secret 授予了对集群 API 的超级用户访问权限。kubectl create clusterrolebinding add-on-cluster-admin \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:default
向命名空间中的所有服务账号授予角色
如果你希望命名空间中的所有应用程序都拥有某个角色,无论它们使用哪个服务账号,你可以向该命名空间的服务账号组授予该角色。
例如,授予“my-namespace”中所有服务账号只读权限。
kubectl create rolebinding serviceaccounts-view \ --clusterrole=view \ --group=system:serviceaccounts:my-namespace \ --namespace=my-namespace
向集群范围内的所有服务账号授予受限角色(不建议)
如果你不想按命名空间管理权限,可以向所有服务帐户授予集群范围的角色。
例如,授予对集群中所有服务帐户跨所有命名空间的只读权限。
kubectl create clusterrolebinding serviceaccounts-view \ --clusterrole=view \ --group=system:serviceaccounts
向集群范围内的所有服务账号授予超级用户访问权限(强烈不建议)
如果你根本不关心权限划分,你可以授予所有服务账号超级用户访问权限。
警告
这允许任何应用程序完全访问你的集群,并授予任何具有 Secret 读取权限(或创建任何 Pod 能力)的用户完全访问你的集群的权限。kubectl create clusterrolebinding serviceaccounts-cluster-admin \ --clusterrole=cluster-admin \ --group=system:serviceaccounts
EndpointSlice 的写访问
在 Kubernetes v1.22 之前创建的 Kubernetes 集群,聚合的“edit”和“admin”角色中包含对 EndpointSlice(以及现在已弃用的 Endpoints API)的写访问权限。作为对 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 策略授予控制平面组件、节点和控制器作用域权限,但除了API 发现角色授予的权限外,**不授予** `kube-system` 命名空间之外的服务账号任何权限。
虽然这种方法更加安全,但可能会对期望自动获得 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 策略。
警告
以下策略允许**所有**服务账号充当集群管理员。在容器中运行的任何应用程序都会自动接收服务账号凭据,并可以对 API 执行任何操作,包括查看 Secret 和修改权限。这不是推荐的策略。
kubectl create clusterrolebinding permissive-binding \
--clusterrole=cluster-admin \
--user=admin \
--user=kubelet \
--group=system:serviceaccounts
切换到使用 RBAC 后,你应该调整集群的访问控制,以确保其满足你的信息安全需求。