资讯专栏INFORMATION COLUMN

【容器云 UK8S】最佳实践:权限管理之了解RBAC和权限管理实践

Tecode / 2322人阅读

摘要:本文介绍了模型中四个最主要的对象,即,大致了解了的工作原理和使用方法,如果要更加深入地了解和掌握,可以查看官方文档。只是这个不能复用到其他,一般只有在做精细化权限管理的时候,我们才会创建对象,比如一个只能查看名称为的。

了解RBAC

简介

RBAC是一种基于角色来管理对计算机或网络资源访问策略的方法。

我们知道,对K8S内所有API对象的操作都是通过访问kube-apiserver来完成的,因此kube-apiserver需要校验访问者是否具备操作这些API对象的权限。而K8S中负责授权和权限校验(Authorization&Authentication)的这套机制,则是RBAC:基于角色的访问控制(Role-based Access Control )

在Kubernetes的RBAC模型里面,有三个基本的概念:

  • Role:角色,其实是一组权限规则的集合,定义了一组对Kubernetes API 对象的操作权限。
  • Subject:主体,即被授予角色的"人"或"物",即可以是Kubernetes里面的Service Account,也可以是外部User,为了简单起见,本文主要以Service Account来做演示。
  • RoleBinding:定义了Role与Subject的绑定关系。

而至于ClusterRole、ClusterRoleBinding,在概念上与Role、RoleBinding非常相似,只是作用域不同而已。

Role & ClusterRole

1、Role---namespace维度的权限集合

首先我们来介绍下Role,Role本身也是Kubernetes中的一个 API 对象,其定义如下:

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

首先,我们注意到这个名为"pod-reader"的Role,通过namespace: default指定了他能产生作用的Namespace。

Namespace是Kubernetes中的一个逻辑管理单位,Kubernetes中大部分业务类API对象(如Pod、Service)都是Namespace级别的,在操作时需要显式指明Namespace,如:kubectl edit role/pod-reader -n namespace2.

然后是rules字段,一个Role对象所拥有的权限,其实就是通过rules字段来定义了。

  • apiGroups:apiGroup代表API对象所属的组,可以通过kubectl api-resources来查看API对象属于哪个组,上文示例""代表Core API group。
  • resources: 用于声明该角色可访问的API对象。
  • verbs:用于声明该角色可对API对象进行的操作,在Kubernetes中,verbs的全集为"get" "list" "watch" "create" "update" "patch" "delete",如果我们要赋予某个role对某个API对象的所有权限,指定verbs的全部集合即可。
  • resourceName:resourceName表示具体的K8S资源,需要注意的是,当声明了resourceName时,则verbs中不能再赋予list操作,该字段较少使用,一般用于较细粒度的权限管理。

了解了Role每个字段的含义后,上文Role示例的意义其实就很清楚了:一组可对default命名空间下所有的Pod,进行GET、WATCH、LIST操作的权限集合,名称为pod-reader。

2、ClusterRole---Cluster维度的权限集合

ClusterRole的API定义与Role基本相同,你可以给一个ClusterRole赋予与Role一样的权限。但由于其cluster-wide的特性,ClusterRole可以被赋予一些不同的权限:

  • 集群级别的API对象访问权限,如nodes、namespace、pv;
  • 非资源类型endpoints的访问权限,如"/healthz";
  • 所有Namespace下资源的访问权限,如kubectl get pods --all-namespaces;

下文是一个ClusterRole的示例,与Role最大的区别就在于不需要声明namespace。

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

值得注意的是,Kubernetes内置了很多为系统保留的ClusterRole,你可以通过kubectl get clusterrole查看到他们。一般来说,这些ClusterRole,是绑定给系统组件对应的service account使用的。比如,其中一个名为system:controller:cronjob-controller的ClusterRole,定义的权限规则是Cronjob这个控制器运行所必要的权限。你可以通过如下示例查看查看其权限规则。

bash-4.4# kubectl describe clusterrole system:controller:cronjob-controller
Name:         system:controller:cronjob-controller
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources                  Non-Resource URLs  Resource Names  Verbs
  ---------                  -----------------  --------------  -----
  jobs.batch                 []                 []              [create delete get list patch update watch]
  events                     []                 []              [create patch update]
  pods                       []                 []              [delete list]
  cronjobs.batch             []                 []              [get list update watch]
  cronjobs.batch/finalizers  []                 []              [update]
  cronjobs.batch/status      []                 []              [update]

