RBAC概述

  • DAC(自主访问控制)、MAC(强制访问控制)、RBAC(基于角色的访问控制)和ABAC(基于属性的访问控制)这四种主流的权限管理模型中,kubernetes支持使用后两种完成普通账户和服务账户的权限管理,另外支持的权限管理模型还有Node和Webhook两种
  • RBAC(Role-Based Access Control)是一种新型、灵活且使用广泛的访问控制机制,它将权限授予角色,通过让”用户”扮演一到多个”角色”完成灵活的权限管理,这有别于传统访问控制机制中将权限直接赋予使用者的方式。相对于kubernetes支持的ABAC和webhook等授权机制,RBAC具有如下优势
    • 对集群中的资源和非资源型URL的权限实现了完整覆盖
    • 整个RBAC完全由少数几个API对象实现,而且与其他API对象一样可以用kubelet或API调用操作
    • 支持权限的运行时跳转,无需重新启动API Server
  • kuberenets自1.5版本起引入了RBAC,1.6版本中将其升级为beta级别,并成为kubeadm部署集群时的默认选项。而后,直到1.8版本它才正式升级为stable级别
  • 在RBAC中,用户(User)就是一个可以独立访问计算机系统中的数据或者用数据表示的其他资源的主体(Subject)。角色是指一个组织或任务中的工作或位置,它代表了一种权利、资格和责任。许可(Permission)就是允许对一个或多个客体(Object)执行的操作。一个用户可经授权而拥有多个角色,一个角色可以由多个用户构成;每个用户可以拥有多种许可,每个许可也可以授权给多个不同的角色。每个操作可施加于多个客体(受控对象),每个客体也可以接收多个操作

RBAC授权插件

  • RBAC是一种特定的权限管理模型,它把可以施加在”资源对象”上的”动作”称为”许可权限,这些许可权限能够按需组合在一起构建出”角色”及其只能,并通过为”用户账户或组账户”分配一到多个角色完成权限委派。这些能够发出动作的用户在RBAC中也称为”主体”
  • 如其名所示,RBAC的基于”角色”这一核心组件实现了权限指派,它为账号赋予一到多个角色从而让其具有角色之上的权限,其中的账号可以是用户账户、用户组、服务账号及其相关的组等,而同时关联至多个角色的账号所拥有的权限是多个角色之上的权限集合。下图展示了RBAC中用户、角色与权限直接的关系
    kubernetes-安全-RBAC基于角色的访问控制 - 图1
  • RBAC访问控制模型中,授权操作只能通过角色完成,主体只有在分配到角色之后才能行驶权限,且仅限于其绑定的各角色之上继承而来的权限。换句话说,用户的权限仅能够通过角色分配获得,未能得到显式角色委派的用户则不具有任何权限
  • 简单来说,RBAC是一种操作授权机制,它以角色为中心用于界定”谁”(Subject)能够”操作”(verb)哪个或哪类”对象”(object)。动作的发出者即为”主体”,通常以”账号”为载体,在kubernetes系统上,它可以是普通账户,也可以是服务账户。”操作”用于表名要执行的具体操作,既PUT、POST、DELETE和GET等请求方法,而”对象”则是指管理操作能够施加的目标实体,对kubernetes API 来说主要指各类资源对象以及非资源型URL
  • API Server是RESTful风格的API,各类客户端基于HTTP的请求报文(首部)发送身份认证信息并由认证插件完成身份验证。而后通过HTTP协议的请求方法指定对目标对象的操作请求,并由授权插件进行授权检查,而操作的对象则是URL路径指定的REST资源。下图给出了HTTP Verb和kubernetes API Server verb的对应关系
    kubernetes-安全-RBAC基于角色的访问控制 - 图2
  • kubernetes系统上的普通账户或服务账户向API Server发起资源请求操作,并以相应的HTTP方法加载,由运行在API Server上的授权插件RBAC进行鉴权负责确定某账号是否有权限对目标资源发起指定的操作,他们都属于”许可(Permission)”类型的授权,不存在任何”拒绝权限”。如下图所示
    kubernetes-安全-RBAC基于角色的访问控制 - 图3
  • kubernetes系统的RBAC授权插件将角色分为Role和ClusterRole两类,它们都是kubernetes内置支持的API资源类型,其中Role作用于名称空间级别,用于承载名称空间内的资源权限集合,而ClusterRole则能够同时承载名称空间和集群级别的资源权限集合。Role无法承载集群级别的资源类型的操作权限。一般来说,ClusteRole的许可授权作用于整个集群,因此常用于控制Role无法生效的资源类型,这类的资源包括集群级别的资源(例如Node)、非资源类型的端点(例如/healthz)以及作用于所有名称空间的资源(例如跨名称空间获取任何资源的权限)等。
  • 利用Role和ClusterRole两类角色进行赋权时,需要用到另外两种资源Rolebinding和ClusterRolebinding,它们同样是由API Server内置支持的资源类型。Rolebinding用于将Role绑定到一个或一组用户上,它隶属于且仅能作用于其所在的单个名称空间。Rolebinding可以引用同一名称中的Role,也可以引用集群别的ClusterRole,但引用ClusterRole的许可权限会降级只能在Rolebinding所在的名称空间生效。而ClusterRoleBinding则用于将ClusterRole绑定到用户或组,它作用于集群全局,且仅能够引用ClusterRole。四者之间的关系如下图所示:
    kubernetes-安全-RBAC基于角色的访问控制 - 图4
  • 一个名称空间中科院包含多个Role和Rolebinding对象,类似的,集群级别也可以同时存在多个ClusterRole和ClusterRoleBinding对象。而一个账户也可以由Rolebinding或者clusterrolebinding关联至多个角色,从而具有多重许可授权
  • 上图中,全局作用范围的USer2因通过A名称空间中的Rolebinding关联至Role-A上,因而它仅能在NamespaceA名称空间中发挥作用。名称空间B中的ServiceAccount1通过Rolebinding关联至集群级别的ClusterRole-M上,对该账户来说,ClusterRole-M上的操作权限也仅限于该名称空间。全局级别的用户user1通过clusterrolebinding关联到clusterrole-M,因而,该用户将在集群级别行使该角色的权限
  • 通常,我们可以把kubernetes集群用户大体规划为集群管理员、名称空间管理员和用户(通常为开发人员)3类
    • 集群管理员可以创建,读取,更新和删除任何资源对象,能够创建命名空间并将其分配个名称空间管理员;此角色适用于在整个集群中管理所有租户或项目的管理员
    • 名称空间管理员可以管理其名称空间中的用户,此角色适用于特定单一租户或项目的管理员
    • 开发者可以创建、读取、更新和删除名称空间内的非策略对象,如Pod、Job和Ingress等,但只在他们有权访问的名称空间中拥有这些权限
  • 另外,有些特殊的应用程序可能还会需要一些比较特殊的权限集合,例如集群或名称空间级别的只读权限等,我们可以在必要时按需定义这些较为特别的角色

