部门角色权限rbac_k8s十 | 一文读懂基于角色的权限控制RBAC

一、ServiceAccount

. 1. ServiceAccount 介绍

首先Kubernetes中账户区分为:User Accounts(用户账户) 和 Service Accounts(服务账户) 两种,它们的设计区别如下:

  • UserAccount是给kubernetes集群外部用户使用的,例如运维或者集群管理人员,使用kubectl命令时用的就是UserAccount账户;UserAccount是全局性。在集群所有namespaces中,名称具有唯一性,默认情况下用户为admin;

  • ServiceAccount是给运行在Pod的程序使用的身份认证,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户;ServiceAccount仅局限它所在的namespace,每个namespace都会自动创建一个default service account;创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。

. 2. 默认Service Account

在上篇文章 k8s九 | 详解配置对象ConfigMap与Secret最后kubernetes.io/service-account-token一节中我们已经提到创建命名空间时会创建一个默认的Service Account,而ServiceAccout 创建时也会创建对应的 Secret,下面我们实际操作下。

创建命名空间

1$ kubectl  create  ns  anmin
2namespace/anmin created

查看命名空间的ServiceAccount

1$ kubectl  get sa -n anmin
2NAME      SECRETS   AGE
3default   1         27s

查看ServiceAccount的Secret

 1$ kubectl  describe  sa  default   -n anmin
2Name:                default
3Namespace:           anmin
4Labels:               5Annotations:          6Image pull secrets:   7Mountable secrets:   default-token-bskds 8Tokens:              default-token-bskds 9Events:              10$ kubectl  get  secret -n anmin11NAME                  TYPE                                  DATA   AGE12default-token-bskds   kubernetes.io/service-account-token   3      75s

可以看到在创建名为“anmin”的命名空间后,自动创建了名为“default”的ServiceAccount,并为“default”服务账户创建了对应kubernetes.io/service-account-token类型的secret。

创建一个Pod

 1apiVersion: v1
2kind: Pod
3metadata:
4  name: testpod
5  namespace: anmin
6spec:
7  containers:
8  - name: testpod
9    image: busybox
10    args: [/bin/sh, -c,
11            'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']

查看Pod的Service Account信息

 1$ kubectl  create -f anmin.yaml 
2pod/testpod created
3$ kubectl  describe pod  testpod  -n anmin
4..........
5    Mounts:
6      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bskds (ro)
7..........
8Volumes:
9  default-token-bskds:
10    Type:        Secret (a volume populated by a Secret)
11    SecretName:  default-token-bskds
12    Optional:    false
13.........

在不指定ServiceAccount的情况下,当前 namespace 下面的 Pod 会默认使用 “default” 这个 ServiceAccount,对应的 Secret 会自动挂载到 Pod 的 /var/run/secrets/kubernetes.io/serviceaccount/ 目录中,我们可以在 Pod 里面获取到用于身份认证的信息。

1$ kubectl  exec -it testpod -n anmin -- /bin/sh
2/ # ls /var/run/secrets/kubernetes.io/serviceaccount/
3ca.crt     namespace  token

. 3. 使用自定义的ServiceAccount

创建一个Service Account

 1$ kubectl  create sa anmin -n anmin
2serviceaccount/anmin created
3$ kubectl  get sa -n anmin
4NAME      SECRETS   AGE
5anmin     1         20s
6default   1         31m
7$ kubectl   get secret -n anmin
8NAME                  TYPE                                  DATA   AGE
9anmin-token-nkb8b     kubernetes.io/service-account-token   3      28s
10default-token-bskds   kubernetes.io/service-account-token   3      31m

Pod使用刚创建的ServiceAccount

 1apiVersion: v1
