# k8s 中使用 RBAC 授权

基于角色的访问控制(“RBAC”)使用“rbac.authorization.k8s.io”API 组来实现授权控制,允许管理员通过 k8s API 动态配置策略。

截至 1.6 RBAC 模式是 beta 版。启用 RBAC:

apiserver --authorization-mode=RBAC。

# API 概述

RBAC API 声明了四个最高级别的类型(本文介绍),RBAC 的授权策略可以利用 kubectl 或者 k8s API 直接进行配置。RBAC 可以授权给用户,让用户有权进行授权管理,这样就无需接触节点,直接进行授权管理。RBAC 在 k8s 中被映射为 API 资源和操作。

# Role 和 ClusterRole

Role 是一系列的权限的集合,例如一个 Role 可以包含读取 Pod 的权限和列出 Pod 的权限,ClusterRole 跟 Role 类似,但是可以在集群中全局使用。

Role 只能授予单个 namespace 中资源的访问权限。以下是 Role“default”namespace 中的示例,用于授予对 pod 的访问权限:

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

ClusterRole 授权 >= Role 授予(与 Role 类似),但 ClusterRole 属于集群级别对象:

  • 集群范围(cluster-scoped)的资源访问控制(如:节点访问权限)
  • 非资源类型(如“/ healthz”)
  • 所有 namespaces 中的 namespaced 资源(如 pod)

ClusterRole 示例:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

# RoleBinding 和 ClusterRoleBinding

RoleBinding 是将 Role 中定义的权限授予给用户或用户组。它包含一个 subjects 列表(users,groups,service accounts),并引用该 Role。RoleBinding 在某个 namespace 内授权,ClusterRoleBinding 适用在集群范围内使用。

RoleBinding 可以引用相同 namespace 下定义的 Role。以下的 RoleBinding 在“default”namespace 中将“pod-reader”Role 授予用户“jane”。将允许“jane”在“default”namespace 中读取 pod 权限。

# This role binding allows "jane" to read pods in the "default" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding 还可以参考 ClusterRole。将允许管理员为整个集群定义一组通用 Role,然后在不同 namespace 中使用 RoleBinding 引用。

示例:

# This role binding allows "dave" to read secrets in the "development" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

最后,ClusterRoleBinding 可以用于集群中所有命名空间中授予权限。以下 ClusterRoleBinding 允许组“manager”中的任何用户在任何命名空间中读取 secrets。

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

# Referring to Resources

大多数资源由 name 字符串的形式表示,例如“pod”。然而,一些 k8s API 涉及“子资源”,例如 Pod 的 logs,pod log endpoint 的 URL:

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

在这种情况下,“pod”是 namespace 中资源,“log”是 pod 的子资源,这种情况要在 RBAC 角色中表示,可以使用斜杠来划分资源和子资源。如下例子:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