Role与ClusterRole

role

  • 如前所述,Role和ClusterRole是API Server内置的两种资源类型,它们在本质上都只是一组许可权限的集合。Role和ClusterRole的资源规范完全相同,该规范没有使用spec字段,而是直接使用rules字段嵌套授权规则列表。规则的基本要素是操作(verb)和相关的目标资源,后者支持指定一个或多个资源类型、特定资源类型下的单个或多个具体的资源,以及非资源类型的URL等。在Role和ClusterRole资源上定义的rules也成为Policy,即策略规则,它可以内嵌的字段有如下几个
    • apiGroups: <[]string>:目标资源的API群组名称,支持列表格式指定多个组,空值(“”)表示核心群组
    • resources: <[]string>: 规则应用的目标资源类型,例如pods、service、deployments和daemonsets等,未同时使用resourceNames字段时,表示指定类型下的所有资源。ResourceAll表示所有资源
    • ResourceNames: <[]string>: 可选字段,指定操作使用的具体目标资源名称
    • nonResourceURLs: <[]string>: 用于定义用户有权限访问的网址列表,它并非名称空间级别的资源,因此只能应用于clusterrole,role支持此字段仅是为了格式上的兼容;该字段在一条规则中与resource和resourceNames互斥
    • verbs: <[]string>:可应用在此规则匹配到的所有资源类型的操作列表,,可用选项有get、list、create、update、patch、watch、proxy、redirect、delete和deletecollection;此字段为必选字段
  • 下面的配置清单示例(pod-reader-rbac.yaml)在default名称空间中定义了一个名称为Role的资源,它设定了读取,列出及监视pods和service资源,以及pods/log子资源的许可权限,清单配置完成之后使用kubectl apply -f将其创建到集群之上
  1. kind: Role
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. metadata:
  4. namespace: default
  5. name: pods-reader
  6. rules:
  7. - apiGroups: [""]
  8. resources: ["pods","services","pods/log"]
  9. verbs: ["get","list","watch"]
  • 绝大多数资源可以通过其资源类型的名称引用,例如pods或services等,这些名称与他们在API endpoint中的形式相同。另外,有些资源类型也支持子资源,例如pod对象的/log,Node对象的/status等,他们在API Server上的URL格式通常如下所表示
  1. GET /api /vl /namespaces/{namespace}/pods/{name}/log
  • 在RBAC角色定义中,如果需要引用这种类型的子资源,则需要使用resource/subresource的格式,例如上面示例中的pods/log。另外,还可以通过直接给定资源名称(resourceName)来引用特定的资源,但此时仅支持get、delete、update和patch等,也可以使用这四个操作的子集实现更小范围的可用操作限制。
  • 除了使用资源清单创建Role资源之外,还可以直接使用kubectl crate role命令进行快速创建,不过也是推荐使用资源清单的方式创建

