RBAC:Role-Based Access Control,基于角色的访问控制。
Kubernetes中的所有API对象都保存在Etcd中的,而对这些API操作都是通过kube-apiserver来实现的,这是因为需要kube-apiserver来帮我们完成授权,而在Kubernetes中完成授权的机制就是RBAC。
其中RBAC中的基本概念为:
- Rule:规则,一组属于不同API Group的操作集合;
- Role:角色,用于定义一组对Kubernetes API对象操作的一组规则,作用于当个namespace;
- ClusterRole:集群角色,该角色不受namespace的限制;
- Subject:被作用者,也就是规则作用的对象;
- RoleBinding:将角色和被作用者进行绑定,作用于当个namespace;
- ClusterRoleBinding:将集群角色和作用者进行绑定,不受namespace限制;
一、Role和RoleBinding
Role本身就是一个Kubernetest API对象,其定义如下:
role-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-demo
namespace: devops
rules:
- apiGroups: [""]
resources: ["pods", "deployment"]
verbs: ["creat", "delete", "watch", "list", "get"]
其意义为:它允许被作用者在devops的namespace中对pod和deployment有creat,delete,watch,list,get操作。注意,其只对devops的namespace有效,在这里的namespace不同于我们docker中的namespace,这里的namespace是kubernetes中的逻辑管理单位,不同的namespace的API对象,在通过kubectl命令进行操作的时候是相互隔离的,这种隔离仅限逻辑上的隔离,并不会提供任何实际的隔离或者多租户能力。
上面就是对Role对象的定义,可以通过kubectl explain role来获取更多帮助。
现在角色已经指定,那么Subject该如何指定呢?这就要通过RoleBinding来实现。
RoleBinding也是Kubernetes API对象,我们为joker用于绑定Role角色,定义如下:
joker-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: joker-rolebinding
namespace: devops
subjects:
- kind: User
name: joker
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: role-demo
apiGroup: rbac.authorization.k8s.io
这就给joker用户和role-demo的Role建立了绑定关系,其中joker这个User只是一个授权系统中的逻辑概念,它需要通过外部认证服务,比如Keystone,或者直接给API Server指定一个用户名,密码文件。
上面的YAML文件中其中一个重要的字段是Subjects字段,它定义”被作用者”,其中的kind表示被作用者的类型,其有以下三种类型:
- User:用户,这是由外部独立服务进行管理的,管理员进行私钥的分配,用户可以使用 KeyStone或者 Goolge 帐号,甚至一个用户名和密码的文件列表,对于用户的管理集群内部没有一个关联的资源对象,所以用户不能通过集群内部的 API 来进行管理。
- Group:组,这是用来关联多个账户,集群中有一个默认的组,比如cluster-admin。
- ServiceAccount:服务帐号,通过Kubernetes API 来管理的一些用户帐号,和 namespace 进行关联的,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到 ServiceAccount。
另外一个重要字段是roleRef,它定义RoleBing对象可以直接通过Role的名字来引用我们定义的Role对象,从而定义被作业者和角色之间的绑定关系。
Role和RoleBinding的作用范围仅限单个namespace,而对于集群来说就要使用ClusterRole和ClusterRuleBinding了。
二、ClusterRole和ClusterRoleBinding
ClusterRole和ClusterRoleBinding的定义与Role和RoleBinding一样,只不过它们的定义中没有namespace字段而已,如下:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-role-demo
rules:
- apiGroups: [""]
resources: [""]
verbs: ["watch", "list", "get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: joker-clusterrolebinding
subjects:
- kind: User
name: joker
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-role-demo
apiGroup: rbac.authorization.k8s.io
上面定义的就是joker这个用户对所有namespace里的Pod都有watch,list,get的操作权限。如果要定义所有权限,可以将verbs字段定义如下:
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
类似的在Role和ClusterRole对象中的rules字段也可以更加细致化,比如要对某一个具体的对象进行操作,如下:
rules:
- apiGroups: [""]
resources: ["configMap"]
resourceName: ["myconfig"]
verbs: ["get"]
这条规则定义被作用者只对名字为myconfig的configMap对象有get权限。
上面我们都使用Subjects中User类型得用户功能,但是在实际中我们很少使用,而是经常使用另外一个内置用户:ServiceAccount,下面对ServiceAccount进行介绍。
三、ServiceAccount
Service Account也是一种账号,但它并不是给Kubernetes集群的用户(系统管理员、运维人员、租户用户等)用的,而是给运行在Pod里的进程用的,它为Pod里的进程提供了必要的身份证明。
我们通过一个例子来了解ServiceAccount的授权过程。
1、首先定义一个ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: devops
name: sa-demo
一个简单的ServiceAccount只需要简单的namespace和name即可。
2、编写RoleBinding的YAML文件来为这个ServiceAccount分配权限:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: sa-rolebinding
namespace: devops
subjects:
- kind: ServiceAccount
name: sa-demo
namespace: devops
roleRef:
kind: Role
name: role-demo
apiGroup: rbac.authorization.k8s.io
然后我们创建上面定义的YAML文件,查看创建完成后的信息:
[root@master rbac]# kubectl describe sa sa-demo -n devops
Name: sa-demo
Namespace: devops
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"sa-demo","namespace":"devops"}}
Image pull secrets: <none>
Mountable secrets: sa-demo-token-bh5t6
Tokens: sa-demo-token-bh5t6
Events: <none>
[root@master rbac]# kubectl get sa sa-demo -o yaml
Error from server (NotFound): serviceaccounts "sa-demo" not found
[root@master rbac]# kubectl get sa sa-demo -o yaml -n devops
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"sa-demo","namespace":"devops"}}
creationTimestamp: "2019-10-25T07:39:11Z"
name: sa-demo
namespace: devops
resourceVersion: "881913"
selfLink: /api/v1/namespaces/devops/serviceaccounts/sa-demo
uid: 83fab159-25a6-499d-8df3-673f4512074b
secrets:
- name: sa-demo-token-bh5t6
[root@master rbac]# kubectl get secret -n devops
NAME TYPE DATA AGE
default-token-v99dn kubernetes.io/service-account-token 3 26m
sa-demo-token-bh5t6 kubernetes.io/service-account-token 3 24m
我们可以看到Kubernetes会自动创建一个Secret对象,这个Secret对象就是引用sa-demo的ServiceAccount对象与API Server进行交互的授权文件。它的内容一般是证书文件或者密码,以Secret对象的形式保存在Etcd中。
然后我们创建一个Pod,来使用ServiceAccount进行权限管理,如下:
pod-sa-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-sa-demo
namespace: devops
spec:
serviceAccountName: sa-demo
containers:
- name: pod-sa-demo
image: nginx
imagePullPolicy: IfNotPresent
然后创建这个Pod,查看Pod的信息:
[root@master rbac]# kubectl describe pod pod-sa-demo -n devops
Name: pod-sa-demo
Namespace: devops
Priority: 0
Node: 172.16.1.130/172.16.1.130
Start Time: Fri, 25 Oct 2019 16:12:08 +0800
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"pod-sa-demo","namespace":"devops"},"spec":{"containers":[{"image":"ng...
Status: Running
IP: 172.20.2.125
Containers:
pod-sa-demo:
Container ID: docker://6e99d1c0d0b16651b486b3307f638b8f12bde87a90ba818b435abd6d258b2604
Image: nginx
Image ID: docker-pullable://nginx@sha256:77ebc94e0cec30b20f9056bac1066b09fbdc049401b71850922c63fc0cc1762e
Port: <none>
Host Port: <none>
State: Running
Started: Fri, 25 Oct 2019 16:12:11 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from sa-demo-token-bh5t6 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
sa-demo-token-bh5t6:
Type: Secret (a volume populated by a Secret)
SecretName: sa-demo-token-bh5t6
Optional: false
QoS Class: BestEffort
......
我们可以看到ServiceAccount的Secret对象自动挂载到容器的/var/run/secrets/kubernetes.io/serviceaccount目录。我们进入容器查看:
[root@master rbac]# kubectl exec -it pod-sa-demo -n devops -- /bin/bash
root@pod-sa-demo:/# ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt namespace token
其中ca,crt就是用来访问API Server的。
如果一个Pod在定义时没有指定spec.serviceAccountName属性,则系统会自动为其赋值为default,即大家都使用同一个Namespace下的默认Service Account。
Subjects的kind类型除了User,ServiceAccount之外,还有一个Group,就是一组用户的意思。如果你为Kubernetes配置了外部认证服务的话,这个用户组就由外部认证服务提供。而对于Kubernetes内置用户ServiceAccount来说,其也有用户和用户组的概念,其中对于一个ServiceAccount,其在Kubernetes中对应的用户是:
system:serviceaccount:<ServiceAccount名字>
而对于其用户组是:
system:serviceaccounts:<Namespace名字>
比如我们定义下面这个RoleBinding:
subjects:
- kind: Group
name: system:serviceaccounts:devops
apiGroup: rbac.authorization.k8s.io
这就意味着Role这个角色的权限规则作用与devops的namespace中的所有ServiceAccount。
再比如:
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
这就意味着Role这个角色规则作用与整个集群的所有ServiceAccount。
kubernetes已经内置了许多ClusterRole,以system:开头,可以用kubectl get clusterrole查看。
另外,Kubernetes还提供了四个预先定义好的ClusterRole来供用户直接使用,它们是:
- cluster-admin:超管
- admin:普通管理权限
- edit:修改权限
- view:只读权限
我们在定义RoleBinding或ClusterRolebinding的时候可以直接使用。