Kubernetes RBAC
一、简介
RBAC
(Role-Based Access Control,基于角色的访问控制),作为Kubernetes安装方式的默认选项,足见其重要程度,相对于其他访问控制方式,RBAC具有以下优势:
-
对集群中的资源和非资源权限均有完整的覆盖
-
整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubect或API进行操作
-
可以在运行时进行调整,无须重启启动API Server
RBAC
使用 rbac.authorization.k8s.io
API Group来实现授权决策,允许管理员通过kubernetes API动态配置策略,要启用RBAC
,需要在apiserver 中添加参数 --authorization-mode=RBAC
二、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,而Deployment
属于apps API Group,要在Kubernetes
中进行RBAC
的管理,除了上面的这些资源和操作外,我们还需要另外的一些对象:
-
Rule:规则,规则是一组属于不同API Group资源上的一组操作的集合
-
Role 和 ClusterRole:角色和集群角色,这两个对象都包含上面的Rule元素,二者区别在于,在Role中,定义的规则只适用于单个命名空间,也就是和namespace关联的,而ClusterRole是集群范围内的,因此定义的规则不受命名空间的约束。另外Role和ClusterRole在Kubernetes中都被定义为集群内部的API资源,和Pod、ConfigMap这些类似,都是集群资源的对象,所有同意的可以使用kubectl相关命令来进行操作
-
Subject:主题,对应在集群中尝试操作的对象,集群中定义了3种类型的主题资源:
-
User Account:用户,这是由外部独立服务进行管理的,管理员进行私钥的分配,用户可以使用KeyStone或者Google账号,甚至一个用户名和密码的文件列表也可以。对于用户的管理集群内部没有一个关联的资源对象,所以用户不能通过集群内部的API进行管理
-
Group:组,这是用来关联多个账户的,集群中有一些默认创建的组,比如cluster-admin
-
Service Account:服务账号,通过Kubernetes API来管理的一些用户账号,和namespace进行关联,适用于集群内部运行的应用程序,需要通过API来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到Service Account
-
-
Role Binding和ClusterRoleBinding:角色绑定和集群角色绑定,简单的来说就是把声明的Subject和我们的Role进行绑定的 过程(给某个用户绑定上操作的权限),二者的区别也是作用范围的区别:RoleBinding只会影响到当前namespace下面的资源操作权限,而ClusterRoleBinding会影响到所有的namespace。
三、创建一个只能访问某个namespace的用户
3.1 创建一个User Account,只能访问kube-system这个命名空间
-
username: tunan
-
group:jiang
(1)给用户tunan创建一个私钥,命名为:tunan.key
# openssl genrsa -out tunan.key 2048
(2)使用刚刚创建的私钥新建一个证书签名请求文件:tunan.csr,确保参数-subj参数中指定用户名和组(CN表示用户名,O表示组)
# openssl req -new -key tunan.key -out tunan.csr -subj "/CN=tunan/O=jiang"
(3)找到kubernetes集群的CA,利用集群的ca.crt和ca.key两个文件来批准上面的证书请求,并设置500天有效期
# openssl x509 -req -in tunan.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki//ca.key -CAcreateserial -out tunan.crt -days 500
(4)查看证书
# ls tunan.crt tunan.csr tunan.key
(5)使用刚创建的证书文件和私钥文件在集群中创建新的凭证和上下文(Context)
# kubectl config set-credentials tunan --client-certificate=tunan.crt --client-key=tunan.key User "tunan" set.
(6)为这个用户设置新的Context
# kubectl config set-context tunan-context --cluster=kubernetes --namespace=kube-system --user=tunan Context "tunan-context" created.
(7)此时使用这个配置文件来操作kubectl会出错,因为还没有定义任何操作权限
# kubectl get pods --context=tunan-context Error from server (Forbidden): pods is forbidden: User "tunan" cannot list resource "pods" in API group "" in the namespace "kube-system"
3.2 创建角色
用户完成后,接下来需要给用户添加操作权限,创建一个允许用户操作Deployment、Pod、ReplicaSets的角色
-
tunan-role.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: tunan-role namespace: kube-system rules: - apiGroups: ["","extensions","apps"] resources: ["deployments","replicasets","pods"] verbs: ["get","list","watch","create","patch","delete"] # 全部权限可以使用["*"]
apiGroups中[""] 代表核心API Group,
ReplicasSets
属于extensions
这个API Group,而Deployments
属于apps
这个API Group。上面的verbs
就是对这些资源对象执行的操作 -
创建这个Role
# kubectl create -f tunan-role.yaml role.rbac.authorization.k8s.io/tunan-role created
3.3 创建角色绑定
Role创建完成后,但是这个Role和用户tunan还没有任何关系,这里就需要创建一个RoleBinding对象,在kube-system这个命名空间下面将上面的tunan-role 角色和用户 tunan进行绑定
-
tunan-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tunan-rolebinding namespace: kube-system subjects: - kind: User name: tunan apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: tunan-role apiGroup: rbac.authorization.k8s.io
-
查看
# kubectl describe role tunan-role -n kube-system Name: tunan-role Labels: <none> Annotations: <none> PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- deployments [] [] [get list watch create patch delete] pods [] [] [get list watch create patch delete] replicasets [] [] [get list watch create patch delete] deployments.apps [] [] [get list watch create patch delete] pods.apps [] [] [get list watch create patch delete] replicasets.apps [] [] [get list watch create patch delete] deployments.extensions [] [] [get list watch create patch delete] pods.extensions [] [] [get list watch create patch delete] replicasets.extensions [] [] [get list watch create patch delete] # kubectl describe rolebinding tunan-rolebinding -n kube-system Name: tunan-rolebinding Labels: <none> Annotations: <none> Role: Kind: Role Name: tunan-role Subjects: Kind Name Namespace ---- ---- --------- User tunan
-
验证
# kubectl get pods --context=tunan-context NAME READY STATUS RESTARTS AGE coredns-66bff467f8-hqqz7 1/1 Running 10 12d coredns-66bff467f8-z2hr4 1/1 Running 10 12d etcd-master 1/1 Running 11 12d kube-apiserver-master 1/1 Running 11 12d kube-controller-manager-master 1/1 Running 13 12d ...
四、创建一个只能访问某个namespace的ServiceAccount
创建一个集群内部的用户ServiceAccount,只能操作kube-system这个命名空间下面的pods和deployments
-
sa.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: tunan-sa namespace: kube-system
-
创建sa
# kubectl create -f sa.yaml # kubectl get sa tunan-sa -n kube-system NAME SECRETS AGE tunan-sa 1 19s
-
创建一个新的Role对象
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: tunan-sa-role namespace: kube-system rules: - apiGroups: [""] resources: ["pods"] verbs: ["get","watch","list"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ['get','list','watch','create','update','patch','delete'] # kubectl create -f tunan-sa-role.yaml role.rbac.authorization.k8s.io/tunan-sa-role created # kubectl get role tunan-sa-role -n kube-system NAME CREATED AT tunan-sa-role 2020-06-17T03:40:00Z # kubectl describe role tunan-sa-role -n kube-system Name: tunan-sa-role Labels: <none> Annotations: <none> PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- deployments.apps [] [] [get list watch create update patch delete] pods [] [] [get watch list]
-
创建一个Rolebinding,将上面的tunan-sa 和 tunan-sa-role进行绑定
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tunan-sa-rolebinding namespace: kube-system subjects: - kind: ServiceAccount name: tunan-sa namespace: kube-system roleRef: kind: Role name: tunan-sa-role apiGroup: rbac.authorization.k8s.io # kubectl get rolebinding tunan-sa-rolebinding -n kube-system NAME ROLE AGE tunan-sa-rolebinding Role/tunan-sa-role 30s # kubectl describe rolebinding tunan-sa-rolebinding -n kube-system Name: tunan-sa-rolebinding Labels: <none> Annotations: <none> Role: Kind: Role Name: tunan-sa-role Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount tunan-sa kube-system
-
验证
每个ServiceAccount会生成一个Srcret对象和它进行映射,这个Secret里面包含一个token,可以利用这个token去登入Dashboard,可以在Dashboard中验证功能是否符合预期
# kubectl get secret -n kube-system |grep tunan-sa # kubectl get secret tunan-sa-token-hn97d -o jsonpath={.data.token} -n kube-system | base64 -d
会得到一个很长的token,利用这个token去登入Dashboard
除了命名空间kube-system中的内容,其他都无法查看,结果是符合预期的
五、创建一个可以访问所有namespace的ServiceAccount
新创建一个ServiceAccount,具有操作所有namespace的权限,这个时候就需要使用到ClusterRole和ClusterRoleBinding这两种资源对象了。
-
创建新的ServiceAccount
apiVersion: v1 kind: ServiceAccount metadata: name: cluster-tunan-sa namespace: kube-system
# kubectl get sa cluster-tunan-sa -n kube-system NAME SECRETS AGE cluster-tunan-sa 1 64s
-
创建一个ClusterRoleBinding对象
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: clusterrolebinding-tunan-sa subjects: - kind: ServiceAccount name: cluster-tunan-sa namespace: kube-system roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
# kubectl create -f cluster-rolebinding-tunan.yaml clusterrolebinding.rbac.authorization.k8s.io/clusterrolebinding-tunan-sa created
# kubectl get clusterrolebinding clusterrolebinding-tunan-sa -n kube-system NAME ROLE AGE clusterrolebinding-tunan-sa ClusterRole/cluster-admin 65s -
获取token
# kubectl get secret -n kube-system | grep cluster-tunan-sa cluster-tunan-sa-token-zj95w kubernetes.io/service-account-token 3 6m51s
# kubectl get secret cluster-tunan-sa-token-zj95w -o jsonpath={.data.token} -n kube-system | base64 -d登入Dashboard验证,可以访问所有的namespace资源