ClusterRole

  • ClusterRole属于集群级别的资源,它引用名称空间级别的资源意味着相关的操作权限能够在所有名称空间生效,同时,它能够引用Role所不支持的集群级别的资源类型,例如nodes和persistentvolumes等。下面的清单示例(nodes-admin-rbac.yaml)定义了ClusterRole资源nodes-admin,它拥有管理集群节点信息的权限。clusterrole不属于名称空间,所以其配置不能够使用metadata.namespace字段,清单配置完成之后使用kubectl apply -f将其创建到集群之上
  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. name: nodes-admin
  5. rules:
  6. - apiGroups: [""]
  7. resources: ["nodes"]
  8. verbs: [""]
  • role或clusterrole资源的详细描述能够以比较直观的方式打印相关的规则定义。使用kubectl describe roles/pods-readerkubectl describe clusterrole/nodes-admin打印出相关的规则定义
  1. [root@kube-master-01 rbac]# kubectl describe role/pods-reader
  2. Name: pods-reader
  3. Labels: <none>
  4. Annotations: <none>
  5. PolicyRule:
  6. Resources Non-Resource URLs Resource Names Verbs
  7. --------- ----------------- -------------- -----
  8. pods/log [] [] [get list watch]
  9. pods [] [] [get list watch]
  10. services [] [] [get list watch]
  11. [root@kube-master-01 rbac]#
  12. [root@kube-master-01 rbac]# kubectl describe clusterrole/nodes-admin
  13. Name: nodes-admin
  14. Labels: <none>
  15. Annotations: <none>
  16. PolicyRule:
  17. Resources Non-Resource URLs Resource Names Verbs
  18. --------- ----------------- -------------- -----
  19. nodes [] [] []
  20. [root@kube-master-01 rbac]#
  • 另外,kubectl命令也分别提供了创建role和clusterrole资源的命令create role和create clusterrole,它们支持如下几个关键选项
    • —verb: 指定可施加于目标资源的动作,支持以逗号分隔的列表值,也支持重复使用该选项分别指定不同动作,例如--verb=get,list,watch或者--verb=get --verb=list --verb=watch
    • —resource: 指定目标资源类型,使用格式类似于—verb
    • — resource-name: 指定目标资源,使用格式类似于—verb
    • —non-resource-url: 指定非资源类型的URL,使用格式类似于—verb,但仅适用于clusterrole资源
  • 例如,下面的第一条命令创建了dev名称空间,第二条命令在该名称空间创建了一个具有资源管理权限的roles/admin资源,第三条命令则创建了一个有PVC和PV资源管理权限的cluserroles/pv-admin资源
  1. [root@kube-master-01 rbac]# kubectl create namespace dev
  2. namespace/dev created
  3. [root@kube-master-01 rbac]#
  4. [root@kube-master-01 rbac]# kubectl create role admin -n dev \
  5. > --resource="*.*" \
  6. > --verb="get,list,watch,create,delete,update,deletecollection,patch"
  7. role.rbac.authorization.k8s.io/admin created
  8. [root@kube-master-01 rbac]#
  9. [root@kube-master-01 rbac]# kubectl create clusterrole pv-admin --verb="*" --resource="persistentvolumeclaims,persistentvolumes"
  10. clusterrole.rbac.authorization.k8s.io/pv-admin created
  11. [root@kube-master-01 rbac]#
  • 但是,role或clusterrole对象本身并不能作为动作的执行主体,它们需要”绑定”到主体(例如User、Group或Service Account)之上完成赋权,而后由相应主体执行资源操作

