简述
RBAC
是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。 简言之,不同用户之间拥有不同的访问权限,就像我们在使用ELK日志系统时,运维人员具有最高权限,根据其他人员的需求对不同的index分配可读,可写,只读,只写,其他各种权限。
在k8s中,负责完成授权工作的机制,就是RBAC
基本概念
- Role/ClusterRole:角色,它包含了一组代表相关权限的规则,这些规则就是对不同
API
的不同操作权限 - Subject:被作用者,用于绑定不同的角色. 可以是组,用户或者服务账户
- RoleBinding/ClusterRoleBinding:定义了
Role/ClusterRole
和Subject
的绑定关系
Role
定义一个Role对象,用来授予对Pod的读访问权限
[root@ycloud ycloud]# cat role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: ycloud
name: example-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
Role对象指定了产生作用的Namespace是:ycloud
Namespace是k8s的一个逻辑管理单位。不同的Namespace的API对象,是相互隔离的。
这个Role对象的rules
字段,其实就是它定义的一组权限规则。
允许"被作用者",对ycloud下面的Pod对象,进行get、watch、list操作。
在Role或者ClusterRole中,如果要赋予用户所有权限,那就可以给verbs字段所有权限
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
RoleBinging
下面例子中定义了一个RoleBinding
对象。
[root@ycloud ycloud]# cat rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: example-rolebinding
namespace: ycloud
subjects:
- kind: User
name: system:anonymous
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: example-role
apiGroup: rbac.authorization.k8s.io
可以看到,这个RoleBinding对象中定义了一个subjects字段,即"被作用者"。它的类型是User,即k8s中的用户。
将"example-role"Role授予在"ycloud"NameSpace中的用户" system:anonymous "。 这样,用户 " system:anonymous " 就具有了读取 "ycloud" NameSpace中所有 Pod 的权限。
实践
我们先在k8s集群中创建名为example的上下文,指定user为匿名用户
[root@ycloud ycloud]# kubectl config set-context example --namespace=ycloud --cluster=kubernetes --user=system:anonymous
Context "example" created.
我们在ycloud这个Namespace下,创建一个简单的Pod对象
[root@ycloud ycloud]# kubectl create ns ycloud
namespace/ycloud created
[root@ycloud ycloud]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: ycloud
labels:
app: pod-demo
spec:
containers:
- name: pod-container-name
image: nginx
ports:
- containerPort: 80
name: http-server
[root@ycloud ycloud]# kubectl apply -f pod.yaml -n ycloud
pod/pod-demo create
切换上下文
[root@ycloud ycloud]# kubectl config set-context example
Context "example" modified.
[root@ycloud ycloud]# kubectl get po
Please enter Username: admin
Please enter Password: NAME READY STATUS RESTARTS AGE
pod-demo 1/1 Running 0 13m
因为我们这里指定的匿名用户,所以我们用户名和密码任意输入,回车即可查看ycloud下面所创建的Pod。
如果我们尝试get deploy或者查看别的Namespace下的pod,查看返回结果,会提示我们这个用户没有权限。
[root@ycloud ycloud]# kubectl get deploy
Please enter Username: admin
Please enter Password: Error from server (Forbidden): deployments.apps is forbidden: User "system:anonymous" cannot list resource "deployments" in API group "apps" in the namespace "ycloud"
---
[root@ycloud ycloud]# kubectl get po -A
Please enter Username: admin
Please enter Password: Error from server (Forbidden): pods is forbidden: User "system:anonymous" cannot list resource "pods" in API group "" at the cluster scope
ClusterRole和ClusterRoleBinding
Role
和 RoleBinding
对象都是 Namespaced 对象,它们仅在自身的 Namespace 内有效,roleRef 也只能引用当前 Namespace 里的 Role 对象。
如果我们想让某一个Role作用到所有的Namespace中去,这时候我们就需要使用到ClusterRole和ClusterRoleBinding这个组合了,这两个API对象跟Role和RoleBinding一样。只不过,不需要我们定义Namespace。
ClusterRole用法:
- 定义对某Namespace的访问权限,并将在个别Namespace内被授予访问权限;
- 为Namespace作用域的对象设置访问权限,并被授予跨所有Namespace的访问权限;
- 为集群作用域的资源定义访问权限。
实践
[root@ycloud ycloud]# cat rolebinding.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-clusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-clusterrolebinding
subjects:
- kind: User
name: example-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: example-clusterrole
apiGroup: rbac.authorization.k8s.io
这里如果你还切换在上个实践中,我们可以通过如下命令切换回原来的上下文:
[root@ycloud ycloud]# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* example kubernetes system:anonymous ycloud
kubernetes-admin@kubernetes kubernetes kubernetes-admin default
[root@ycloud ycloud]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
我这里的名称叫"kubernetes-admin@kubernetes",根据自己的来修改。
接下来让我们创建一下:
[root@ycloud ycloud]# kubectl apply -f clusterrole.yaml
clusterrole.rbac.authorization.k8s.io/example-clusterrole created
clusterrolebinding.rbac.authorization.k8s.io/example-clusterrolebinding created
这里我们已经创建成功,让我们重新切换回我们新建的上下文来验证一下,
[root@ycloud ycloud]# kubectl get po -n default
Please enter Username: admin
Please enter Password: NAME READY STATUS RESTARTS AGE
nginx-deployment-585449566-hvpqd 1/1 Running 0 12d
nginx-deployment-585449566-k7rjr 1/1 Running 0 12d
nginx-deployment-585449566-ptb2q 1/1 Running 0 12d
---
[root@ycloud ycloud]# kubectl get po -n traefik
Please enter Username: admin
Please enter Password: NAME READY STATUS RESTARTS AGE
traefik-84b7798f44-pczfd 1/1 Running 0 12d
whoami-78447d957f-hs9r6 1/1 Running 0 12d
whoami-78447d957f-vmsbl 1/1 Running 0 12d
我们发现可以对所有的Namespace进行Pod访问。最后移除权限
[root@ycloud ycloud]# kubectl delete -f ../ycloud/
clusterrole.rbac.authorization.k8s.io "example-clusterrole" deleted
clusterrolebinding.rbac.authorization.k8s.io "example-clusterrolebinding" deleted
pod "pod-demo" deleted
role.rbac.authorization.k8s.io "example-role" deleted
rolebinding.rbac.authorization.k8s.io "example-rolebinding" deleted
ServiceAccount
大多数时候我们不太使用"用户"这个功能,而是直接使用K8s的内置用户ServiceAccount
,不过在使用上是一样的。
首先我们定义一个ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: ycloud
name: sa
我们只需要指定是作用于某个Namespace即可
然后我们可以通过Role和RoleBinding,来对ServiceAccout进行权限分配和绑定
[root@ycloud ycloud]# cat rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: ycloud
name: role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rolebinding
namespace: ycloud
subjects:
- kind: ServiceAccount
name: sa
namespace: mynamespace
roleRef:
kind: Role
name: role
apiGroup: rbac.authorization.k8s.io
可以看到,RoleBinding对象中,subjects字段不再是一个User,而是一个serviceaccount。
[root@ycloud ycloud]# kubectl apply -f serviceaccount.yaml
serviceaccount/sa created
[root@ycloud ycloud]# kubectl apply -f rbac.yaml
role.rbac.authorization.k8s.io/role created
rolebinding.rbac.authorization.k8s.io/rolebinding created
创建好之后,让我们查看一下ServiceAccount的描述内容:
[root@ycloud ycloud]# kubectl describe serviceaccount sa -n ycloud
Name: sa
Namespace: ycloud
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: sa-token-pxc28
Tokens: sa-token-pxc28
Events: <none>
我们会发现,k8s会为ServiceAccount对象自动分配一个secrets。这个secrets是用来ServiceAccount和APIserver进行交互的授权文件,一般保存的会是证书或者是密码。
让我们将"用户"和Pod进行绑定,在之前的pod文件中添加一行。
[root@ycloud ycloud]# cat pod.yaml
`````
spec:
serviceAccountName: sa ###指定ServiceAccount
containers:
- name: pod-container-name
image: nginx
`````
如果pod没有绑定serviceAccount,k8s也会自动在它的Namespace下创建一个名叫default的默认ServiceAccount,分配给这个Pod。
除了这些,k8s还提供了几种定义好的ClusterRole来供我们使用,分别是超级用户、可读、可写
- cluster-admin
- admin
- edit
- view
[root@ycloud ycloud]# kubectl describe clusterrole cluster-admin
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
[*] [] [*]
"*"代表了所有权限
总结
我们了解了什么是RBAC,之后我们可以根据我们的需要分配不同的权限。