2kind: Pod
3metadata:
4  name: testpod
5  namespace: anmin
6spec:
7  containers:
8  - name: testpod
9    image: busybox
10    args: [/bin/sh, -c,
11            'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
12  serviceAccountName: anmin
13 ```
14 更新Pod
15 ```shell
16 $ kubectl   apply -f anmin.yaml 
17pod/testpod created
18$ kubectl  describe  pod  testpod -n anmin
19.........
20    Mounts:
21      /var/run/secrets/kubernetes.io/serviceaccount from anmin-token-nkb8b (ro)
22Conditions:
23  Type              Status
24  Initialized       True 
25  Ready             True 
26  ContainersReady   True 
27  PodScheduled      True 
28Volumes:
29  anmin-token-nkb8b:
30    Type:        Secret (a volume populated by a Secret)
31    SecretName:  anmin-token-nkb8b
32    Optional:    false
33    ............

可以看到更新后的Pod已经使用了新创建的ServiceAccount服务账户。

. 4. ServiceAccount中添加Image pull secrets

我们也可以在Service Account中设置imagePullSecrets,然后就会自动为使用该 SA 的 Pod 注入 imagePullSecrets 信息。

创建kubernetes.io/dockerconfigjson类型的私有仓库镜像Secret

1$ kubectl create secret docker-registry harbor --docker-server=http://192.168.166.229  --docker-username=admin   --docker-password=1234567  --docker-email=test@163.com   -n anmin
22secret/harbor created

将镜像仓库的Secret添加到ServiceAccount

 1$ kubectl  edit sa  anmin  -n anmin
2# Please edit the object below. Lines beginning with a '#' will be ignored,
3# and an empty file will abort the edit. If an error occurs while saving this file will be
4# reopened with the relevant failures.
5#
6apiVersion: v1
7kind: ServiceAccount
8metadata:
9  creationTimestamp: "2020-06-16T16:09:54Z"
10  name: anmin
11  namespace: anmin
12  resourceVersion: "37509823"
13  selfLink: /api/v1/namespaces/anmin/serviceaccounts/anmin
14  uid: c6bec7bb-808d-459f-86c8-6c78b48cb3ab
15secrets:
16- name: anmin-token-nkb8b
17imagePullSecrets:
18- name: harbor

查看ServiceAccount中Image pull secrets字段信息

1$ kubectl  describe sa  anmin -n  anmin 
2Name:                anmin
3Namespace:           anmin
4Labels:              5Annotations:         6Image pull secrets:  harbor7Mountable secrets:   anmin-token-nkb8b8Tokens:              anmin-token-nkb8b9Events:              

使用ServiceAccount拉取私有镜像部署Pod

 1apiVersion: v1
2kind: Pod
3metadata:
4  name: anmin2
5  namespace: anmin
6spec:
7  containers:
8  - name: anmin2
9    image: 192.168.166.229/1an/node-exporter:latest
10  serviceAccountName: anmin

更新Pod并查看状态

 1$ kubectl  apply -f harborsecret.yaml 
2pod/anmin2 created
3$ kubectl  get pod -n anmin
4NAME         READY   STATUS             RESTARTS   AGE
5anmin2       1/1     Running            0          20s
6$ kubectl describe pod  anmin2 -n anmin
7......
8Volumes:
9  anmin-token-nkb8b:
10    Type:        Secret (a volume populated by a Secret)
11    SecretName:  anmin-token-nkb8b
12    Optional:    false
13QoS Class:       BestEffort
14Node-Selectors:  15Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s16                 node.kubernetes.io/unreachable:NoExecute for 300s17Events:18  Type    Reason     Age   From                 Message19  ----    ------     ----  ----                 -------20  Normal  Pulling    8h    kubelet, k8s-node01  Pulling image "192.168.166.229/1an/node-exporter:latest"21  Normal  Pulled     8h    kubelet, k8s-node01  Successfully pulled image "192.168.166.229/1an/node-exporter:latest"

可以看到Pod已经成功从镜像仓库拉取镜像并正常运行。

二、RBAC

. 1. RBAC介绍

在Kubernetes 中所有资源对象都是通过 API 对象进行操作, 它们保存在 Etcd 里。而对Etcd的操作我们需要通过访问 kube-apiserver来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制则是通过RBAC:基于角色的访问控制实现的。

Role + RoleBinding + ServiceAccount 的权限分配方式是要重点掌握的内容。

RBAC的三个基本概念:

  1. Role:角色,其实是一组规则,定义了一组对 Kubernetes API 对象的操作权限;

  2. Subject:被作用者,既可以是“人”,也可以是“机器”,也就是在 Kubernetes 里定义的“用户”;

  3. RoleBinding:定义了“被作用者”和“角色”的绑定关系。

. 2. Role与RoleBinding

现在我们通过实际操作来理解RBAC的工作机制
创建一个Service Account

1$ kubectl  create sa  zhanmin-sa  -n kube-system
2serviceaccount/zhanmin created

定义一个Role对象 zhanmin-sa-role.yaml

 1apiVersion: rbac.authorization.k8s.io/v1
2kind: Role
3metadata:
4  name: zhanmin-sa-role
5  namespace: kube-system
6rules:
7- apiGroups: [""]
8  resources: ["pods"]
9  verbs: ["get", "watch", "list"]
10- apiGroups: ["apps"]
11  resources: ["deployments"]
12  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

在上面的文件我们定义了被作用的命名空间为:kube-system,其中的rules 字段,就是它所定义的权限规则。其中规则定义的角色对Pod没有创建、删除、更新的权限。

其中的“被作用者”我们则是通过RoleBinding  对象来指定。

定义Rolebinding对象 zhanmin-sa-rolebinding.yaml

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

subjects 字段,即“被作用者”。它的类型是 User,即 Kubernetes 里的用户,也就是上文中的Service Account,这里我们定义被作用者用户为“zhanmin-sa”。

roleRef则是定义:RoleBinding 对象可以直接通过名字,来引用我们前面定义的 Role 对象,也就是“zhanmin-sa-role”,从而定义了“被作用者(Subject)”和“角色(Role)”之间的绑定关系。

所以Pod使用名为“zhanmin-sa”的ServiceAccount访问API Server时只能够做对Pod做get", "watch", "list"操作。这是因为“zhanmin-sa” 这个 ServiceAccount 的权限,已经被我们绑定了 Role 做了限制。

注意:Role 和 RoleBinding 对象都是 Namespaced 对象(Namespaced Object),它们对权限的限制规则仅在它们自己的 Namespace 内有效,roleRef 也只能引用当前 Namespace 里的 Role 对象。

下面创建这些对象

1$ kubectl   create -f zhanmin-sa-role.yaml 
2role.rbac.authorization.k8s.io/zhanmin-sa-role created
3$ kubectl  create -f  zhanmin-sa-rolebinding.yaml 
4rolebinding.rbac.authorization.k8s.io/zhanmin-sa-rolebinding created

现在可以去之前部署的kubernetes-dashboard上验证权限
获取当前Service Account的Secret信息

1$ kubectl  get secret  -n kube-system
2zhanmin-sa-token-x6gxs                           kubernetes.io/service-account-token   3      136m
3$ kubectl   get secret   zhanmin-sa-token-x6gxs  -o jsonpath={.data.token} -n kube-system |base64 -d
4eyJhbGciOiJSUzI1NiIsImtpZCI6InJCZFhYLTVRc2E4STlGVVN0VzEwWlc2M1VGMVF0ZDZFaFdJQlc3V2RLMzAifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VeXN

现在可以去之前部署的kubernetes-dashboard上验证权限
命名空间修改为kube-system,因为上面我们已经说了Service Account只对当前的namespace有效。

4a4d86ce16dcc61f87b4b5ab008cc4e9.png
在这里插入图片描述
8cf26663e03686ec7b2662a87ac65bd7.png
在这里插入图片描述

可以看到,权限是符合我们上面的定义,只可以查看Pod和Deployments对象,查看其他资源比如SVC显示是没有数据的。后面我们可以根据自己的需求去查询API对象修改相应的权限规则。

. 3.  ClusterRole 和 ClusterRoleBinding

上面的Role和RoleBinding只可以在他们自己的命名空间中有效,如果我们需要一个具有全部命名空间或者对节点有权限的角色时,就需要使用ClusterRole 和 ClusterRoleBinding 对象来做授权了。

ClusterRole 和 ClusterRoleBinding 这两个 API 对象的用法跟 Role 和 RoleBinding 几乎完全一样。不一样的是,它们的定义里,没有了 Namespace 字段,权限可以作用于整个集群。

创建ClusterRole集群角色  clusterrole.yaml

1kind: ClusterRole
2apiVersion: rbac.authorization.k8s.io/v1
3metadata:
4  name: clusterrole-anmin
5rules:
6- apiGroups: [""]
7  resources: ["pods"]
8  verbs: ["get", "watch", "list"]

含义为:名为“clusterrole-anmin”的集群角色可以对集群所有命名空间的Pod进行“GET、Watch、List” 操作。

在Role 或者 ClusterRole 里面,如果要赋予用户 example-user 所有权限,那你就可以给它指定一个 verbs 字段的全集,如下所示:

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

创建 ClusterRoleBinding集群角色绑定  ClusterRoleBinding.yaml

 1kind: ClusterRoleBinding
2apiVersion: rbac.authorization.k8s.io/v1
3metadata:
4  name: example-clusterrolebinding
5subjects:
6- kind: User
7  name: user-anmin
8  apiGroup: rbac.authorization.k8s.io
9roleRef:
10  kind: ClusterRole
11  name: clusterrole-anmin
12  apiGroup: rbac.authorization.k8s.io

含义为:subjects字段定义被作用者用户为“user-anmin”,roleRef字段定义:绑定名为“clusterrole-anmin”集群角色。

在 Kubernetes 中已经内置了很多个为系统保留的 ClusterRole,它们的名字都以 system: 开头。你可以通过 kubectl get clusterroles查看到它们。

查看集群角色

1$ kubectl get clusterroles 
2NAME                                                                   AGE
3admin                                                                  242d
4calico-kube-controllers                                                211d
5calico-node                                                            211d
6cluster-admin                                                          242d
7cluster-regular                                                        217d
8edit                                                                   242d
9......

查看角色的权限

 1$ kubectl describe clusterrole edit 
2Name:         edit
3Labels:       kubernetes.io/bootstrapping=rbac-defaults
4              rbac.authorization.k8s.io/aggregate-to-admin=true
5Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
6PolicyRule:
7  Resources                                Non-Resource URLs  Resource Names  Verbs
8  ---------                                -----------------  --------------  -----
9  configmaps                               []                 []              [create delete deletecollection patch update get list watch]
10  endpoints                                []                 []              [create delete deletecollection patch update get list watch]
11  persistentvolumeclaims                   []                 []              [create delete deletecollection patch update get list watch]
12  pods                                     []                 []              [create delete deletecollection patch update get list watch]
13  replicationcontrollers/scale             []                 []              [create delete deletecollection patch update get list watch]
14......

. 4. Group用户组

Kubernetes 还拥有“用户组”(Group)的概念,也就是一组“用户”的意思。如果你为 Kubernetes 配置了外部认证服务的话,这个“用户组”的概念就会由外部认证服务提供。

ServiceAccount,在 Kubernetes 里对应的“用户”的名字是:

1system:serviceaccount:<Namespace名字>:<ServiceAccount名字>

对应的内置“用户组”的名字,就是:

1system:serviceaccounts:<Namespace名字>

比如,现在我们可以在 RoleBinding 里定义如下的 subjects:

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

这就意味着这个 Role 的权限规则,作用于 mynamespace 里的所有 ServiceAccount。这就用到了“用户组”的概念。而下面这个例子:

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

就意味着这个 Role 的权限规则,作用于整个系统里的所有 ServiceAccount。

总结:通过上面的实践,我们了解了在kubernetes中用户分为User Accounts和 Service Accounts,在我们平常的使用中会经常使用ServiceAccount。而对于权限的控制,我们需要先创建角色(Role),其实就是一组权限规则列表。然后我们分配这些权限的方式,就是通过创建 RoleBinding 对象,将被作用者(subject)Service Account和权限列表Role进行绑定,也就是Role + RoleBinding + ServiceAccount来实现。另外ClusterRole 和 ClusterRoleBinding,则是 Kubernetes 集群级别的 Role 和 RoleBinding,它们的作用范围不受 Namespace 限制。

参考资料:
https://time.geekbang.org/column/article/42154
https://www.qikqiak.com/k8s-book/docs/30.RBAC.html


关注公众号回复【k8s】获取视频教程及更多资料:

b0c3f5699d4509e63e8ca931d310e898.png
image.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值