RoleBinding和ClusterRoleBinding

  • RoleBinding负责在客户端名称空间级别向普通用户、服务账户或组分配Role或ClusterRole,而ClusterRolebinding则只能用于在集群级别分配ClusterRole。但二者的配置规范格式完全相同。它们都没有spec字段,直接使用subjects和roleRef两个嵌套的字段。其中,subjects的值是一个对象列表,用于给出要绑定的主体,而roleRef的值是单个对象,用于指定要绑定的role或clusterrole资源。subjects字段的可嵌套字段如下:
    • apiGroups: <string>:要引用的主体所属的API群组,对于ServiceAccount类的主体来说默认为””,而User和Group类主体的默认值为rbac.authorization.k8s.io
    • kind: <string>:要引用的资源对象(主体)所属的类别,可用值为User、Group和ServcieAccount,必选字段
    • name: <string>: 引用的主体的名称,必选字段
    • namespace: <string>: 引用的主体所属的名称空间,对于非名称空间类型的主体,例如User和Group,其值必须为空,否则授权插件将返回错误信息
  • roleRef的可嵌套字段如下
    • apiGroup: <string>: 引用的资源(Role或ClusterRole)所属的API群组,必选字段
    • kind: <string>: 引用的资源所属的类别,可用值为Role或ClusterRole,必选字段
    • name: <string>: 引用的资源(Role或ClusterRole)的名称
  • RoleBinding是名称空间级别的资源
  • 需要注意的是,Rolebinding仅能够引用同一名称空间中的Role资源,例如下面配置清单中的RoleBindings在kube-ops名称空间中新建一个admin角色并且将权限分配该角色,然后使用rolebinding将该角色绑定到集群用户kube-user上,从而kube-user拥有了此角色之上的所有许可权限
  1. --- #在kube-ops名称空间创建admin的角色,该角色的权限能够操作及访问kube-ops名称空间下的pods,service,pods/log资源
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: Role
  4. metadata:
  5. namespace: kube-ops
  6. name: admin
  7. rules:
  8. - apiGroups: [""]
  9. resources: ["pods","services","pods/log"]
  10. verbs: ["get","list","watch","delete","update","deletecollection","patch"]
  11. --- #将kube-ops名称空间下的admin角色绑定到kube-user用户上,使kube-user用户能够访问到kube-ops名称空间下的所有资源
  12. apiVersion: rbac.authorization.k8s.io/v1
  13. kind: RoleBinding
  14. metadata:
  15. name: kube-user-admin
  16. namespace: kube-ops
  17. subjects:
  18. - kind: User
  19. name: kube-user
  20. apiGroup: rbac.authorization.k8s.io
  21. roleRef:
  22. kind: Role
  23. name: admin
  24. apiGroup: rbac.authorization.k8s.io
  • 将上面的RoleBinding资源kube-user-admin创建到集群上,便能够以该用户的身份测试及其继承而来的权限是否生效
  • 使用kubectl config use-context命令将用户切换到kube-user,或者直接使用--contex=kube-user@kubernetes选项指定上下文。然后通过执行结果可以很明显的看到kube-user已经具备了kube-ops名称空间资源的操作权限
  1. [root@kube-master-01 data]# kubectl get pods -n kube-ops --context=kube-user@kubernetes
  2. NAME READY STATUS RESTARTS AGE
  3. alertmanager-778644d955-4j57d 1/1 Running 0 14d
  4. blackbox-exporter-6cf54f4d98-5vtzz 1/1 Running 0 13d
  5. blackbox-exporter-6cf54f4d98-ngcts 1/1 Running 0 13d
  6. blackbox-exporter-6cf54f4d98-vhvn8 1/1 Running 0 13d
  7. grafana-57df885c4-jr8h2 1/1 Running 0 15d
  8. node-exporter-24dmf 1/1 Running 0 14d
  9. node-exporter-dd92q 1/1 Running 2 14d
  10. node-exporter-ghxvb 1/1 Running 0 14d
  11. node-exporter-ww8xt 1/1 Running 7 14d
  12. node-exporter-xk5nd 1/1 Running 0 14d
  13. prometheus-76fb655799-smkv5 2/2 Running 0 14d
  14. [root@kube-master-01 data]#
  15. [root@kube-master-01 data]# kubectl delete pods/blackbox-exporter-6cf54f4d98-5vtzz -n kube-ops --context=kube-user@kubernetes
  16. pod "blackbox-exporter-6cf54f4d98-5vtzz" deleted
  17. [root@kube-master-01 data]#
  18. [root@kube-master-01 data]# kubectl get pods --context=kube-user@kubernetes
  19. Error from server (Forbidden): pods is forbidden: User "kube-user" cannot list resource "pods" in API group "" in the namespace "default"
  20. [root@kube-master-01 data]#
  • RoleBinding也能够为主体分配集群角色,但它仅能赋予主体访问RoleBinding资源本身所在的名称空间之内的,由ClusterRole所持有的权限。例如,对于具有PVC和PV管理权限的clusterrole/pv-admin来说,在kube-ops名称空间中使用Rolebinding将其分配给用户kube-user,意味着kube-user仅对kube-ops名称空间下的PVC资源具有管理权限,它无法继承clusterrole/pv-admin除kube-ops名称空间之外的其他名称空间中的PVC管理权限,更不能继承集群级别资源PV的任何权限
  • 一种高效分配权限的做法是,由集群管理员在集群范围预先定义好一组具有名称空间级别资源的ClusterRole资源,而后由RoleBinding分别在不同名称空间中引用它们,从而在多个名称空间向不同用户授予Rolebinding所有名称空间下的相同权限。
  • 由此可见,Role和RoleBinding是名称空间级别的资源,它们仅能用于完成单个名称空间内的访问控制,需要赋予某个主体多个名称空间中的访问权限时就不得不在各个名称空间分别进行。若需要完成集群全局的资源管理授权,或者希望资源操作能够针对Node、Namepsaces和PersistentVolumes等集群级别的资源进行,就需要使用ClusterRoleBinding
  • 值得注意的是,nonResourceURLs资源仅支持get访问权限
  • 下面的配置清单示例(rolebinding-and-clusterrolebinding-rbac.yaml)中,rolebinding/kube-user-pv-admin资源位于kube-ops名称空间,它使用RoleBinding为用户kube-user分配了pv-admin这一集群角色,而clusterrolebinding/ilinux-pv-admin隶属于集群级别,它使用ClusterRoleBinding为ilinux分类pv-admin这一集群级别的管理权限
  1. #创建一个集群级别的角色pv-admin
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: ClusterRole
  4. metadata:
  5. name: pv-admin
  6. rules:
  7. - apiGroups: [""]
  8. resources: ["persistentvolumeclaims","persistentvolumes"]
  9. verbs: ["*"]
  10. ---
  11. #将该角色绑定到只能访问kube-ops名称空间的kube-user用户上
  12. apiVersion: rbac.authorization.k8s.io/v1
  13. kind: RoleBinding
  14. metadata:
  15. namespace: kube-ops
  16. name: kube-user-pv-admin
  17. subjects:
  18. - kind: User
  19. name: kube-user
  20. apiGroup: rbac.authorization.k8s.io
  21. roleRef:
  22. kind: ClusterRole
  23. name: pv-admin
  24. apiGroup: rbac.authorization.k8s.io
  25. ---
  26. #再将该集群角色绑定到集群用户ilinux之上,使ilinux用户能够访问所有名称空间的pv和pvc
  27. apiVersion: rbac.authorization.k8s.io/v1
  28. kind: ClusterRoleBinding
  29. metadata:
  30. name: ik8s-pv-admin
  31. subjects:
  32. - kind: User
  33. name: ilinux
  34. apiGroup: rbac.authorization.k8s.io
  35. roleRef:
  36. kind: ClusterRole
  37. name: pv-admin
  38. apiGroup: rbac.authorization.k8s.io
  • 将上面的示例创建到集群之上
  1. [root@jenkins rbac]# kubectl apply -f rolebinding-and-clusterrolebinding-rbac.yaml
  2. clusterrole.rbac.authorization.k8s.io/pv-admin created
  3. rolebinding.rbac.authorization.k8s.io/kube-user-pv-admin created
  4. clusterrolebinding.rbac.authorization.k8s.io/ik8s-pv-admin created
  5. [root@jenkins rbac]#
  • 首先,我们使用kube-user用户进行测试,因为刚刚的授权规则里面,我们是使用RoleBinding将其绑定到kube-ops名称空间,所以正常情况下它只能访问kube-ops名称空间下的PVC,而无法访问集群级别的pv资源,且无法通过RoleBinding从cluterRole/pv-admin继承指定名称空间之外的任何权限
  1. [root@jenkins rbac]# kubectl get pv,pvc -n kube-ops --context=kube-user@kubernetes
  2. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
  3. glusterfs-alertmanager-data Bound pvc-0e9918b4-4743-4fbc-a12b-dbde55c2beb4 5Gi RWX glusterfs 15d
  4. glusterfs-grafana-data Bound pvc-dd329273-657a-48ad-be43-d62d65f51826 20Gi RWX glusterfs 15d
  5. glusterfs-prometheus-data Bound pvc-965c1363-69e2-4746-9c29-6b813cfa8fea 20Gi RWX glusterfs 15d
  6. Error from server (Forbidden): persistentvolumes is forbidden: User "kube-user" cannot list resource "persistentvolumes" in API group "" at the cluster scope
  7. [root@jenkins rbac]#
  8. [root@jenkins rbac]# kubectl get pv,pvc -n default --context=kube-user@kubernetes
  9. Error from server (Forbidden): persistentvolumes is forbidden: User "kube-user" cannot list resource "persistentvolumes" in API group "" at the cluster scope
  10. Error from server (Forbidden): persistentvolumeclaims is forbidden: User "kube-user" cannot list resource "persistentvolumeclaims" in API group "" in the namespace "default"
  11. [root@jenkins rbac]#
  • 再使用ilinux用户进行测试,它通过ClusterRoleBinding从clusterroles/pv-admin继承了该集群角色的所有授权,如下面的命令及结果所显示
  1. [root@jenkins rbac]# kubectl get pv,pvc -n kube-ops --context=ilinux@kube-dev
  2. NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
  3. persistentvolume/pvc-0e9918b4-4743-4fbc-a12b-dbde55c2beb4 5Gi RWX Delete Bound kube-ops/glusterfs-alertmanager-data glusterfs 15d
  4. persistentvolume/pvc-965c1363-69e2-4746-9c29-6b813cfa8fea 20Gi RWX Delete Bound kube-ops/glusterfs-prometheus-data glusterfs 15d
  5. persistentvolume/pvc-dd329273-657a-48ad-be43-d62d65f51826 20Gi RWX Delete Bound kube-ops/glusterfs-grafana-data glusterfs 15d
  6. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
  7. persistentvolumeclaim/glusterfs-alertmanager-data Bound pvc-0e9918b4-4743-4fbc-a12b-dbde55c2beb4 5Gi RWX glusterfs 15d
  8. persistentvolumeclaim/glusterfs-grafana-data Bound pvc-dd329273-657a-48ad-be43-d62d65f51826 20Gi RWX glusterfs 15d
  9. persistentvolumeclaim/glusterfs-prometheus-data Bound pvc-965c1363-69e2-4746-9c29-6b813cfa8fea 20Gi RWX glusterfs 15d
  10. [root@jenkins rbac]#
  • 另外,kubectl也提供了分别创建Rolebinding和ClusterRolebinding资源的格式命令kubectl create rolebindingkubectl create clusterrolebinding。具体的这里就不演示了,因为我们更习惯的还是使用资源清单的方式进行创建

