配置基于角色的访问权限控制

本页面简要介绍了 Kubernetes 提供的 RBAC(基于角色的访问权限控制)系统,以及如何在 Google Kubernetes Engine (GKE) 中使用 Kubernetes RBAC。

概览

Kubernetes 内置了一项基于角色的访问权限控制 (RBAC) 机制,可让您配置一组特定的细化权限,以定义某一特定 Google Cloud 用户或用户组如何与集群(或集群的特定命名空间)中的任何 Kubernetes 对象互动。

默认情况下,Kubernetes RBAC 处于启用状态。

准备工作

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

  • 确保您已启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 确保您已安装 Cloud SDK
  • 使用以下方法之一为您的项目设置默认 gcloud 命令行工具设置:
    • 使用 gcloud init(如果您想要在系统引导下完成项目默认设置)。
    • 使用 gcloud config(如果您想要单独设置项目 ID、可用区和区域。

    gcloud init

    1. 运行 gcloud init 并按照说明操作:

      gcloud init

      如果您要在远程服务器上使用 SSH,请使用 --console-only 标志来防止命令启动浏览器:

      gcloud init --console-only
    2. 按照说明授权 gcloud 工具使用您的 Google Cloud 帐号。
    3. 创建新配置或选择现有配置。
    4. 选择 Google Cloud 项目。
    5. 选择默认的 Compute Engine 可用区
    6. 选择默认的 Compute Engine 区域

    gcloud config

    1. 设置默认项目 ID
      gcloud config set project PROJECT_ID
    2. 设置默认的 Compute Engine 区域(例如 us-central1):
      gcloud config set compute/region COMPUTE_REGION
    3. 设置默认的 Compute Engine 可用区(例如 us-central1-c):
      gcloud config set compute/zone COMPUTE_ZONE
    4. gcloud 更新到最新版本:
      gcloud components update

    通过设置默认位置,您可以避免 gcloud 工具中出现以下错误:One of [--zone, --region] must be supplied: Please specify location

与 Identity and Access Management 互动

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

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

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

在 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

API 用法和示例

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

问题排查和调试

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

限制

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

默认发现角色

创建的集群包含一组默认 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
    

后续步骤