使用基于角色的访问权限控制向集群中的操作授权


本页面介绍如何使用 Kubernetes 中内置的基于角色的访问权限控制 (RBAC) 机制来授权对 Google Kubernetes Engine (GKE) 集群中的资源执行的操作。

RBAC 是 Kubernetes 中的一个核心安全功能,可让您创建精细的权限,以管理用户和工作负载可以对集群中的资源执行的操作。作为平台管理员,您可以创建 RBAC 角色并将这些角色绑定到主体,这些主体是经过身份验证的用户,例如服务账号或群组。默认情况下,Kubernetes RBAC 处于启用状态。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。

与 Identity and Access Management 互动

您可以使用 Identity and Access Management (IAM) Kubernetes RBAC 来控制对 GKE 集群的访问权限:

  • IAM 并非特定于 Kubernetes;它为多种 Google Cloud 产品提供身份管理,并且主要在 Google Cloud 项目级层运行。

  • Kubernetes RBAC 是 Kubernetes 的核心组成部分,可让您针对集群内的任何对象或对象类型创建和授予角色(一组权限)。

  • 为了授权操作,GKE 首先会检查是否存在 RBAC 政策。如果不存在 RBAC 政策,GKE 会检查 IAM 权限。

在 GKE 中,IAM 和 Kubernetes RBAC 集成在一起,您可以通过任一工具向用户授权,使其有足够的权限执行操作。这对于 GKE 集群的引导过程至关重要,因为默认情况下,Google Cloud 用户不具有任何 Kubernetes RBAC RoleBindings。

如需使用 Google Cloud 账号向用户授权,您必须首先将客户端正确配置为使用这些账号进行身份验证。例如,如果您使用的是 kubectl,则必须先配置 kubectl 命令以向 Google Cloud 进行身份验证,然后才能运行任何需要授权的命令。

在几乎所有情况下,都可以使用 Kubernetes RBAC 而不是 IAM。GKE 用户至少需要拥有集群所属项目中的 container.clusters.get IAM 权限。此权限包含在 container.clusterViewer 角色以及其他具有更高特权的角色中。用户必须拥有 container.clusters.get 权限才能向项目中的集群进行身份验证,但并未获得授权在这些集群内执行任何操作。随后,授权可由 IAM 或 Kubernetes RBAC 提供。

定义和分配权限

您可以在 ClusterRoleRole 对象中定义 RBAC 规则,然后使用 ClusterRoleBindingRoleBinding 对象分配这些规则,如下所示:

  • ClusterRole:资源的集群级分组和允许的操作,您可以使用 RoleBindingClusterRoleBinding 将其分配给用户或组。
  • 角色:借助 RoleBinding 分配给资源或用户组的命名空间和分组操作。
  • ClusterRoleBinding:为集群中的所有命名空间向用户或群组分配一个 ClusterRole
  • RoleBinding:将 RoleClusterRole 分配给特定命名空间中的用户或群组。

使用 RoleBinding 为用户或群组分配 ClusterRole 时,这些用户和群组只能访问您在 RoleBinding 中指定的命名空间中的资源。如果您希望用户或群组访问所有命名空间中的资源,请改用 ClusterRoleBinding

使用 Role 或 ClusterRole 定义权限

您可以在 Role 或 ClusterRole 对象中定义权限。Role 用于定义对单个命名空间内资源的访问权限,而 ClusterRole 用于定义对整个集群内资源的访问权限。

Role 和 ClusterRole 采用相同语法。每个对象都有一个 rules 部分,您可以在其中定义规则应用于的资源以及为角色授予的操作。例如,以下 Role 授予 accounting 命名空间内所有 Pod 的读取访问权限(getwatchlist):

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

如需查看允许的字段的完整列表,请参阅 RoleClusterRole API 文档。

RoleClusterRole