聚合型ClusterRole

  • kubernetes自1.9版本开始支持clusterrole的rules字段中嵌套aggregationRuels字段来整合其他ClusterRole资源的规则,这种类型的ClusterRole对象的实际可用权限受控于控制器,具体许可授权由所有被标签选择器匹配到的ClusterRole的聚合授权规则合并生成
  • 下面的配置清单中首先定义了两个拥有标签的集群角色global-resources-viewglobal-resources-eidt,而后在第三个集群角色资源global-resources-admin上使用聚合规则的标签选择器来匹配前两个资源的标签,因此,集群角色global-resources-admin的权限将由匹配到的其他ClusterRole资源的规则列表自动聚合而成。
  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. name: global-resources-view
  5. labels:
  6. rbac.ilinux.io/aggregate-to-global-resource-admin: "true"
  7. rules:
  8. - apiGroups: [""]
  9. resources:
  10. - nodes
  11. - namespaces
  12. - persistentvolumes
  13. - clusterroles
  14. verbs:
  15. - get
  16. - list
  17. - watch
  18. ---
  19. apiVersion: rbac.authorization.k8s.io/v1
  20. kind: ClusterRole
  21. metadata:
  22. name: global-resource-edit
  23. labels:
  24. rbac.ilinux.io/aggregate-to-global-resource-admin: "true"
  25. rules:
  26. - apiGroups: [""]
  27. resources:
  28. - nodes
  29. - namespaces
  30. - persistentvolumes
  31. - clusterroles
  32. verbs:
  33. - create
  34. - delete
  35. - deletecollection
  36. - path
  37. - update
  38. ---
  39. apiVersion: rbac.authorization.k8s.io/v1
  40. kind: ClusterRole
  41. metadata:
  42. name: global-resource-admin
  43. aggregationRule:
  44. clusterRoleSelectors:
  45. - matchLabels:
  46. rbac.ilinux.io/aggregate-to-global-resource-admin: "true"
  47. rules: [] #该规则列表为空,它将由控制器自动聚合生成
  • 任何能够被示例中clusterrole/global-resources-admin资源的标签选择器匹配到的clusterrole资源的相关规则将一同合并为它的授权规则,并且相关作用域内的任何ClusterRole资源的变动都将实时反馈到聚合资源之上。因而,聚合型ClusterRole的规则会随着标签选择器的匹配结果动态变化。
  • 事实上,kubernetes系统上面向用户的内置ClusterRole admin和edit也是聚合型的ClusterRole对象,因为这可以使得默认角色中包含自定义资源的相关规则,例如由CustomResourceDefinitions或Aggregated API服务器提供的规则等

