kubernetes 装好正常运行一段时间后,会出现要把研发和运维权限分开的场景:

比如:

  • 给某个用户某一指定名称空间下的管理权限
  • 给用户赋予集群的只读权限

非常麻烦,我们这里不讨论过多的概念,从运维的角度出发,简单实用化

我们需要明确三个RBAC最基本的概念

  • Role: 角色,它定义了一组规则,定义了一组对Kubernetes API对象的操作权限
  • RoleBinding: 定义了"被作用者"和"角色"的绑定关系
  • Subject: 被作用者,既可以是"人",也可以是机器,当然也可以是 Kubernetes 中定义的用户(ServiceAccount主要负责kubernetes内置用户)

我们的操作过程流程如下,首先创建客户端证书;其次创建Role角色;再创建RoleBinding,把Subject和Role绑定,就完事了;最后一步是生成 kubectl 的配置文件。

一、创建客户端证书

我们以已建好的阿里 ACK 为例,或者自建好的 Kubernetes 也行;确定已经有了 .kube/config 配置文件,拥有集群最高权限,并且可以正常执行 kubectl 命令。

首先是生成证书,并向集群提出证书请求并签发,脚本如下:

#!/bin/sh  

useraccount=reader

openssl req -new -newkey rsa:4096 -nodes -keyout $useraccount-k8s.key -out $useraccount-k8s.csr -subj "/CN=$useraccount/O=devops"  
csr=$(cat $useraccount-k8s.csr | base64 | tr -d '\n')  
cat << EOF > k8s-csr.yaml  
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: $useraccount-k8s-access
spec:
  groups:
  - system:authenticated
  request: $csr
  usages:
  - client auth
EOF
 

kubectl create -f k8s-csr.yaml  
kubectl certificate approve $useraccount-k8s-access  

kubectl get csr $useraccount-k8s-access -o jsonpath='{.status.certificate}' | base64 --decode > $useraccount-k8s-access.crt  
kubectl config view -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' --raw | base64 --decode - > k8s-ca.crt

解释一下:我们定义了一个用户CN=reader,然后向集群发送了证书请求并签发,最终从集群获得了 reader-k8s-access.crt 的客户端证书和 k8s-ca.crt 的 CA 证书。

k8s-csr.yaml 和 reader-k8s.csr 都是中间产物,最终我们有了客户端私钥 reader-k8s.key ,客户端证书 reader-k8s-access.crt ,CA 证书 k8s-ca.crt 这三个有用的文件。

二、创建 Role 角色

cat << EOF >> role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-pods_reader
  namespace: default
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - pods/log
  verbs:
  - get
  - list
  - watch
EOF

kubectl apply -f role.yaml

解释:我们创建了一个 role 角色,名字叫做 role-pods_reader,所属命名空间是 default ,它对 pods 和 pods/log 有 get 、list、watch的权限,也就是说role-pods_reader 可以查看 default 空间的 pods 和 pods 的日志。

三、创建 Rolebinding

cat << EOF >> rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: rolebinding-default_pods_reader
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: role-pods_reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: reader
EOF

kubectl apply -f rolebinding.yaml

解释:我们创建了一个 rolebinding,名字叫做 rolebinding-default_pods_reader,同样所属命名空间是 default,它绑了两个东西,一个是 role,就是上面第二步创建的 role-pods_reader;另一个是 subject,对应了一个用户,就是我们第一步创建的那个 reader。

四、生成 kubectl 配置文件

#!/bin/sh
useraccount=reader
namespace=default

kubectl config set-cluster $(kubectl config view -o jsonpath='{.clusters[0].name}') --server=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}') --certificate-authority=k8s-ca.crt --embed-certs --kubeconfig=$useraccount-k8s-config

kubectl config set-credentials $useraccount --client-certificate=$useraccount-k8s-access.crt --client-key=$useraccount-k8s.key --embed-certs --kubeconfig=$useraccount-k8s-config

kubectl config set-context $useraccount --cluster=$(kubectl config view -o jsonpath='{.clusters[0].name}') --namespace=$namespace --user=$useraccount --kubeconfig=$useraccount-k8s-config

kubectl config use-context $useraccount --kubeconfig=$useraccount-k8s-config

解释:上面看起来很复杂,其实就是四步,在配置文件里设置 cluster 、设置 credentials 证书、设置 context 上下文、设置当前上下文。

完事后会产生一个完整的 reader-k8s-config 文件,如下:

image-20211109133307250

五、测试

我们验证一下:

KUBECONFIG=reader-k8s-config kubectl get pods

KUBECONFIG=reader-k8s-config kubectl auth can-i delete pods

KUBECONFIG=reader-k8s-config kubectl auth can-i delete svc

这样一个对 default 空间的只读用户就建立好了

六、集群只读用户

我们这里给出集群只读用户的 role,命名 role-cluster_reader

kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-cluster_reader
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  - pods
  - pods/exec
  - pods/log
  - services
  - configmaps
  - secrets
  - serviceaccounts
  - endpoints
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - deployments
  - replicasets
  - daemonsets
  - statefulsets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - jobs
  - cronjobs
  verbs:
  - get
  - list
  - watch
EOF

以及 rolebinding,还是绑到第一步的用户 reader 的例子

kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: rolebinding-cluster_reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: role-cluster_reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: reader
EOF

生成配置文件的步骤跟上一步是一样的。

从上面大家可以看到,其实最主要的就是 role 的 yaml 文件,里面控制着到底有怎么样的权限。