使用 RBAC 授权
基于角色的访问控制 (RBAC) 是一种根据组织中个人用户的角色来调节对计算机或网络资源访问的方法。
RBAC 授权使用 rbac.authorization.k8s.io
API 组 来驱动授权决策,允许您通过 Kubernetes API 动态配置策略。
要启用 RBAC,请使用 --authorization-mode
标志将 API 服务器
启动为包含 RBAC
的逗号分隔列表;例如
kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options
API 对象
RBAC API 声明了四种 Kubernetes 对象:角色、集群角色、角色绑定 和 集群角色绑定。您可以使用 kubectl
等工具描述或修改 RBAC 对象,就像任何其他 Kubernetes 对象一样。
注意
这些对象的设计目的是为了施加访问限制。如果您在学习时正在对集群进行更改,请参阅 特权提升预防和引导 以了解这些限制如何阻止您进行某些更改。角色和集群角色
RBAC 角色 或 集群角色 包含表示一组权限的规则。权限纯粹是累加的(没有“拒绝”规则)。
角色始终在特定 命名空间 内设置权限;当您创建角色时,您必须指定它所属的命名空间。
相比之下,集群角色是非命名空间资源。这些资源具有不同的名称(角色和集群角色),因为 Kubernetes 对象始终必须是命名空间或非命名空间的;它不能同时是两者。
集群角色有几种用途。您可以使用集群角色来
- 定义对命名空间资源的权限,并在单个命名空间内被授予访问权限
- 定义对命名空间资源的权限,并在所有命名空间中被授予访问权限
- 定义对集群范围资源的权限
如果您想在命名空间内定义角色,请使用角色;如果您想在集群范围内定义角色,请使用集群角色。
角色示例
这是一个在“默认”命名空间中的角色示例,它可用于授予对 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”角色授予“默认”命名空间内的用户“jane”。这允许“jane”读取“默认”命名空间中的 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
,则需要删除绑定对象并创建替换对象。
此限制有两个原因
- 使
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
,您可以使用通配符 *
作为后缀 glob 匹配。对于 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 来向“监控”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 允许“管理员”和“编辑”默认角色管理名为 CronTab 的自定义资源,而“查看”角色只能对 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 组中读取/写入 Deployment(在 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"
(因为 Node 是集群范围的,所以必须在与 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 将角色绑定到主体。主体可以是组、用户或ServiceAccount。
Kubernetes 将用户名表示为字符串。这些可以是:普通名称,如“alice”;电子邮件样式的名称,如“bob@example.com”;或以字符串表示的数字用户 ID。作为集群管理员,您需要配置身份验证模块,以便身份验证以您想要的格式生成用户名。
注意
前缀system:
为 Kubernetes 系统使用保留,因此您应确保没有用户或组的名称意外以 system:
开头。除了此特殊前缀外,RBAC 授权系统对用户名没有格式要求。在 Kubernetes 中,身份验证器模块提供组信息。组与用户一样,也用字符串表示,并且该字符串没有格式要求,除了前缀 system:
是保留的。
ServiceAccount 的名称以 system:serviceaccount:
为前缀,并属于以 system:serviceaccounts:
为前缀的组。
注意
system:serviceaccount:
(单数)是服务帐户用户名的前缀。system:serviceaccounts:
(复数)是服务帐户组的前缀。
角色绑定示例
以下示例是 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)。要禁用匿名未经身份验证的访问,请将 --anonymous-auth=false
标志添加到 API 服务器配置中。
要通过 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+ 创建的集群中的 EndpointSlices(或 Endpoints)进行写访问。有关更多信息,请参阅“EndpointSlices 和 Endpoints 的写访问权限”部分。 |
edit | 无 | 允许对命名空间中的大多数对象进行读/写访问。 此角色不允许查看或修改角色或角色绑定。但是,此角色允许访问 Secret 并以命名空间中的任何 ServiceAccount 的身份运行 Pod,因此它可以用来获得命名空间中任何 ServiceAccount 的 API 访问级别。此角色也不允许对使用 Kubernetes v1.22+ 创建的集群中的 EndpointSlices(或 Endpoints)进行写访问。有关更多信息,请参阅“EndpointSlices 和 Endpoints 的写访问权限”部分。 |
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 访问权限。 Thesystem: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-dns 服务帐户在 kube-system 命名空间中 | 用于 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)。请注意,每个健康检查端点和指标端点可能暴露敏感信息。 |
用于内置控制器的角色
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
没有在集群范围内列出 Secrets 的能力,他们就无法创建包含该权限的 ClusterRole。要允许用户创建/更新角色
- 授予他们一个角色,允许他们根据需要创建/更新 Role 或 ClusterRole 对象。
- 授予他们权限,让他们在创建/更新角色时包含特定权限
- 隐式地,通过授予他们这些权限(如果他们尝试创建或修改一个 Role 或 ClusterRole,而他们自己没有被授予权限,API 请求将被禁止)
- 或通过授予他们对
rbac.authorization.k8s.io
API 组中的roles
或clusterroles
资源执行escalate
动词的权限,明确允许在Role
或ClusterRole
中指定任何权限。
对角色绑定创建或更新的限制
您只能在已经拥有引用角色中包含的所有权限(与角色绑定相同的范围)或已被授权对引用角色执行 bind
动词的情况下创建/更新角色绑定。例如,如果 user-1
没有在集群范围内列出 Secrets 的能力,他们就无法创建将该权限授予角色的 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,其中指定了资源名称
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
创建一个名为 "foo" 的 Role,其中指定了 api 组
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,其中指定了资源名称
kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
创建一个名为 "foo" 的 ClusterRole,其中指定了 api 组
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,其中指定了非资源 URL
kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
创建一个名为 "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 访问权限,但更容易管理。
从最安全到最不安全,方法如下
将角色授予应用程序特定的服务帐户(最佳实践)
这要求应用程序在其 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
将角色授予命名空间中的 "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" 服务帐户授予集群管理员权限。注意
启用此功能意味着kube-system
命名空间包含授予您的集群 API 超级用户访问权限的 Secrets。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
授予所有服务帐户集群范围的超级用户访问权限(强烈不建议)
如果您根本不关心分区权限,则可以授予所有服务帐户超级用户访问权限。
警告
这允许任何应用程序完全访问您的集群,并且还授予任何具有读取秘密访问权限(或创建任何 Pod 的能力)的用户完全访问您的集群。kubectl create clusterrolebinding serviceaccounts-cluster-admin \ --clusterrole=cluster-admin \ --group=system:serviceaccounts
EndpointSlices 和 Endpoints 的写入访问权限
在 Kubernetes v1.22 之前创建的 Kubernetes 集群包括对聚合的“编辑”和“管理员”角色中的 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 以 5 或更高的日志级别运行 RBAC 组件(--vmodule=rbac*=5
或 --v=5
)时,您可以在 API 服务器日志中看到 RBAC 拒绝(以 RBAC
为前缀)。您可以使用该信息来确定需要授予哪些用户、组或服务帐户哪些角色。
一旦您 向服务帐户授予了角色 并且工作负载在服务器日志中没有 RBAC 拒绝消息的情况下运行,您就可以删除 ABAC 授权器。
宽松的 RBAC 权限
您可以使用 RBAC 角色绑定复制宽松的 ABAC 策略。
警告
以下策略允许 **所有** 服务帐户充当集群管理员。在容器中运行的任何应用程序都会自动接收服务帐户凭据,并且可以对 API 执行任何操作,包括查看机密和修改权限。这不是推荐的策略。
kubectl create clusterrolebinding permissive-binding \
--clusterrole=cluster-admin \
--user=admin \
--user=kubelet \
--group=system:serviceaccounts
在您过渡到使用 RBAC 后,您应该调整集群的访问控制,以确保它们满足您的信息安全需求。