除此以外,还有几个预先的定义的CluterRole值得留意下,后面给其他集群用户配置权限的时候,我们可能会用到:

  • view
  • edit
  • admin
  • cluster-admin

其所拥有的权限,通过其名称我们也能猜到大概,具体的权限规则可以通过kubectl describe clusterrole clusterrole-name来查看。

了解了Role和ClusterRole后,我们知道如何在Kubernetes集群内声明一组权限集合,那怎么把权限赋予某个具体的"人"或"物"呢?答案就是RoleBinding和ClusterRoleBinding啦。

RoleBinding&ClusterRoleBinding

1、Rolebinding---在Namespace范围内授予权限

Rolebinding可将角色中定义的权限授予用户或用户组,它包含subject(user、group或Service Account),以及所引用的角色。RoleBinding可以在同一命名空间中引用Role(意味着Role和Rolebinding必须位于同一Namespace)。

以下RoleBinding的示例,将“pod-reader”角色授予“default”命名空间中的“jane”。 这允许“jane”读取“默认”命名空间中的pod。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: ServiceAccount
  name: jane # must create a ServiceAccount jane in default namespace
  namespace: default
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

值得注意的是,一个RoleBinding也可以引用ClusterRole,这样ClusterRole中所定义的Namespace级别的权限将会被赋予Subject,当然只在rolebinding所在的Namespace有效。这样做的好处是,集群管理员可以预先创建一些通用的ClusterRole,然后在不同的Namespace中使用他们,比如在上个章节提到的view、admin.

如下文所示,虽然"view-only"这个RoleBinding引用了ClusterRole,但"ucloud"这个ServiceAccount只拥有查看"development"这个命名空间下所有资源的权限,而不能查看所有命名空间下的资源。

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
kind: RoleBinding
metadata:
  name: view-only
  namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: ServiceAccount
  name: ucloud # Create a ServiceAccount in your cluster before test
  namespace: production # The namespace of subject can be different with Rolebinding
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

2、ClusterRoleBinding---在Cluster范围内授予权限

下面我们来了解下ClusterRoleBinding,前面我们提到过,Role和RoleBinding都是Namespace级别的资源,也就是说他们所声明的权限规则都只在Namespace范围内有效。
那如果我们

  1. 想让某个Subject(用户)拥有所有Namespace的查看权限;
  2. 或者想让某个Pod拥有查看Node的权限;

应该怎么办呢?这就需要用到ClusterRole和ClusterRoleBinding这对组合了,和ClusterRole一样,ClusterRoleBinding与RoleBinding的最大不同其实就是不需要声明"namespace"这个字段了。

首先我们来看一个示例,我们想让techleader拥有所有Namespace的查看权限,注意roleRef,对于ClusterRoleBinding,只能引用ClusterRole,而不能是Role。

apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows a service account named "techleader" to view resource in any namespace.
kind: ClusterRoleBinding
metadata:
  name: techleader-read-global
subjects:
- kind: ServiceAccount
  name: techleader   
  namespace: default
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

其次,我们还希望为techleader赋予查看nodes的权限,所以我们需要在创建一个ClusterRole和ClusterRoleBinding。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: node-reader
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get" "watch" "list"]
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows a service account named "techleader" to view resource in any namespace.
kind: ClusterRoleBinding
metadata:
  name: techleader-read-node
subjects:
- kind: ServiceAccount
  name: techleader   
  namespace: default
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: node-reader
  apiGroup: rbac.authorization.k8s.io

本文介绍了Kubernetes RBAC 模型中四个最主要的API对象,即Role、ClusterRole、RoleBinding、ClusterRoleBinding,大致了解了RBAC的工作原理和使用方法,如果要更加深入地了解和掌握RBAC,可以查看官方文档

权限管理实践

背景

本文主要通过一个例子来介绍如何基于K8S的RBAC实现授权决策,允许集群管理员通过Kubernetes API动态配置策略,让非集群管理员具有某个namespace下的所有权限,并可通过Dashboard或者kubectl来管理该ns下的资源。

一、创建NS

kubectl create ns pre

上面的示例创建了一个名为"pre"的命名空间,用于部署预发布的服务。

二、创建Service Account

