Kubernetes 使用RBAC鉴权

1,736 阅读2分钟

基于角色(Role)的访问控制(RBAC)是一种基于企业中用户的角色来调节控制对计算机或网络资源的访问方法。

RBAC 使用 rbac.authorization.k8s.io API 组 来驱动鉴权操作,允许管理员通过 Kubernetes API 动态配置策略。

在 1.8 版本中,RBAC模式是稳定的并通过 rbac.authorization.k8s.io/v1 API 提供支持。

要启用 RBAC,在启动 API 服务器时添加 --authorization-mode=RBAC 参数。

API 概述

本节介绍 RBAC API 所声明的四种顶级类型。用户可以像与其他 API 资源交互一样, (通过 kubectl、API 调用等方式)与这些资源交互。例如, 命令 kubectl apply -f (resource).yml 可以用在这里的任何一个例子之上。 尽管如此,建议读者循序渐进阅读下面的章节,由浅入深。

创建一个只能访问某个 namespace 的用户

我们来创建一个 User Account,只能访问 kube-system 这个命名空间:

  • username:mooon
  • group: cmcc

第1步:创建用户凭证

我们前面已经提到过,Kubernetes没有 User Account 的 API 对象,不过要创建一个用户帐号的话也是挺简单的,利用管理员分配给你的一个私钥就可以创建了,这个我们可以参考官方文档中的方法,这里我们来使用OpenSSL证书来创建一个 User,当然我们也可以使用更简单的cfssl工具来创建:

给用户 mooon创建一个私钥,命名成:mooon.key:

$ openssl genrsa -out mooon.key 2048

使用我们刚刚创建的私钥创建一个证书签名请求文件:mooon.csr,要注意需要确保在-subj参数中指定用户名和组(CN表示用户名,O表示组):

openssl req -new -key mooon.key -out mooon.csr -subj "/CN=mooon/O=cmcc"

然后找到我们的Kubernetes集群的CA,我们使用的是kubeadm安装的集群,CA相关证书位于/etc/kubernetes/pki/目录下面,如果你是二进制方式搭建的,你应该在最开始搭建集群的时候就已经指定好了CA的目录,我们会利用该目录下面的ca.crt和ca.key两个文件来批准上面的证书请求生成最终的证书文件,我们这里设置证书的有效期为500天:

openssl x509 -req -in mooon.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out mooon.crt -days 500

现在查看我们当前文件夹下面是否生成了一个证书文件:

ls
mooon.csr mooon.key mooon.crt

现在我们可以使用刚刚创建的证书文件和私钥文件在集群中创建新的凭证和上下文(Context):

kubectl config set-credentials mooon --client-certificate=mooon.crt --client-key=mooon.key

我们可以看到一个用户haimaxy创建了,然后为这个用户设置新的 Context:

kubectl config set-context mooon-context --cluster=kubernetes --namespace=kube-system --user=mooon

到这里,我们的用户haimaxy就已经创建成功了,现在我们使用当前的这个配置文件来操作kubectl命令的时候,应该会出现错误,因为我们还没有为该用户定义任何操作的权限呢:

kubectl get pods --context=haimaxy-context
Error from server (Forbidden): pods is forbidden: User "haimaxy" cannot list pods in the namespace "default"

第2步:创建角色

用户创建完成后,接下来就需要给该用户添加操作权限,我们来定义一个YAML文件,创建一个允许用户操作 Deployment、Pod、ReplicaSets 的角色,如下定义:(mooon-role.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pods-reader
rules:
- apiGroups: [""]
  resources: ["pods","pods/exec"]
  verbs: ["get", "list", "watch", "create"] # 也可以使用['*']

创建

kubectl create -f mooon-role.yaml

第3步:创建角色权限绑定

ClusterRole 创建完成了,但是很明显现在我们这个 ClusterRole 和我们的用户 mooon还没有任何关系,对吧?这里我就需要创建一个ClusterRoleBinding对象,在 kube-system 这个命名空间下面将上面的mooon-role 角色和用户mooon 进行绑定:(mooon-rolebinding.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pods-readonly
subjects:
- kind: User
  name: mooon
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pods-reader
  apiGroup: rbac.authorization.k8s.io

创建

kubectl create -f mooon-rolebinding.yaml

第4步. 测试

现在我们应该可以上面的mooon-context上下文来操作集群了:

kubectl get pods --context=mooon-context
kubectl get nodes --context=haimaxy-context
Error from server (Forbidden): pods is forbidden: User "mooon" cannot list pods in the namespace "default"

一些命令行工具

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 对象并指定资源名称:
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 对象并指定非资源路径:
kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
  • 创建名为 “monitoring” 的 ClusterRole 对象并指定聚合规则:
kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"

kubectl create rolebinding

在特定的命名空间中对 RoleClusterRole 授权。例如:

  • 在命名空间 “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

设置集群参数

[root@k8s-master admin]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/cert/ca.pem --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=kubectl.kubeconfig

设置客户端认证参数

[root@k8s-master admin]# kubectl config set-credentials admin --client-certificate=admin.pem --client-key=admin-key.pem --embed-certs=true --kubeconfig=kubectl.kubeconfig
```shell
### 设置上下文参数,包含集群名称和访问集群的用户名字
```shell
[root@k8s-master admin]# kubectl config set-context kubernetes --cluster=kubernetes --user=admin --kubeconfig=kubectl.kubeconfig

使用默认上下文

[root@k8s-master admin]# kubectl config use-context kubernetes --kubeconfig=kubectl.kubeconfig
Switched to context "kubernetes"

参考

www.jianshu.com/p/f77d5d0df…
v1-17.docs.kubernetes.io/zh/docs/ref…