面向用户的内置ClusterRole

  • API Server内置了一组默认的ClusterRole和ClusterRoleBinding资源预留给系统使用,其中大多数都以system:为前缀。另外还有一些不以system:为前缀的默认的ClusterRole资源是为面向用户的需求而设计,包括集群管理员角色cluster-admin,以及专用于授予特定名称空间级别权限的集群角色admin、edit和view。如下图所示。掌握这些默认的内置ClusterRole资源有助于按需创建用户并分配相应权限。

    kubernetes-安全-RBAC基于角色的访问控制 - 图5

  • 内置的clusterroles/cluster-admin角色拥有管理集群所有资源的权限,而内置的clusterrolebinding/cluster-admin将该角色分配给了system:masters用户组,这意味着所有隶属于该组的用户都将自动具有集群的超级管理权限。kubeadmin安装设置集群时,自动创建的配置文件/etc/kubernetes/admin.conf种定义的用户kubernetes-admin使用证书文件/etc/kubernetes/pki/apiserver-kubelet-client.crt向API Server进行验证。而该数字证书的Subject属性值为/O=system:masters,API Server会在成功验证该用户的身份之后将其识别为system:masters用户组的成员

  1. [root@kube-master-01 pki]# openssl x509 -in /etc/kubernetes/pki/apiserver-kubelet-client.crt -noout -subject
  2. subject= /O=system:masters/CN=kube-apiserver-kubelet-client
  3. [root@kube-master-01 pki]#
  • 于是,为kubernetes集群自定义超级管理员的方式至少有两种:
    • 将用户归入system:masters组
    • 通过ClusterRoleBinding直接将用户绑定至内置的集群角色cluster-admin之上。具体的实现方式与之前的授权方式一样
  • 另外,在多租户,多项目或多环节等使用场景中,用户通常应该获得名称空间级别绝大多数资源的管理(admin)、只读(view)或编辑(edit)权限,可通过在指定的名称空间种创建RoleBinding资源引用内置的ClusterRole资源进行这类权限的快速授予。例如,在名称空间kube-ops种创建一个RoleBinding资源,为ilinux用户分配集群角色admin,将使得该用户具有管理kube-ops名称空间种除了名称空间本身及资源配额之外的所有资源权限
  • 另外,API Server默认创建的以system:为前缀的大多数clusterrole和ClusterRoleBinding是专为kubernetes系统的基础架构而设计,修改这些资源可能会导致集群功能不正常。例如,若修改了为kubelet赋权的system:node将会导致kubelet无法正常工作。所有默认的clusterrole和clusterrolebinding都打上了kubernetes.io/bootstrapping=rbac-defaults标签。
  • 每次启动时,API Server都会自动为所有默认的ClusterRole重新赋予缺失的权限,同时为默认的ClusterRoleBinding绑定缺失的主体。这种机制给了集群从意外中修改自动恢复的能力,以及升级版本后自动将clusterrole和ClusterRoleBinding升级到满足新版本需求的能力
  • 必要时,在默认的clusterrole或clusterrolebinding上设置annotation中的rbac.authorization.kubernetes.io/autoupdate属性的值为false,即可禁止这种自动恢复的功能
  • 另外,启用RBAC后,kubernetes系统的各个核心组件,附加组件,以及由controller-manager运行的核心控制器等,几乎都需要依赖于合理的授权才能正常运行。因而,RBAC授权模型为这些组件内置了可获得最小化的资源访问授权的clusterrile和clusterrolebinding,例如,system:kube-scheduler、system:kube-controller-manager、system:node、system:node-proxier和system:kube-dns等,其中大多数组件都可以做到见名知意思。

