RBAC:Role-Based Access Control,基于角色的访问控制。

Kubernetes中的所有API对象都保存在Etcd中的,而对这些API操作都是通过kube-apiserver来实现的,这是因为需要kube-apiserver来帮我们完成授权,而在Kubernetes中完成授权的机制就是RBAC。

其中RBAC中的基本概念为:

  1. Rule:规则,一组属于不同API Group的操作集合;
  2. Role:角色,用于定义一组对Kubernetes API对象操作的一组规则,作用于当个namespace;
  3. ClusterRole:集群角色,该角色不受namespace的限制;
  4. Subject:被作用者,也就是规则作用的对象;
  5. RoleBinding:将角色和被作用者进行绑定,作用于当个namespace;
  6. ClusterRoleBinding:将集群角色和作用者进行绑定,不受namespace限制;

一、Role和RoleBinding

Role本身就是一个Kubernetest API对象,其定义如下:
role-demo.yaml

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: Role
  3. metadata:
  4. name: role-demo
  5. namespace: devops
  6. rules:
  7. - apiGroups: [""]
  8. resources: ["pods", "deployment"]
  9. 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

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: RoleBinding
  3. metadata:
  4. name: joker-rolebinding
  5. namespace: devops
  6. subjects:
  7. - kind: User
  8. name: joker
  9. apiGroup: rbac.authorization.k8s.io
  10. roleRef:
  11. kind: Role
  12. name: role-demo
  13. 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字段而已,如下:

  1. ---
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: ClusterRole
  4. metadata:
  5. name: cluster-role-demo
  6. rules:
  7. - apiGroups: [""]
  8. resources: [""]
  9. verbs: ["watch", "list", "get"]
  10. ---
  11. apiVersion: rbac.authorization.k8s.io/v1
  12. kind: ClusterRoleBinding
  13. metadata:
  14. name: joker-clusterrolebinding
  15. subjects:
  16. - kind: User
  17. name: joker
  18. apiGroup: rbac.authorization.k8s.io
  19. roleRef:
  20. kind: ClusterRole
  21. name: cluster-role-demo
  22. apiGroup: rbac.authorization.k8s.io

上面定义的就是joker这个用户对所有namespace里的Pod都有watch,list,get的操作权限。如果要定义所有权限,可以将verbs字段定义如下:

  1. verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

类似的在Role和ClusterRole对象中的rules字段也可以更加细致化,比如要对某一个具体的对象进行操作,如下:

  1. rules:
  2. - apiGroups: [""]
  3. resources: ["configMap"]
  4. resourceName: ["myconfig"]
  5. verbs: ["get"]

这条规则定义被作用者只对名字为myconfig的configMap对象有get权限。

上面我们都使用Subjects中User类型得用户功能,但是在实际中我们很少使用,而是经常使用另外一个内置用户:ServiceAccount,下面对ServiceAccount进行介绍。

三、ServiceAccount

Service Account也是一种账号,但它并不是给Kubernetes集群的用户(系统管理员、运维人员、租户用户等)用的,而是给运行在Pod里的进程用的,它为Pod里的进程提供了必要的身份证明。

我们通过一个例子来了解ServiceAccount的授权过程。
1、首先定义一个ServiceAccount:

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. namespace: devops
  5. name: sa-demo

一个简单的ServiceAccount只需要简单的namespace和name即可。

2、编写RoleBinding的YAML文件来为这个ServiceAccount分配权限:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: RoleBinding
  3. metadata:
  4. name: sa-rolebinding
  5. namespace: devops
  6. subjects:
  7. - kind: ServiceAccount
  8. name: sa-demo
  9. namespace: devops
  10. roleRef:
  11. kind: Role
  12. name: role-demo
  13. apiGroup: rbac.authorization.k8s.io

