https://www.cnblogs.com/fuyuteng/p/10984283.html
https://mp.weixin.qq.com/s/BWzkem1bJtkuqIYziG_VrA
RBAC
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 | grep RBAC - --authorization-mode=Node,RBAC
如果是二进制的方式搭建的集群,添加这个参数过后,记得要重启 apiserver 服务。
RBAC API 对象
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
的配置方法。
我们来创建一个 User Account,只能访问 kube-system 这个命名空间:
username: zjz group: cetc
第1步:创建用户凭证
我们前面已经提到过,Kubernetes
没有 User Account 的 API 对象,不过要创建一个用户帐号的话也是挺简单的,利用管理员分配给你的一个私钥就可以创建了,参考https://kubernetes.io/docs/reference/access-authn-authz/authentication/,这里我们来使用OpenSSL
证书来创建一个 User,当然我们也可以使用更简单的cfssl
工具来创建:
给用户 zjz创建一个私钥,命名成:zjz.key:
# openssl genrsa -out zjz.key 2048 Generating RSA private key, 2048 bit long modulus ..............+++ ....................................+++ e is 65537 (0x10001)
使用我们刚刚创建的私钥创建一个证书签名请求文件:zjz.csr,要注意需要确保在-subj
参数中指定用户名和组(CN表示用户名,O表示组):
# openssl req -new -key zjz.key -out zjz.csr -subj "/CN=zjz/O=cetc"
然后找到我们的Kubernetes
集群的CA
,我们使用的是kubeadm
安装的集群,CA
相关证书位于/etc/kubernetes/pki/
目录下面,如果你是二进制方式搭建的,你应该在最开始搭建集群的时候就已经指定好了CA
的目录,我们会利用该目录下面的ca.crt
和ca.key
两个文件来批准上面的证书请求
生成最终的证书文件,我们这里设置证书的有效期为500天:
# openssl x509 -req -in zjz.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out zjz.crt -days 500
Signature ok subject=/CN=zjz/O=cetc Getting CA Private Key
现在查看我们当前文件夹下面是否生成了一个证书文件:
ls zjz.crt zjz.key zjz.csr
现在我们可以使用刚刚创建的证书文件和私钥文件在集群中创建新的凭证和上下文(Context):
# kubectl config set-credentials zjz --client-certificate=zjz.crt --client-key=zjz.key User "zjz" set.
我们可以看到一个用户zjz
创建了,然后为这个用户设置新的 Context:
# kubectl config set-context zjz-context --cluster=kubernetes --namespace=kube-system --user=zjz Context "zjz-context" created.
到这里,我们的用户zjz
就已经创建成功了,现在我们使用当前的这个配置文件来操作kubectl
命令的时候,应该会出现错误,因为我们还没有为该用户定义任何操作的权限呢:
kubectl get pods --context=zjz-context
Error from server (Forbidden): pods is forbidden: User "zjz" cannot list resource "pods" in API group "" in the namespace "kube-system"
第2步:创建角色
用户创建完成后,接下来就需要给该用户添加操作权限,我们来定义一个YAML
文件,创建一个允许用户操作 Deployment、Pod、ReplicaSets 的角色,如下定义:(zjz-role.yaml)
# cat zjz-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: zjz-role namespace: kube-system rules: - apiGroups: ["", "extensions", "apps"] resources: ["deployments", "replicasets", "pods"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 也可以使用['*'] 其中Pod属于 core 这个 API Group,在YAML中用空字符就可以,而Deployment属于 apps 这个 API Group,ReplicaSets属于extensions这个 API Group( 我怎么知道的?https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/), 所以 rules 下面的 apiGroups 就综合了这几个资源的 API Group:["", "extensions", "apps"],其中verbs就是我们上面提到的可以对这些资源对象执行的操作, 我们这里需要所有的操作方法,所以我们也可以使用['*']来代替。
然后创建这个Role
:
kubectl create -f zjz-role.yaml
注意这里我们没有使用上面的zjz-context
这个上下文,因为没有权限
第3步:创建角色权限绑定
Role 创建完成了,但是很明显现在我们这个 Role 和我们的用户 zjz 还没有任何关系,对吧?这里我就需要创建一个RoleBinding
对象,
在 kube-system 这个命名空间下面将上面的 zjz-role 角色和用户 zjz 进行绑定:(zjz-rolebinding.yaml)
# cat zjz-rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: zjz-rolebinding namespace: kube-system subjects: - kind: User name: zjz apiGroup: "" roleRef: kind: Role name: zjz-role apiGroup: ""
上面的YAML
文件中我们看到了subjects
关键字,这里就是我们上面提到的用来尝试操作集群的对象,这里对应上面的 User 帐号 zjz,使用kubectl
创建上面的资源对象:
kubectl create -f zjz-rolebinding.yaml
第4步. 测试
现在我们应该可以上面的haimaxy-context
上下文来操作集群了:
# kubectl get pods --context=zjz-context NAME READY STATUS RESTARTS AGE coredns-66bff467f8-gs592 1/1 Running 0 3h36m coredns-66bff467f8-vrk4l 1/1 Running 0 3h36m etcd-master 1/1 Running 0 3h36m kube-apiserver-master 1/1 Running 0 3h36m kube-controller-manager-master 1/1 Running 0 3h36m kube-flannel-ds-amd64-hcsnq 1/1 Running 0 119m kube-flannel-ds-amd64-nwlvk 1/1 Running 0 119m kube-flannel-ds-amd64-pzh5q 1/1 Running 0 119m kube-proxy-2sbdv 1/1 Running 0 3h36m kube-proxy-jj6nh 1/1 Running 0 174m kube-proxy-qr625 1/1 Running 0 175m kube-scheduler-master 1/1 Running 0 3h36m
我们可以看到我们使用kubectl
的使用并没有指定 namespace 了,这是因为我们已经为该用户分配了权限了,如果我们在后面加上一个-n default
试看看呢?
$ kubectl --context=zjz-context get pods --namespace=default Error from server (Forbidden): pods is forbidden: User "haimaxy" cannot list pods in the namespace "default"
是符合我们预期的吧?因为该用户并没有 default 这个命名空间的操作权限