Kubernetes RBAC权限控制

实际生产环境中,往往需要对不同运维人员赋预不同的权限.而根据实际情况也可能会赋予开发人员只读的权限.这一节我们将介绍如何创建不同权限的用户.

1.K8S RBAC

RBAC (Role-Based Access Control)是基于角色的访问控制。

K8S RBAC 框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过 API Server 配置来启用插件。

  • Authentication 鉴权
  • Authorization 授权
  • Admission Control 准入控制

上面流程中 Authentication 鉴权插件将返回通过鉴权的主体;然后将其交给 Authorization 授权插件来检查主体是否有权限执行某个操作。

三种客户端 “访问用户” 类型:

  • User 用户
  • Group 用户组
  • ServerAccount K8S 资源对象 SA

三种 Authentication 鉴权方式:

客户端想要访问 K8S 集群 apiserver,可选三种客户端身份鉴权认证:

  • HTTPS 证书认证(kubeconfig):基于CA证书签名的数字证书认证
  • HTTP Token 认证:通过一个 Token 来识别用户
  • HTTP Base 认证:用户名+密码的方式认证(不常用)

Authorization 授权:

RBAC 授权逻辑通过将主体与角色绑定来决定是否可以执行某项操作。主体与角色关联,角色与资源权限关联。

Admission Control 准入控制:

Admission Control 实际上是一个准入控制插件列表,发送 API Server 的请求都需要经过这个列表的每个准入控制插件的检查,检查不通过,则拒绝请求。

2.RBAC 创建流程

(1)创建主体

选择一个主体类型,ServerAccount 是 K8S 较为常用的客户端主体类型。(上面有讲三种类型 user、group、ServerAccount)

(2)创建角色

角色两种 kind 类型:
  • Role 授权特定命名空间的访问权限
  • ClusterRole 授权所有命名空间的访问权限

Role 与 ClusterRole 最大区别在于,Role 有 namespace 区分,如果要应用在多个 namespace ,需要每个 namespace 下创建一个 Role。或者直接选择 ClusterRole 类型就不受 namespace 的限制。

为角色分配自定义资源权限:
  • apiGroups: K8S API 组,核心组为 “”,API Group
  • resources:K8S 资源对象,例如 Pod, Deployment, cronjob
  • verbs:资源操作方法 get, list, create, update, patch, watch, delete

apiGroups: K8S API 组也可以称之为 Legacy Groups,作为 k8s 最核心的 API ,其特点是没有组的概念,例如 “v1”,在资源对象的定义中表示为 “apiVersion: v1”,属于核心组的资源主要有下面几种:

  • Container
  • Pod
  • ReplicationController
  • Endpoint
  • Service
  • ConfigMap
  • Secret
  • Volume
  • PersistentVolumeClaim
  • Event
  • LimitRange
  • PodTemplate
  • Binding
  • ComponentStatus
  • Namespace
  • Node
  • jobs
  • cronjobs

kubectl api-resources -o wide 命令可以查看到资源、apiGroup API组、verbs 资源操作方法之间的关系。

1
2
3
4
5
6
> kubectl api-resources -o wide
NAME SHORTNAMES APIVERSION NAMESPACED KIND VERBS
bindings v1 true Binding [create]
componentstatuses cs v1 false ComponentStatus [get list]
nodes metrics.k8s.io/v1beta1 false NodeMetrics [get list]
pods metrics.k8s.io/v1beta1 true PodMetrics [get list]

(3)角色绑定主体

角色绑定主体的 kind 类型也有两种:
  • RoleBinding 将角色绑定到主体,即 subjects

  • ClusterRoleBinding 将集群角色绑定到主体

    subjects 就是鉴权的主体, kind 类型有三种:
  • User 用户

  • Group 用户组

  • ServerAccount K8S 资源对象 SA

3.案例

案例1:创建一个只有 default名称空间的只读用户的 token

思考创建流程:

主体(SA) -> 角色(Role) -> 角色绑定主体(RoleBinding)
创建主体

创建一个 SA 类型的 主体,注意主体是有名称空间的限制的。

1
2
3
4
5
6
7
8
$ mkdir -p /opt/kubernetes/cfg/rbac-user
$ vim serviceaccount-develop.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: develop
namespace: default

此时,基础组件里的 token-controller 自动(根据 –service-account-private-key-file 的证书)为 ServiceAccount 生成 secrets,secrets 中包含的 token 信息,即可用作http token请求中的认证信息。获取 SA TOKEN:

1
2
3
4
5
6
7
# 获取 secret name
$ kubectl get serviceaccount develop -o jsonpath={.secrets[0].name}
develop-token-7wc66

# 根据 secret name 获取 token,token 串需要 base64 解密
# kubectl get secret ${SECRET_NAME} -o jsonpath={.data.token} | base64 -d
$ kubectl get secret develop-token-7wc66 -o jsonpath={.data.token} | base64 -d

获取 serviceaccount 详细信息,方便排查问题。

1
2
3
kubectl describe serviceaccounts user-admin -n kube-system
kubectl get clusterrolebindings.rbac.authorization.k8s.io user-admin
kubectl describe clusterrolebindings.rbac.authorization.k8s.io develop-readonly
创建角色

创建角色 Role,分配常用资源只读权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ vim role-develop.yaml 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: develop
namespace: default
rules:
- apiGroups: [""]
resources: ["pods","pods/exec","pods/log","services"]
verbs: ["get", "list", "watch", "create"]
- apiGroups: ["apps"]
resources: ["deployments","daemonsets","statefulsets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs","cronjobs"]
verbs: ["get", "list", "watch"]
角色绑定主体

创建角色绑定 RoleBinding:

  • roleRef 绑定的角色规则
  • subject 绑定的角色的主体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ vim rolebinding-develop.yaml 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: develop
namespace: default
roleRef:
kind: Role
name: develop
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: develop
namespace: default

上述 RBAC 权限账号创建完成。由于 Role 和 Rolebinding 都在 default 下创建,所以只能访问 default 命名空间下的资源(仅限 Role 中配置的资源和 action)。

案例2:创建一个有所有名称空间的只读用户的 token

与案例1区别的是,使用的是 ClusterRole + ClusterRoleBinding,对所有 namespace 有权限,结合 Jumpserver 可以快速进入容器。