演示

创一个新的kubernetes集群管理员账号

  • 为kubernetes再创建一个基于X509证书认证的集群账号,此账号需要拥有所有资源管理权限,并且默认需要使用此账号来管理kubernetes集群
  • 并且新生成一个kubeconfig配置文件
  • 此步骤需要在master节点上执行

生成私钥文件

  • 新集群管理员账号: kubernetes-cluster-admin
  • 之前有讲到过,创建一个新的集群超级管理员账号有两种方式,第一种是将用户归入system:masters组,第二种是通过clusterrolebinding直接将用户绑定至集群内置的角色cluster-admin之上。这里我们使用第二种方式
  • 以客户端的身份,生成目标账户kubernetes-cluster-admin的私钥,保存在默认的/etc/kubernetes/pki目录中
  • 私钥文件权限设置为600防止其他用户读取
  1. [root@kube-master-01 pki]# (umask 077; openssl genrsa -out kubernetes-cluster-admin.key 2048)
  2. Generating RSA private key, 2048 bit long modulus
  3. .................................................+++
  4. ...............................................................+++
  5. e is 65537 (0x10001)
  6. [root@kube-master-01 pki]#

创建证书签署请求

  • -subj选项中的CN的值会被kube-apiserver识别为用户名,并且在kubeconfig文件中作为用户名使用,O的值则会被识别为用户组
  1. [root@kube-master-01 pki]# openssl req -new -key kubernetes-cluster-admin.key -out kubernetes-cluster-admin.csr -subj "/CN=kubernetes-cluster-admin/O=admin"
  2. [root@kube-master-01 pki]#

签署证书

  • kubernetes默认信任的CA就是集群自己的kubernetes-ca。使用kubernetes-ca的身份签署上面生成的证书签署请求,将签署后的文件同样保存在默认的目录
  1. [root@kube-master-01 pki]# openssl x509 -req -days 365 \
  2. > -CA /etc/kubernetes/pki/ca.crt \
  3. > -CAkey /etc/kubernetes/pki/ca.key \
  4. > -CAcreateserial \
  5. > -in /etc/kubernetes/pki/kubernetes-cluster-admin.csr \
  6. > -out /etc/kubernetes/pki/kubernetes-cluster-admin.crt
  7. Signature ok
  8. subject=/CN=kubernetes-cluster-admin/O=admin
  9. Getting CA Private Key
  10. [root@kube-master-01 pki]#

验证证书

  • 必要时可以验证一下证书
  1. [root@kube-master-01 pki]# openssl x509 -in kubernetes-cluster-admin.crt -text -noout
  2. Certificate:
  3. Data:
  4. Version: 1 (0x0)
  5. Serial Number:
  6. a0:28:31:35:64:e9:df:f9
  7. Signature Algorithm: sha256WithRSAEncryption
  8. Issuer: CN=kubernetes
  9. Validity
  10. Not Before: Sep 9 06:25:11 2021 GMT
  11. Not After : Sep 9 06:25:11 2022 GMT
  12. Subject: CN=kubernetes-cluster-admin, O=admin
  13. Subject Public Key Info:
  14. Public Key Algorithm: rsaEncryption
  15. Public-Key: (2048 bit)
  16. Modulus:
  17. ...
  18. ...
  19. de:79
  20. Exponent: 65537 (0x10001)
  21. ...
  22. ...
  23. [root@kube-master-01 pki]#

设置集群信息

  • 添加集群配置,包括集群名称,API Server URL和信任的CA证书
  • kubeconfig配置文件里面集群名称为kubernetes-internal-dev
  1. [root@kube-master-01 pki]# kubectl config set-cluster kubernetes-internal-dev --embed-certs=true \
  2. > --certificate-authority=/etc/kubernetes/pki/ca.crt \
  3. > --server="https://172.18.14.244:6443" \
  4. > --kubeconfig=$HOME/.kube/kubernetes-internal-dev.config
  5. Cluster "kubernetes-internal-dev" set.
  6. [root@kube-master-01 pki]#

创建身份认证凭据

  • 使用X509数字证书及私钥创建身份凭据,列表项名称同目标用户名
  1. [root@kube-master-01 pki]# kubectl config set-credentials kubernetes-cluster-admin --embed-certs=true \
  2. > --client-certificate=/etc/kubernetes/pki/kubernetes-cluster-admin.crt \
  3. > --client-key=/etc/kubernetes/pki/kubernetes-cluster-admin.key \
  4. > --kubeconfig=$HOME/.kube/kubernetes-internal-dev.config
  5. User "kubernetes-cluster-admin" set.
  6. [root@kube-master-01 pki]#

