权限管理实践
背景
本文主要通过一个例子来介绍如何基于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 namespace: pre 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/mingpianwnag -n pre Name: mingpianwnag Namespace: pre Labels:Annotations: Image pull secrets: Mountable secrets: mingpianwnag-token-4l8xj Tokens: mingpianwnag-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: mingpianwnag 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 undefined ; exit 255; }" EXIT SA_SECRET=$( kubectl get sa -n undefined undefined -o jsonpath='{.secrets[0].name}' ) # Pull the bearer token and cluster CA from the service account secret. BEARER_TOKEN=$( kubectl get secrets -n undefined undefined -o jsonpath='{.data.token}' | base64 -d ) kubectl get secrets -n undefined undefined -o jsonpath='{.data.ca\.crt}' | base64 -d > undefined/ca.crt CLUSTER_URL=$( kubectl config view -o jsonpath='{.clusters[0].cluster.server}' ) KUBECONFIG=kubeconfig kubectl config --kubeconfig=undefined \ set-cluster \ undefined \ --server=undefined \ --certificate-authority=undefined/ca.crt \ --embed-certs=true kubectl config --kubeconfig=undefined \ set-credentials undefined --token=undefined kubectl config --kubeconfig=undefined \ set-context registry \ --cluster=undefined \ --user=undefined \ --namespace=undefined kubectl config --kubeconfig=undefined \ use-context registry echo "kubeconfig written to file \"undefined\""
直接在master节点执行sh kubeconfig.sh pre mingpianwang,即可自动生成一个kubeconfig文件,将这个kubeconfig文件分发给使用者,让其复制到~/.kube/config下即可,而且默认NS就是pre,get nodes等操作都是不被允许的。
自动生成kubeconfig的源代码在这里,generator kubeconfig,我们只是加了一个默认NS,这样不需要在执行kubectl命令的时候追加-n pre。