1
$ vim rbac-develop.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: develop
namespace: default

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: develop
rules:
- apiGroups: [""]
resources: ["pods","pods/exec","pods/log","services"]
verbs: ["get", "list", "watch", "create"]
- apiGroups: ["apps"]
resources: ["deployments","daemonsets","statefulsets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs","cronjobs"]
verbs: ["get", "list", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: develop
namespace: default
roleRef:
kind: ClusterRole
name: develop
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: develop
namespace: default

给程序员使用只读RBAC权限用户,结合Jumpserver可以快速进入容器排障。

案例3:创建超级管理员的 token

k8s创建管理员token

1
2
3
4
5
6
7
8
# 鉴权(HTTP Token):创建用户账户 
$ kubectl create serviceaccount user-admin -n kube-system

# 授权:为用户账户绑定权限
$ kubectl create clusterrolebinding user-admin --clusterrole=cluster-admin --serviceaccount=kube-system:user-admin

# 查看用户token
$ kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/user-admin/{print $1}')

案例4:创建一个只读SA用户:develop-readonly

kubernetes实战篇之创建一个只读权限的用户

创建用户
1
kubectl create serviceaccount develop-readonly -n kube-system

或者
serviceaccount-develop-readonly.yaml

1
2
3
4
5
6
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: develop-readonly
namespace: kube-system
创建策略

clusterrole-develop-readonly.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: develop-readonly
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- persistentvolumeclaims
- pods
- replicationcontrollers
- replicationcontrollers/scale
- serviceaccounts
- services
- nodes
- persistentvolumeclaims
- persistentvolumes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- bindings
- events
- limitranges
- namespaces/status
- pods/log
- pods/status
- replicationcontrollers/status
- resourcequotas
- resourcequotas/status
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- deployments/scale
- replicasets
- replicasets/scale
- statefulsets
verbs:
- get
- list
- watch
- apiGroups:
- autoscaling
resources:
- horizontalpodautoscalers
verbs:
- get
- list
- watch
- apiGroups:
- batch
resources:
- cronjobs
- jobs
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- daemonsets
- deployments
- deployments/scale
- ingresses
- networkpolicies
- replicasets
- replicasets/scale
- replicationcontrollers/scale
verbs:
- get
- list
- watch
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
- ingresses
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- storage.k8s.io
resources:
- storageclasses
- volumeattachments
verbs:
- get
- list
- watch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterrolebindings
- clusterroles
- roles
- rolebindings
verbs:
- get
- list
- watch
用户和策略绑定

clusterrolebinding-develop-readonly.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: develop-readonly
subjects:
- kind: ServiceAccount
name: develop-readonly
namespace: kube-system
roleRef:
kind: ClusterRole
name: develop-readonly
apiGroup: rbac.authorization.k8s.io
查看对应的权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
kubectl describe clusterrole  develop-readonly
Name: develop-readonly
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
bindings [] [] [get list watch create]
events [] [] [get list watch create]
limitranges [] [] [get list watch create]
namespaces/status [] [] [get list watch create]
pods/exec [] [] [get list watch create]
pods/log [] [] [get list watch create]
pods/status [] [] [get list watch create]
replicationcontrollers/status [] [] [get list watch create]
resourcequotas/status [] [] [get list watch create]
resourcequotas [] [] [get list watch create]
configmaps [] [] [get list watch]
endpoints [] [] [get list watch]
namespaces [] [] [get list watch]
nodes [] [] [get list watch]
persistentvolumeclaims [] [] [get list watch]
persistentvolumes [] [] [get list watch]
pods [] [] [get list watch]
replicationcontrollers/scale [] [] [get list watch]
replicationcontrollers [] [] [get list watch]
serviceaccounts [] [] [get list watch]
services [] [] [get list watch]
daemonsets.apps [] [] [get list watch]
deployments.apps/scale [] [] [get list watch]
deployments.apps [] [] [get list watch]
replicasets.apps/scale [] [] [get list watch]
replicasets.apps [] [] [get list watch]
statefulsets.apps [] [] [get list watch]
horizontalpodautoscalers.autoscaling [] [] [get list watch]
cronjobs.batch [] [] [get list watch]
jobs.batch [] [] [get list watch]
daemonsets.extensions [] [] [get list watch]
deployments.extensions/scale [] [] [get list watch]
deployments.extensions [] [] [get list watch]
ingresses.extensions [] [] [get list watch]
networkpolicies.extensions [] [] [get list watch]
replicasets.extensions/scale [] [] [get list watch]
replicasets.extensions [] [] [get list watch]
replicationcontrollers.extensions/scale [] [] [get list watch]
ingressclasses.networking.k8s.io [] [] [get list watch]
ingresses.networking.k8s.io [] [] [get list watch]
networkpolicies.networking.k8s.io [] [] [get list watch]
poddisruptionbudgets.policy [] [] [get list watch]
clusterrolebindings.rbac.authorization.k8s.io [] [] [get list watch]
clusterroles.rbac.authorization.k8s.io [] [] [get list watch]
rolebindings.rbac.authorization.k8s.io [] [] [get list watch]
roles.rbac.authorization.k8s.io [] [] [get list watch]
storageclasses.storage.k8s.io [] [] [get list watch]
volumeattachments.storage.k8s.io [] [] [get list watch]
查看token
1
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/develop-readonly/{print $1}')

参考资料1
参考资料2