rbac 访问控制

基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。RBAC 鉴权机制使用 rbac.authorization.k8s.io API 组来驱动鉴权决定, 允许你通过 Kubernetes API 动态配置策略。

要启用 RBAC,在启动 API 服务器时将 --authorization-mode 参数设置为一个逗号分隔的列表并确保其中包含 RBAC。

API Server

目前支持以下几种授权策略:

  • AlwaysDeny:表示拒绝所有请求,一般用于测试。
  • AlwaysAllow:允许接收所有请求。如果集群不需要授权流程,则可以采用该策略,这也是Kubernetes的默认配置。
  • ABAC(Attribute-Based Access Control):基于属性的访问控制。表示使用用户配置的授权规则对用户请求进行匹配和控制。
  • Webhook:通过调用外部REST服务对用户进行授权。
  • RBAC:Role-Based Access Control,基于角色的访问控制(本章讲解)。
  • Node:是一种专用模式,用于对kubelet发出的请求进行访问控制。

rbac-k8s
在RABC API中,通过如下的步骤进行授权:

  • 定义角色:在定义角色时会指定此角色对于资源的访问控制的规则。
  • 绑定角色:将主体与角色进行绑定,对用户进行访问授权。

角色

  • Role:授权特定命名空间的访问权限
  • ClusterRole:授权所有命名空间的访问权限

角色绑定

  • RoleBinding:将角色绑定到主体(即subject)
  • ClusterRoleBinding:将集群角色绑定到主体

主体(subject)

  • User:用户
  • Group:用户组
  • ServiceAccount:服务账号

Role 与 ClusterRole

在 RBAC API 中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有” 否定” 的规则)。 角色可以由命名空间(namespace)内的 Role 对象定义,而整个 Kubernetes 集群范围内有效的角色则通过 ClusterRole 对象实现。

Role 创建角色

一个 Role 对象只能用于授予对某一单一命名空间中资源的访问权限。 以下示例描述了”default” 命名空间中的一个 Role 对象的定义,用于授予对 pod 的读访问权限:
创建一个role.yaml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # 空字符串"" 表明使用 core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

执行

kubectl apply -f role.yaml
kubectl get role -n default
kubectl describe role pod-role -n default

ClusterRole 创建角色

创建一个ClusterRole.yaml

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-clusterrole
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

执行

kubectl apply -f ClusterRole.yaml
kubectl get clusterrole pod-clusterrole
kubectl describe clusterrole pod-clusterrole

参数

1、Role、ClsuterRole Verbs可配置参数

"get", "list", "watch", "create", "update", "patch", "delete", "exec"

2、Role、ClsuterRole Resource可配置参数

"services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"

3、Role、ClsuterRole APIGroup可配置参数

"","apps", "autoscaling", "batch"

RoleBinding 和 ClusterRoleBinding

角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干主体(Subject)(用户、组或服务账户)的列表和对这些主体所获得的角色的引用。 RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。

一个 RoleBinding 可以引用同一的名字空间中的任何 Role。 或者,一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。 如果你希望将某 ClusterRole 绑定到集群中所有名字空间,你要使用 ClusterRoleBinding。

RoleBinding 角色绑定

下面的例子中的 RoleBinding 将 "pod-reader" Role 授予在 "default" 名字空间中的用户 "jane"。 这样,用户 "jane" 就具有了读取 "default" 名字空间中所有 Pod 的权限。
创建 RoleBinding,yaml

apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pod
# 你需要在该名字空间中有一个名为 “pod-reader” 的 Role
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
# 你可以指定不止一个“subject(主体)”
- kind: User
  name: jane # "name" 是区分大小写的
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
  kind: Role        # 此字段必须是 Role 或 ClusterRole
  name: pod-reader  # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
  apiGroup: rbac.authorization.k8s.io

执行

kubectl apply -f RoleBinding.yaml
kubectl get RoleBinding
kubectl describe RoleBinding rb

ClusterRoleBinding 角色绑定

要跨整个集群完成访问权限的授予,你可以使用一个 ClusterRoleBinding。 下面的 ClusterRoleBinding 允许 "manager" 组内的所有用户访问任何名字空间中的 Secret。
创建ClusterRoleBinding.yaml

apiVersion: rbac.authorization.k8s.io/v1
# 此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 Secret 资源
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager      # 'name' 是区分大小写的
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

执行

kubectl apply -f ClusterRoleBinding.yaml
kubectl get ClusterRoleBinding crb
kubectl describe ClusterRoleBinding crb

命令行

kubectl create role

创建 Role 对象,定义在某一名字空间中的权限。例如:

  • 创建名称为 “pod-reader” 的 Role 对象,允许用户对 Pods 执行 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 对象,使其具有对特定名称的资源执行 get/update 的权限:
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 对象,允许用户对 Pods 对象执行 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-permissions,则可以删除多余的主体。

例如:

  • 测试应用 RBAC 对象的清单文件,显示将要进行的更改:
kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client
  • 应用 RBAC 对象的清单文件,保留角色(roles)中的额外权限和绑定(bindings)中的其他主体:
kubectl auth reconcile -f my-rbac-rules.yaml
  • 应用 RBAC 对象的清单文件,删除角色(roles)中的额外权限和绑定中的其他主体:
kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions

服务账户权限

默认的 RBAC 策略为控制面组件、节点和控制器授予权限。 但是不会对 kube-system 名字空间之外的服务账户授予权限。 (除了授予所有已认证用户的发现权限)

这使得你可以根据需要向特定 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” 服务账户运行。 要允许这些插件组件以超级用户权限运行,需要将集群的 cluster-admin 权限授予 kube-system 名字空间中的 “default” 服务账户。

注意:启用这一配置意味着在 kube-system 名字空间中包含以超级用户账号来访问集群 API 的 Secret。

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
Last Updated:
Contributors: jobcher