然后我们创建上面定义的YAML文件,查看创建完成后的信息:

  1. [root@master rbac]# kubectl describe sa sa-demo -n devops
  2. Name: sa-demo
  3. Namespace: devops
  4. Labels: <none>
  5. Annotations: kubectl.kubernetes.io/last-applied-configuration:
  6. {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"sa-demo","namespace":"devops"}}
  7. Image pull secrets: <none>
  8. Mountable secrets: sa-demo-token-bh5t6
  9. Tokens: sa-demo-token-bh5t6
  10. Events: <none>
  11. [root@master rbac]# kubectl get sa sa-demo -o yaml
  12. Error from server (NotFound): serviceaccounts "sa-demo" not found
  13. [root@master rbac]# kubectl get sa sa-demo -o yaml -n devops
  14. apiVersion: v1
  15. kind: ServiceAccount
  16. metadata:
  17. annotations:
  18. kubectl.kubernetes.io/last-applied-configuration: |
  19. {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"sa-demo","namespace":"devops"}}
  20. creationTimestamp: "2019-10-25T07:39:11Z"
  21. name: sa-demo
  22. namespace: devops
  23. resourceVersion: "881913"
  24. selfLink: /api/v1/namespaces/devops/serviceaccounts/sa-demo
  25. uid: 83fab159-25a6-499d-8df3-673f4512074b
  26. secrets:
  27. - name: sa-demo-token-bh5t6
  28. [root@master rbac]# kubectl get secret -n devops
  29. NAME TYPE DATA AGE
  30. default-token-v99dn kubernetes.io/service-account-token 3 26m
  31. 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

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: pod-sa-demo
  5. namespace: devops
  6. spec:
  7. serviceAccountName: sa-demo
  8. containers:
  9. - name: pod-sa-demo
  10. image: nginx
  11. imagePullPolicy: IfNotPresent

然后创建这个Pod,查看Pod的信息:

  1. [root@master rbac]# kubectl describe pod pod-sa-demo -n devops
  2. Name: pod-sa-demo
  3. Namespace: devops
  4. Priority: 0
  5. Node: 172.16.1.130/172.16.1.130
  6. Start Time: Fri, 25 Oct 2019 16:12:08 +0800
  7. Labels: <none>
  8. Annotations: kubectl.kubernetes.io/last-applied-configuration:
  9. {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"pod-sa-demo","namespace":"devops"},"spec":{"containers":[{"image":"ng...
  10. Status: Running
  11. IP: 172.20.2.125
  12. Containers:
  13. pod-sa-demo:
  14. Container ID: docker://6e99d1c0d0b16651b486b3307f638b8f12bde87a90ba818b435abd6d258b2604
  15. Image: nginx
  16. Image ID: docker-pullable://nginx@sha256:77ebc94e0cec30b20f9056bac1066b09fbdc049401b71850922c63fc0cc1762e
  17. Port: <none>
  18. Host Port: <none>
  19. State: Running
  20. Started: Fri, 25 Oct 2019 16:12:11 +0800
  21. Ready: True
  22. Restart Count: 0
  23. Environment: <none>
  24. Mounts:
  25. /var/run/secrets/kubernetes.io/serviceaccount from sa-demo-token-bh5t6 (ro)
  26. Conditions:
  27. Type Status
  28. Initialized True
  29. Ready True
  30. ContainersReady True
  31. PodScheduled True
  32. Volumes:
  33. sa-demo-token-bh5t6:
  34. Type: Secret (a volume populated by a Secret)
  35. SecretName: sa-demo-token-bh5t6
  36. Optional: false
  37. QoS Class: BestEffort
  38. ......

我们可以看到ServiceAccount的Secret对象自动挂载到容器的/var/run/secrets/kubernetes.io/serviceaccount目录。我们进入容器查看:

  1. [root@master rbac]# kubectl exec -it pod-sa-demo -n devops -- /bin/bash
  2. root@pod-sa-demo:/# ls /var/run/secrets/kubernetes.io/serviceaccount
  3. 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中对应的用户是:

  1. system:serviceaccount:<ServiceAccount名字>

而对于其用户组是:

  1. system:serviceaccounts:<Namespace名字>

比如我们定义下面这个RoleBinding:

  1. subjects:
  2. - kind: Group
  3. name: system:serviceaccounts:devops
  4. apiGroup: rbac.authorization.k8s.io

这就意味着Role这个角色的权限规则作用与devops的namespace中的所有ServiceAccount。

再比如:

  1. subjects:
  2. - kind: Group
  3. name: system:serviceaccounts
  4. apiGroup: rbac.authorization.k8s.io

这就意味着Role这个角色规则作用与整个集群的所有ServiceAccount。

kubernetes已经内置了许多ClusterRole,以system:开头,可以用kubectl get clusterrole查看。

另外,Kubernetes还提供了四个预先定义好的ClusterRole来供用户直接使用,它们是:

  • cluster-admin:超管
  • admin:普通管理权限
  • edit:修改权限
  • view:只读权限

我们在定义RoleBinding或ClusterRolebinding的时候可以直接使用。