配置上下文

  1. [root@kube-master-01 pki]# kubectl config set-context kubernetes-cluster-admin@kubernetes-internal-dev --cluster=kubernetes-internal-dev --user=kubernetes-cluster-admin --kubeconfig=$HOME/.kube/kubernetes-internal-dev.config
  2. Context "kubernetes-cluster-admin@kubernetes-internal-dev" created.
  3. [root@kube-master-01 pki]#

设置默认的上下文

  • 设置kubernetes-internal-dev默认使用的上下文
  1. [root@kube-master-01 pki]# kubectl config use-context kubernetes-cluster-admin@kubernetes-internal-dev --kubeconfig=$HOME/.kube/kubernetes-internal-dev.config
  2. Switched to context "kubernetes-cluster-admin@kubernetes-internal-dev".
  3. [root@kube-master-01 pki]#

验证

  • 可以随便查看一个集群上的资源都会显示无权限
  1. [root@kube-master-01 pki]# kubectl get namespace --kubeconfig=$HOME/.kube/kubernetes-internal-dev.config
  2. Error from server (Forbidden): namespaces is forbidden: User "kubernetes-cluster-admin" cannot list resource "namespaces" in API group "" at the cluster scope
  3. [root@kube-master-01 pki]#

合并kubeconfig

  • 为了后续操作方便,这里将kubeconfig先合并
  1. [root@kube-master-01 kubernetes]# export KUBECONFIG="$HOME/.kube/config:$HOME/.kube/kubernetes-internal-dev.config"
  2. [root@kube-master-01 kubernetes]# kubectl config get-contexts
  3. CURRENT NAME CLUSTER AUTHINFO NAMESPACE
  4. ik8s@kube-dev kube-dev ilinux
  5. ilinux@kube-dev kube-dev ilinux
  6. kube-user@kubernetes kubernetes kube-user
  7. * kubernetes-admin@kubernetes kubernetes kubernetes-admin
  8. kubernetes-cluster-admin@kubernetes-internal-dev kubernetes-internal-dev kubernetes-cluster-admin
  9. [root@kube-master-01 kubernetes]# kubectl config view --merge --flatten > $HOME/.kube/kube.config
  10. [root@kube-master-01 kubernetes]#
  11. [root@kube-master-01 kubernetes]#
  12. [root@kube-master-01 kubernetes]# kubectl config get-contexts
  13. CURRENT NAME CLUSTER AUTHINFO NAMESPACE
  14. ik8s@kube-dev kube-dev ilinux
  15. ilinux@kube-dev kube-dev ilinux
  16. kube-user@kubernetes kubernetes kube-user
  17. * kubernetes-admin@kubernetes kubernetes kubernetes-admin
  18. kubernetes-cluster-admin@kubernetes-internal-dev kubernetes-internal-dev kubernetes-cluster-admin
  19. [root@kube-master-01 kubernetes]#

创建RBAC授权

  • 使用RBAC为该用户授权
  • 将集群的cluster-admin角色绑定到该用户账户上,使其能够拥有集群超级管理员的权限
  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRoleBinding
  3. metadata:
  4. name: kubernetes-cluster-admin
  5. subjects:
  6. - kind: User
  7. name: kubernetes-cluster-admin
  8. apiGroup: rbac.authorization.k8s.io
  9. roleRef:
  10. kind: ClusterRole
  11. name: cluster-admin
  12. apiGroup: rbac.authorization.k8s.io

切换上下文

  • 切换集群的上下文,然后验证kubernetes-cluster-admin用户是否具备超级管理员的权限
  • 生产环境里面,生成好了权限配置之后,直接将新生成的kubeconfig文件单独发送给客户端使用,而不是发送$HOME/.kube/config文件
  1. [root@kube-master-01 pki]# kubectl config use-context kubernetes-cluster-admin@kubernetes-internal-dev
  2. Switched to context "kubernetes-cluster-admin@kubernetes-internal-dev".
  3. [root@kube-master-01 pki]#
  4. [root@kube-master-01 pki]# kubectl config current-context
  5. kubernetes-cluster-admin@kubernetes-internal-dev
  6. [root@kube-master-01 pki]#
  7. [root@kube-master-01 pki]# kubectl get pods -n kube-ops
  8. NAME READY STATUS RESTARTS AGE
  9. alertmanager-778644d955-4j57d 1/1 Running 0 14d
  10. blackbox-exporter-6cf54f4d98-ngcts 1/1 Running 0 13d
  11. blackbox-exporter-6cf54f4d98-vhvn8 1/1 Running 0 13d
  12. blackbox-exporter-6cf54f4d98-xbkkb 1/1 Running 0 5h3m
  13. grafana-57df885c4-jr8h2 1/1 Running 0 15d
  14. node-exporter-24dmf 1/1 Running 0 15d
  15. node-exporter-dd92q 1/1 Running 2 15d
  16. node-exporter-ghxvb 1/1 Running 0 15d
  17. node-exporter-ww8xt 1/1 Running 7 15d
  18. node-exporter-xk5nd 1/1 Running 0 15d
  19. prometheus-76fb655799-smkv5 2/2 Running 0 15d
  20. [root@kube-master-01 pki]#
  • 同理,创建view、edit等一系列需要集群角色的用户也可以使用类似上面的方式,只需要做些许修改即可