K8s中RBAC

RBAC - 基于角色的访问控制

官方文档:使用 RBAC 鉴权 | Kubernetes

RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策,允许管理员通过 Kubernetes API 动态配置策略,要启用RBAC,需要在 apiserver 中添加参数--authorization-mode=RBAC ,如果使用的kubeadm 安装的集群,1.6 版本以上的都默认开启了RBAC,可以通过查看 Master 节点上 apiserver 的静态Pod 定义文件:

cat /etc/kubernetes/manifests/kube-apiserver.yaml
- --authorization-mode=Node,RBAC

cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep authorization-mode=Node,RBAC

如果是二进制的方式搭建的集群,添加这个参数过后,记得要重启 apiserver 服务。

Kubernetes 有一个很基本的特性就是它的所有资源对象都是模型化的 API 对象,允许执行 CRUD(Create、Read、Update、Delete)操作(增、删、 改、查),比如下面的这些资源:

Pods , ConfigMaps ,Deployments ,Nodes ,Secrets ,Namespaces

上面这些资源对象的可能存在的操作有:

create, get, delete, list, update, edit, watch, exec

在更上层,这些资源和 API Group 进行关联,比如Pods属于 Core API Group,而Deployements 属于 apps API Group,要在Kubernetes 中进 行RBAC的管理,除了上面的这些资源和操作以外,还需要另外的一些对象:

Rule:规则,规则是一组属于不同 API Group 资源上的一组操作的集 合

Role 和 ClusterRole:角色和集群角色,这两个对象都包含上面的 Rules 元素,二者的区别在于,在 Role 中,定义的规则只适用于单个 命名空间,也就是和 namespace 关联的,而 ClusterRole 是集群范围 内的,因此定义的规则不受命名空间的约束。另外 Role 和 ClusterRole 在Kubernetes 中都被定义为集群内部的 API 资源,和我们前面学习过 的 Pod、ConfigMap 这些类似,都是我们集群的资源对象,所以同样 的可以使用我们前面的kubectl相关的命令来进行操作

Subject:主题,对应在集群中尝试操作的对象,集群中定义了3种类型 的主题资源:

User Account:用户,这是有外部独立服务进行管理的,管理员进 行私钥的分配,用户可以使用 KeyStone或者 Goolge 帐号,甚至一 个用户名和密码的文件列表也可以。对于用户的管理集群内部没有 一个关联的资源对象,所以用户不能通过集群内部的 API 来进行管 理

Group:组,这是用来关联多个账户的,集群中有一些默认创建的 组,比如cluster-admin

Service Account:服务帐号,通过Kubernetes API 来管理的一 些用户帐号,和 namespace 进行关联的,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权 限操作,都需要使用到 ServiceAccount,这也是我们的重点

RoleBinding 和 ClusterRoleBinding:角色绑定和集群角色绑定,简单 来说就是把声明的 Subject 和 Role 进行绑定的过程(给某个用户绑定上 操作的权限),二者的区别也是作用范围的区别:RoleBinding 只会影响 到当前 namespace 下面的资源操作权限,而 ClusterRoleBinding 会影 响到所有的 namespace。

接下来通过几个示例来演示下RBAC的配置方法:

#创建一个只能访问某个 namespace 的用户:
username: jjy
group: jjy

#给用户 jjy 创建一个私钥,命名成:jjy.key:
openssl genrsa -out jjy.key 2048

#使用刚刚创建的私钥创建一个证书签名请求文件:jjy.csr,要注意需要确保在-subj参数中指定用户名和组(CN表示用户名,O表示组):
openssl req -new -key jjy.key -out jjy.csr -subj "/CN=jjy/O=jjy"    #新的请求私钥jjy.key输出jjy.csr指定用户和组

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

#生成最终的证书文件,设置证书的有效期为500天:
openssl x509 -req -in jjy.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out jjy.crt -days 500

现在可以使用刚刚创建的证书文件和私钥文件在集群中创建新的凭证:

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

为这个用户设置新的上下文 Context:

kubectl config set-context jjy-context --cluster=kubernetes --namespace=kube-system --user=jjy
#起名字为jjy-context 然后这个用户可以对kubernetes集群对名称空间中的kube-system权限绑定到jjy用户

#使用命令查看权限会发现无法查看
kubectl get pods --context=jjy-context
Error from server (Forbidden): pods is forbidden: User "jjy" cannot list resource "pods" in API group "" in the namespace "kube-system"

创建角色

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

vim jjy-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: jjy-role
  namespace: kube-system
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update","patch", "delete"]
# 也可以使用['*']


kubectl apply -f jjy-role.yaml
kubectl get role -A

创建角色权限绑定

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

vim jjy-rolebinding.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jjy-rolebinding
  namespace: kube-system
subjects:
- kind: User
  name: jjy
  apiGroup: ""
roleRef:
  kind: Role
  name: jjy-role
  apiGroup: ""

kubectl get rolebindings.rbac.authorization.k8s.io  -A

上面的 YAML文件中我们看到了subjects关键字,这里就是我们上面提到 的用来尝试操作集群的对象,这里对应上面的 User 帐号 jjy,使用 kubectl创建上面的资源对象