kubectl create sa mingpianwang -n pre

在pre的命名空间下创建一个名为"mingpianwang"的Service account,给到某个特定的用户使用。这里要说明下,K8S里面有两类用户,一个是Service Account,另一个是普通用户(user)。但K8S本身不并管理user,而是交由外部独立服务管理,因此我们不能通过K8S API来创建user,考虑到我们只是通过kubectl和Dashboard来管理集群,Service account已经足够满足要求,而且可以在Kubernetes中直接管理。因此这里不介绍如何使用user这个对象来管理集群。

三、赋予权限

由于我们已经预先说明,需要给mingpianwang这个用户赋予pre 这个命名空间下的所有权限,即admin权限。

重点来了,RoleBinding对象是可以引用一个ClusterRole对象的,然后这个ClusterRole所拥有的权限只会在这个NS下面有效。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的名字空间中复用这些角色。

我们先看下集群内默认的ClusterRole有哪些,执行get clusterrole命名可以看到,有admin、cluster-admin、edit等角色,那我们可以直接使用admin这个clusterrole角色,通过rolebinding的方式赋予”mingpianwang“这个用户。

[root@10-9-149-7 ~]# kubectl get clusterrole
NAME AGE
admin 4h53m
cluster-admin 4h53m
edit 4h53m

示例的yaml如下,我们只要执行下kubectl apply -f rolebinding.yaml 即可。

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: pre
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin
subjects:
- kind: ServiceAccount
  name: mingpianwang
  namespace: pre