由于 ClusterRole 授予的权限适用于整个集群,因此您可以使用 ClusterRole 来控制与使用 Role 可以控制的不同资源的访问权限。其中包括:

  • 集群级资源(例如节点)
  • 非资源 REST 端点(例如 /healthz
  • 所有命名空间内的命名空间型资源(例如,整个集群内的所有 Pod,无论位于哪个命名空间)

使用 RoleBinding 或 ClusterRoleBinding 分配角色

创建 Role 或 ClusterRole 后,您可以通过创建 RoleBinding 或 ClusterRoleBinding 将其分配给特定用户或用户组。用户和群组被称为 subjects,可以是以下任何类型:

主体类型 kind”的值 name”的值
Google Cloud 用户账号 User Google Cloud 注册电子邮件地址
Kubernetes 服务账号 ServiceAccount 集群中 Kubernetes ServiceAccount 对象的名称
IAM 服务账号 User 自动生成的 IAM 服务账号电子邮件地址
通过验证的网域上的 Google 群组地址 Group Google Workspace 群组的电子邮件地址,该地址是 gke-security-groups 群组的成员。有关为 RBAC 设置 Google 群组的说明,请参阅为 RBAC 设置 Google 群组

以下 RoleBinding 向用户、Kubernetes 服务账号、IAM 服务账号和 Google 群组授予 pod-reader 角色

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader-binding
  namespace: accounting
subjects:
# Google Cloud user account
- kind: User
  name: janedoe@example.com
# Kubernetes service account
- kind: ServiceAccount
  name: johndoe
# IAM service account
- kind: User
  name: test-account@test-project.iam.gserviceaccount.com
# Google Group
- kind: Group
  name: accounting-group@example.com
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

使用 kubectl 验证 API 访问权限

kubectl 提供 auth can-i 子命令,可快速查询 API 授权层。作为平台管理员,您可能需要模拟用户以确定他们可以执行的操作。您可以使用 auth can-i 并传递额外的 --as 标志。

当您运行不带 --as 标志的 kubectl auth can-i 命令时,Identity and Access Management (IAM) 会执行授权。而当您附加 --as 标志时,Kubernetes RBAC 会执行授权。因此,您需要为 RBAC 创建必要的 RoleRoleBinding 对象。

如需了解详情,请参阅验证 API 访问权限

API 用法和示例

如需全面了解如何使用 Kubernetes API 创建 RBAC 所需的 RoleClusterRoleRoleBindingClusterRoleBinding 对象,请参阅 Kubernetes 文档中的使用基于角色的访问权限控制授权

问题排查和调试

如需调试 RBAC 的问题,请使用管理员活动审核日志(默认情况下,系统会在所有集群上启用该日志)。如果由于缺少足够的权限而导致对资源或操作的访问被拒绝,则 API 服务器会记录 RBAC DENY 错误以及其他信息,例如用户的隐式和显式群组成员资格。如果您使用的是 Google RBAC 群组,则日志消息中会显示 google groups

限制

以下部分介绍了在使用 Kubernetes RBAC 和 IAM 时可能不太明显的交互。

默认发现角色

创建的集群包含一组默认 ClusterRole 和 ClusterRoleBinding。 使用有效凭据发出的请求将置于 system:authenticated 组中,而其他所有请求都将归入 system:unauthenticated

system:basic-user ClusterRole 可让用户进行 SelfSubjectAccessReviews,以测试其在集群中的权限。system:discovery 角色可让用户读取发现 API,这些 API 可以发现已添加到集群的 CustomResourceDefinitions 的相关信息。

匿名用户 (system:unauthenticated) 将收到 system:public-info-viewer ClusterRole,该角色会授予 /healthz/version API 的只读访问权限。

如需查看 system:discovery ClusterRole 允许的 API 端点,请运行以下命令:

kubectl get clusterroles system:discovery -o yaml

Google Cloud 虚拟机实例上的服务账号出现“禁止使用”错误

如果虚拟机实例没有 userinfo-email 范围,则可能会发生以下错误:

Error from server (Forbidden): error when creating ... "role-name" is forbidden: attempt to grant extra privileges:...

例如,假设虚拟机具有 cloud-platform 范围,但没有 userinfo-email 范围。当虚拟机获得访问令牌时,Google Cloud 会将该令牌与 cloud-platform 范围相关联。当 Kubernetes API 服务器向 Google Cloud 请求与访问令牌相关联的身份时,它会收到服务账号的唯一 ID,而不是服务账号的电子邮件地址。

如需成功进行身份验证,请使用 userinfo-email 范围创建新的虚拟机,或者创建使用唯一 ID 的新角色绑定。

如需使用 userinfo-email 范围创建新的虚拟机,请运行以下命令:

gcloud compute instances create INSTANCE_NAME \
    --service-account SERVICE_ACCOUNT_EMAIL \
    --scopes userinfo-email

如需创建使用现有虚拟机的服务账号唯一 ID 的新角色绑定,请执行以下步骤:

  1. 标识服务账号的唯一 ID:

    gcloud iam service-accounts describe SERVICE_ACCOUNT_EMAIL
    

    例如,以下输出会显示 my-iam-account@somedomain.com 服务账号的 uniqueId

    displayName: Some Domain IAM service account
    email: my-iam-account@somedomain.com
    etag: BwWWja0YfJA
    name: projects/project-name/serviceAccounts/my-iam-account@somedomain.com
    oauth2ClientId: '123456789012345678901'
    projectId: project-name
    uniqueId: '123456789012345678901'
    
  2. 使用服务账号的 uniqueId 创建角色绑定:

    kubectl create clusterrolebinding CLUSTERROLEBINDING_NAME \
        --clusterrole cluster-admin \
        --user UNIQUE_ID
    

创建或更新角色和角色绑定的权限

在 Kubernetes 中,仅当您满足以下条件时,才能创建或更新具有特定权限的角色或角色绑定:

  • 创建或更新角色:您必须已经拥有要授予该角色的权限。或者,您必须有权对该角色执行 escalate 动词。
  • 创建或更新角色绑定:您必须已经拥有要绑定的角色中授予的相同权限,范围与角色绑定相同。或者,您必须有权对引用的角色执行 bind 动词。

如果您在角色中授予的权限最初是使用 IAM 政策(而不是 RBAC)向您授予的,则您的角色或角色绑定请求可能会失败。例如,考虑以下角色创建请求,该请求来自已被授予 container.pods.*container.roles.create IAM 权限的用户:

kubectl create role allowed-to-view-pods --resource pods --verb list,get

如果仅使用 IAM 向用户授予了这些权限,则可能会发生以下错误:

Error from server (Forbidden): clusterroles.rbac.authorization.k8s.io "allowed-to-view-pods" is forbidden:
user "caller@example.com" (groups=["system:authenticated"]) is attempting to grant RBAC permissions not currently held:
{APIGroups:[""], Resources:["pods"], Verbs:["list" "get"]}

要缓解此限制,请使用 RBAC(而非 IAM)向调用方授予角色中的权限。

您也可以使用 RBAC 或 IAM 向调用方授予 escalate 和/或 bind 动词。但是,GKE 不建议使用此方法,因为这样调用方可以向任何角色授予任何权限。

后续步骤