资源也可以通过 resourceNames 列表的某些请求的资源名称来引用。如下例子:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  resources: ["configmap"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

需要注意如果设置了 resourceNames,那么 verbs 不能指定为 list、watch、create 或 deletecollection。

# Role 示例

只有 rules 部分定义显示在以下示例中。

允许在核心 API Group 中读取“pods”资源:

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

允许在“extensions”和“apps”API Group 中读/写“deployments”:

rules:
- apiGroups: ["extensions", "apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取 “Pod” 和 读/写 “jobs”:

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取名称为 “my-config” 的 ConfigMap:

rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]

允许读取核心 Group 中资源“Node”(Node 属于集群范围,则必须将 ClusterRole 绑定 ClusterRoleBinding):

rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

允许非资源型“/ healthz”和所有子路径进行 “GET”和“POST”请求:(必须将 ClusterRole 绑定 ClusterRoleBinding):

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

# Referring to Subjects

RoleBinding 或 ClusterRoleBinding 可以将 Role 绑定到主体 subjects。Subjects 可以是 groups、users 和 service accounts。

用户名 Users 由字符串表示,可用的格式有,如纯字符“alice”,Emai 格式“bob@example.com”或表示为字符串的数字。Users 除了需要满足 k8s 管理员配置的 authentication modules,对 Users, RBAC 授权系统没有做任何格式限定。除了前缀为 system:是为 k8s 系统使用而保留的用户名格式,除此之外 RBAC 授权系统可以使用任何格式的 Users。

k8s 的 Group 信息目前由 Authenticator 模块提供。和 Users 一样,Group 由字符串表示,而且字符串没有格式要求,除了前缀 system:是保留的。

Service Accounts 使用 system:serviceaccount:前缀的用户名,并且属于具有 system:serviceaccounts:前缀的 Group 组。

# Role Binding 示例

适合一个名为“alice@example.com”的用户:

subjects:
- kind: User
  name: "alice@example.com"
  apiGroup: rbac.authorization.k8s.io

适合一个名为“frontend-admins”的 Group:

subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io

适合 kube-system Namespace 中的默认 ServiceAccount:

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

适合“qa”Namespace 中的所有 ServiceAccount:

subjects:
- kind: Group
  name: system:serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io

适合集群中所有 ServiceAccount:

subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

适合所有经过认证的用户(1.5 版本以上):

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io

适合所有未经认证的用户(1.5 版本以上):

subjects:
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

适合所有用户(1.5 版本以上):

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

# 默认 Role 和 Role Bindings

API Server 会创建一组默认的 ClusterRole 和 ClusterRoleBinding 对象。其中许多都是 system:前缀,表示这些资源属于系统基础组件。修改这些资源对象可能会引起一些未知错误。例如:是 system:nodeClusterRole,此角色定义了 kubelet 的权限,如果角色被修改,将会引起 kubelet 无法工作。

# Auto-reconciliation

在每次启动时,API Server 会更新默认的 cluster roles,并更新默认 ClusterRoleBinding 各个角色绑定主体,这使集群能够修复某些意外修改情况。

RBAC 授权器处于激活状态时,在 k8s 1.6 版本会默认启用 Auto-reconciliation 功能。

# Discovery Roles

Default ClusterRole Default ClusterRoleBinding Description
system:basic-user system:authenticated 和 system:unauthenticatedgroups Allows a user read-only access to basic information about themselves.
system:discovery system:authenticated 和 system:unauthenticatedgroups Allows read-only access to API discovery endpoints needed to discover and negotiate an API level

# User-facing Roles

一些不以 system:为前缀的角色是面向用户的 Role。它们包括超级用户 Role (cluster-admin),ClusterRoleBindings (cluster-status),以及特定 namespaces 中授权的 RoleBinding( admin,edit,view )

Default ClusterRole Default ClusterRoleBinding Description
cluster-admin system:masters group Allows super-user access to perform any action on any resource. When used in a ClusterRoleBinding, it gives full control over every resource in the cluster and in all namespaces. When used in a RoleBinding, it gives full control over every resource in the rolebinding's namespace, including the namespace itself.
admin None Allows admin access, intended to be granted within a namespace using a RoleBinding. If used in a RoleBinding, allows read/write access to most resources in a namespace, including the ability to create roles and rolebindings within the namespace. It does not allow write access to resource quota or to the namespace itself.
edit None Allows read/write access to most objects in a namespace. It does not allow viewing or modifying roles or rolebindings
view None Allows read-only access to see most objects in a namespace. It does not allow viewing roles or rolebindings. It does not allow viewing secrets, since those are escalating

# Core Component Roles

Default ClusterRole Default ClusterRoleBinding Description
system:kube-scheduler system:kube-scheduler user Allows access to the resources required by the kube-scheduler component.
system:kube-controller-manager system:kube-controller-manager user Allows access to the resources required by the kube-controller-manager component. The permissions required by individual control loops are contained in the controller roles.
system:node system:nodes group (deprecated in 1.7) Allows access to resources required by the kubelet component, including read access to all secrets, and write access to all pods. As of 1.7, use of the Node authorizer and NodeRestriction admission plugin is recommended instead of this role, and allow granting API access to kubelets based on the pods scheduled to run on them. As of 1.7, when the Node authorization mode is enabled, the automatic binding to the system:nodes group is not created.
system:node-proxier system:kube-proxy user Allows access to the resources required by the kube-proxy component

# Other Component Roles

Default ClusterRole Default ClusterRoleBinding Description
system:auth-delegator None Allows delegated authentication and authorization checks. This is commonly used by add-on API servers for unified authentication and authorization.
system:heapster None Role for the Heapster component.
system:kube-aggregator None Role for the kube-aggregator component.
system:kube-dns kube-dns service account in the kube-system namespace Role for the kube-dns component.
system:node-bootstrapper None Allows access to the resources required to perform Kubelet TLS bootstrapping.
system:node-problem-detector None Role for the node-problem-detector component.
system:persistent-volume-provisioner None Allows access to the resources required by most dynamic volume provisioners.

# Controller Roles

k8s controller manager 负责运行的核心控制循环(core control loops)。当调用--use-service-account-credentials 时,每个 control loops 都使用一个单独的 service account 启动,每个 control loops 存在前缀为 system:controller:的 Roles。如果 controller manager 未启动--use-service-account-credentials 选项,它将使用本身的凭证运行所有 control loops,如果这样需要在 RBAC 模式中授权相关 Role。这些角色包括:

  • system:controller:attachdetach-controller
  • system:controller:certificate-controller
  • system:controller:cronjob-controller
  • system:controller:daemon-set-controller
  • system:controller:deployment-controller
  • system:controller:disruption-controller
  • system:controller:endpoint-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:replicaset-controller
  • system:controller:replication-controller
  • system:controller:resourcequota-controller
  • system:controller:route-controller
  • system:controller:service-account-controller
  • system:controller:service-controller
  • system:controller:statefulset-controller
  • system:controller:ttl-controller

# 命令行工具

有两个 kubectl 命令,用于在单个 namespace 或整个集群中授权 Roles。

  • kubectl create clusterrolebinding
  • kubectl create rolebinding

# kubectl create rolebinding

授权特定 namespace 中的 Role 或 ClusterRole。如下示例:

  • 在“acme” Namespace 将 admin ClusterRole 授予用户“bob”:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
  • 在“acme”Namespace 将 view ClusterRole 授予用户为“myapp”的 Service Account:
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme

# kubectl create clusterrolebinding

在整个集群中所有 Namespace 下授予 ClusterRole。如下示例:

  • 在整个集群中将 cluster-admin ClusterRole 授予用户“root”:
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
  • 在整个集群中将 system:node ClusterRole 授予用户“kubelet”:
kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet
  • 在整个集群中将 view ClusterRole 授予 Namespace “acme”中的 serviceaccount”myapp”:
kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp

更多详细用法,请参考 CLI 说明

# Service Account Permissions

默认 RBAC 策略限定的权限授予范围有 control-plane 组件、nodes 和 controllers,不会向“kube-system”Namespace 之外的 Service Account 授予权限。

这允许你根据需要向特定的 Service Account 授予特定的 Role。细粒度角色绑定提供了更好的安全性,但需要更复杂的管理工作。更宽松的角色权限绑定可以提供不必要的 API 访问服务帐户权限,但更容易管理。

安全级别逐步降低:

1、应用指定 Service Account 授予特定的 Role(最佳实践)

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

2、在 Namespace 中为“default”Service Account 提供一个 Role

kubectl create clusterrolebinding add-on-cluster-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:default

3、为 Namespace 中所有 Service Account 提供 Role

kubectl create rolebinding serviceaccounts-view \
  --clusterrole=view \
  --group=system:serviceaccounts:my-namespace \
  --namespace=my-namespace

4、为所有 Service Account 授予 Role(不推荐)

kubectl create clusterrolebinding serviceaccounts-view \
  --clusterrole=view \
  --group=system:serviceaccounts

5、授予超级用户权限对所有 Service Account(强烈反对)

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

# 从 1.5 版本升级

在 k8s 1.6 之前,许多部署使用的 ABAC 策略,像有对 Service Account 授予全部的 API 访问权限。

默认 RBAC 策略限定的权限授予范围有 control-plane 组件、nodes 和 controllers,不会向“kube-system”Namespace 之外的 Service Account 授予权限。

虽然安全性更高,但这可能应权限问题影响到某些工作负载。以下是管理两种权限的方法:

# Parallel Authorizers

一起运行 RBAC 和 ABAC 授权(并包括旧版 ABAC 策略):

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

RBAC 授权器将首先尝试对请求授权,如果 API 请求被拒绝,那么将进行 ABAC 授权。

可以在 apiserver(以 2(-v=2)或更高的日志级别运行)的日志中看到 RBAC 授权被拒绝信息,使用该日志信息可以查看哪些 Roles 需要被授予哪些 users, groups, 或 service accounts。如果向 service accounts 授予 Roles,并且在服务器日志中查看到没有 RBAC 被拒绝的工作负载消息的时,则可以删除 ABAC 授权器。

# Permissive RBAC Permissions

可以使用 RBAC role bindings 复制一个宽泛的策略。

警告:下面的策略允许所有 Service Account 充当集群管理员。在容器中运行的任何应用程序都会自动接收 service account credentials,并且可以对 API 执行任何操作,包括查看 secrets、修改权限。默认不推荐使用。

kubectl create clusterrolebinding permissive-binding \
  --clusterrole=cluster-admin \
  --user=admin \
  --user=kubelet \
  --group=system:serviceaccounts
Last Updated: 4/15/2023, 8:33:17 PM