当然,我们也可以创建一个Namespace级别的role,并将这个角色绑定到ServiceAccount。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: pre
  name: admin
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["*"]
  verbs: ["*"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: pre
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: admin
subjects:
- kind: ServiceAccount
  name: mingpianwang
  namespace: pre

只是这个role不能复用到其他Namespace,一般只有在做精细化权限管理的时候,我们才会创建Role对象,比如一个只能查看pod 名称为test-pod的Role。其他场景下,我们推荐集群管理员使用ClusterRole。

四、访问Dashboard

这里我们使用token方式来登录Dashboard,那我们就要获取到”mingpianwang“的token,其实就是secret了。这个secret在我们创建的时候,K8S就帮我们自动生成了。通过下面的方式来获取,最后的token复制下来就可以了。

bash-4.4# kubectl describe sa/mingpianwang -n pre
Name:                mingpianwang
Namespace:           pre
Labels:              
Annotations:         
Image pull secrets:  
Mountable secrets:   mingpianwang-token-4l8xj
Tokens:              mingpianwang-token-4l8xj
Events:              
bash-4.4# kubectl describe secret/mingpianwang-token-4l8xj -n pre
Name:         mingpianwang-token-4l8xj
Namespace:    pre
Labels:       
Annotations:  kubernetes.io/service-account.name: mingpianwang
              kubernetes.io/service-account.uid: d7bb847d-7621-11e9-9679-5254007e7ba9

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1359 bytes
namespace:  5 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9/....

复制到登录框,我们发现可以登录到Dashboard首页,不过需要注意的是,由于这个账号只有pre这个命名空间的权限,而Dashboard默认是default,所以进去之后会报一堆错咯,没关系,只要将左侧的NS改为pre即可。

五、通过kubectl管理集群

由于我们还需要支持kubectl命令行管理NS,因此还需要为mingpianwang生成kubecofnig,一个用户还好,多个用户就很麻烦了,因此这里我们使用一个自动生成kubeconfig的脚本,代码如下:

#!/bin/bash -e
# Usage ./k8s-service-account-kubeconfig.sh ( namespace ) ( service account name )
TEMPDIR=$( mktemp -d )
trap "{ rm -rf $TEMPDIR ; exit 255; }" EXIT
SA_SECRET=$( kubectl get sa -n $1 $2 -o jsonpath={.secrets[0].name} )
# Pull the bearer token and cluster CA from the service account secret.
BEARER_TOKEN=$( kubectl get secrets -n $1 $SA_SECRET -o jsonpath={.data.token} | base64 -d )
kubectl get secrets -n $1 $SA_SECRET -o jsonpath={.data.ca.crt} | base64 -d > $TEMPDIR/ca.crt
CLUSTER_URL=$( kubectl config view -o jsonpath={.clusters[0].cluster.server} )
KUBECONFIG=kubeconfig

kubectl config --kubeconfig=$KUBECONFIG 
    set-cluster 
    $CLUSTER_URL 
    --server=$CLUSTER_URL 
    --certificate-authority=$TEMPDIR/ca.crt 
    --embed-certs=true

kubectl config --kubeconfig=$KUBECONFIG 
    set-credentials $2 --token=$BEARER_TOKEN

kubectl config --kubeconfig=$KUBECONFIG 
    set-context registry 
    --cluster=$CLUSTER_URL 
    --user=$2 
    --namespace=$1

kubectl config --kubeconfig=$KUBECONFIG 
    use-context registry

echo "kubeconfig written to file "$KUBECONFIG""

直接在master节点执行sh kubeconfig.sh pre mingpianwang,即可自动生成一个kubeconfig文件,将这个kubeconfig文件分发给使用者,让其复制到~/.kube/config下即可,而且默认NS就是pre,get nodes等操作都是不被允许的。

自动生成kubeconfig的源代码在这里,generator kubeconfig,我们只是加了一个默认NS,这样不需要在执行kubectl命令的时候追加-n pre。

实时文档欢迎访问https://docs.ucloud.cn/uk8s/bestpractice/authorization/rbac

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/126292.html

相关文章

  • 容器UK8S】新手指导

    摘要:详细请见产品价格产品概念使用须知名词解释漏洞修复记录集群节点配置推荐模式选择产品价格操作指南集群创建需要注意的几点分别是使用必读讲解使用需要赋予的权限模式切换的切换等。UK8S概览UK8S是一项基于Kubernetes的容器管理服务,你可以在UK8S上部署、管理、扩展你的容器化应用,而无需关心Kubernetes集群自身的搭建及维护等运维类工作。了解使用UK8S为了让您更快上手使用,享受UK...

    Tecode 评论0 收藏0
  • 每个人都必须遵循的九项Kubernetes安全最佳实践

    摘要:的元数据隐藏功能会更改集群部署机制以避免此暴露,我们建议使用它直到有永久解决方案。授权失败可能意味着攻击者试图滥用被盗的凭据。年中国论坛提案征集现已开放论坛让用户开发人员从业人员汇聚一堂,面对面进行交流合作。 作者:StackRox产品经理Connor Gilbert 上个月,Kubernetes(世界上最受欢迎的容器编排器)生态系统因发现Kubernetes的第一个主要安全漏洞而动摇...

    jzman 评论0 收藏0
  • 每个人都必须遵循的九项Kubernetes安全最佳实践

    摘要:的元数据隐藏功能会更改集群部署机制以避免此暴露,我们建议使用它直到有永久解决方案。授权失败可能意味着攻击者试图滥用被盗的凭据。年中国论坛提案征集现已开放论坛让用户开发人员从业人员汇聚一堂,面对面进行交流合作。 作者:StackRox产品经理Connor Gilbert 上个月,Kubernetes(世界上最受欢迎的容器编排器)生态系统因发现Kubernetes的第一个主要安全漏洞而动摇...

    endless_road 评论0 收藏0
  • 每个人都必须遵循的九项Kubernetes安全最佳实践

    摘要:的元数据隐藏功能会更改集群部署机制以避免此暴露,我们建议使用它直到有永久解决方案。授权失败可能意味着攻击者试图滥用被盗的凭据。年中国论坛提案征集现已开放论坛让用户开发人员从业人员汇聚一堂,面对面进行交流合作。 作者:StackRox产品经理Connor Gilbert 上个月,Kubernetes(世界上最受欢迎的容器编排器)生态系统因发现Kubernetes的第一个主要安全漏洞而动摇...

    Travis 评论0 收藏0
  • 容器 UK8S最佳实践:基于Jenkins的CI/CD实践

    摘要:扩展性好当集群的资源严重不足而导致排队等待时,可以很容易的添加一个到集群中,从而实现扩展。用法,选择尽可能使用这个节点镜像,填写,这个容器镜像是我们的运行环境。更新文件,这里我们只是将中的镜像更换成最新构建出的镜像。基于Jenkins的CI/CD实践[TOC]一、概要提到K8S环境下的CI/CD,可以使用的工具有很多,比如Jenkins、Gitlab CI、新兴的drone等,考虑到大多公司...

    Tecode 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<