08 安全重点 认证和授权

本节我们将开始学习将 K8S 应用于生产环境中至关重要的一环,权限控制。当然,不仅是 K8S 对于任何应用于生产环境中的系统,权限管理或者说访问控制都是很重要的。

整体概览

通过前面的学习,我们已经知道 K8S 中几乎所有的操作都需要经过 kube-apiserver 处理,所以为了安全起见,K8S 为它提供了三类安全访问的措施。分别是:用于识别用户身份的认证(Authentication),用于控制用户对资源访问的授权(Authorization)以及用于资源管理方面的准入控制(Admission Control)。

下面的图基本展示了这一过程。来自客户端的请求分别经过认证,授权,准入控制之后,才能真正执行。

当然,这里说基本展示是因为我们可以直接通过 kubectl proxy 的方式直接通过 HTTP 请求访问 kube-apiserver 而无需任何认证过程。

另外,也可通过在 kube-apiserver 所启动的机器上,直接访问启动时 --insecure-port 参数配置的端口进行绕过认证和授权,默认是 8080。为了避免安全问题,也可将此参数设置为 0 以规避问题。注意:这个参数和 --insecure-bind-address 都已过期,并将在未来的版本移除。

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
+-----------------------------------------------------------------------------------------------------------+

| |

| +---------------------------------------------------------------------------+ +--------+ |

| | | | | |

| +--------+ | +------------------+ +----------------+ +--------------+ +------+ | | | |

| | | | | | | | | Admission | | | | | | |

| | Client +------> | Authentication +-> | Authorization +-> | Control +-> |Logic | +--> | Others | |

| | | | | | | | | | | | | | | |

| +--------+ | +------------------+ +----------------+ +--------------+ +------+ | | | |

| | | | | |

| | | | | |

| | Kube-apiserver | | | |

| +---------------------------------------------------------------------------+ +--------+ |

| |

+-----------------------------------------------------------------------------------------------------------+

认证(Authentication)

认证,无非是判断当前发起请求的用户身份是否正确。例如,我们通常登录服务器时候需要输入用户名和密码,或者 SSH Keys 之类的。

在讲认证前,我们应该先理一下 K8S 中的用户。

K8S 中有两类用户,一般用户及 Service Account

  • 一般用户:一般用户只能通过外部服务进行管理,由管理员进行私钥分发。这也意味着 K8S 中并没有任何表示一般用户的对象,所以一般用户是无法通过 API 直接添加到集群的。
  • Service Account:由 K8S API 管理的用户,与特定的 NameSpace(命名空间)绑定。由 API Server 自动创建或者通过 API 手动进行创建。 同时,它会自动挂载到 Pod 中容器的 /var/run/secrets/kubernetes.io/serviceaccount/ 目录中,其中会包含 NameSpace token 等信息,并允许集群内进程与 API Server 进行交互。

对集群操作的 API 都是与用户相关联的,或者被视为匿名请求。匿名请求可通过 kube-apiserver--anonymous-auth 参数进行控制,默认是开启的,匿名用户默认的用户名为 system:anonymous,所属组为 system:unauthenticated

理完 K8S 中的用户,我们来看下 K8S 中的认证机制。

K8S 支持以下认证机制:

  • X509 客户端证书:这个认证机制我们并不陌生,我们前面搭建集群时,虽然没有指定配置文件,但 kubeadm 已经添加了默认参数 --client-ca-file=/etc/kubernetes/pki/ca.crt 而在进行认证时,将会使用客户端证书 subject 的 CN 域(Common Name)用作用户名,O 域(Organization)用作组名。
  • 引导 Token:这个我们也不会陌生,前面我们搭建集群时,当集群通过 kubeadm init 初始化完成后,将会展示一行提示,其中便携带着引导 Token。如果不使用 kubeadm 时,需要设置 --enable-bootstrap-token-auth=true
  • 静态 Token 文件:启动 Kube-apiserver 时,设置 --token-auth-file=SOMEFILE 并在请求时,加上 Authorization: Bearer TOKEN 的请求头即可。
  • 静态密码文件:与静态 Token 文件类似,设置 --basic-auth-file=SOMEFILE 并在请求时,加上 Authorization: Basic BASE64ENCODED(USER:PASSWORD) 的头即可。
  • Service Account Token:这是默认启用的机制,关于 Service Account 前面也已经介绍过了,不再赘述。
  • OpenID:其实是提供了 OAuth2 的认证支持,像 Azure 或 Google 这类云厂商都提供了相关支持。
  • 认证代理:主要是配合身份验证代理进行使用,比如提供一个通用的授权网关供用户使用。
  • Webhook:提供 Webhook 配合一个远端服务器使用。

可选择同时开启多个认证机制。比如当我们使用 kubeadm 创建集群时,默认便会开启 X509 客户端证书和引导 Token 等认证机制。

授权(Authorization)

授权,也就是在验证当前发起请求的用户是否有相关的权限。例如,我们在 Linux 系统中常见的文件夹权限之类的。

授权是以认证的结果为基础的,授权机制检查用户通过认证后的请求中所包含的属性来进行判断。

K8S 支持多种授权机制,用户想要正确操作资源,则必须获得授权,所以 K8S 默认情况下的权限都是拒绝。当某种授权机制通过或者拒绝后,便会立即返回,不再去请求其他的授权机制;当所有授权机制都未通过时便会返回 403 错误了。

K8S 支持以下授权机制:

  • ABAC(Attribute-Based Access Control):基于属性的访问控制,在使用时需要先配置 --authorization-mode=ABAC--authorization-policy-file=SOME_FILENAME 。ABAC 本身设计是非常好的,但是在 K8S 中使用却有点过于繁琐,这里不再赘述。
  • RBAC(Role-based access control):基于角色的访问控制,自 K8S 1.6 开始 beta,1.8 进入稳定版,已被大量使用。而当我们使用 kubeadm 安装集群的时候,默认将会添加 --authorization-mode=Node,RBAC 的参数,表示同时开启 NodeRBAC 授权机制。当然,如果你对 MongoDB 有所了解或者比较熟悉的话,这部分的内容就会很容易理解,因为 MongoDB 的权限控制也使用了 RBAC (Role-based access control)。
  • Node:这是一种特殊用途的授权机制,专门用于对 kubelet 发出的 API 请求做授权验证。
  • Webhook:使用外部的 Server 通过 API 进行授权校验,需要在启动时候增加 --authorization-webhook-config-file=SOME_FILENAME 以及 --authorization-mode=Webhook
  • AlwaysAllow:默认配置,允许全部。
  • AlwaysDeny:通常用于测试,禁止全部。

角色(Role)

上面提到了 RBAC,为了能更好的理解,我们需要先认识下 K8S 中的角色。K8S 中的角色从类别上主要有两类,RoleClusterRole

  • Role:可以当作是一组权限的集合,但被限制在某个 Namespace 内(K8S 的 Namespace)。
  • ClusterRole:对于集群级别的资源是不被 Namespace 所限制的,并且还有一些非资源类的请求,所以便产生了它。

当已经了解到角色后,剩下给用户授权也就只是需要做一次绑定即可。在 K8S 中将这一过程称之为 binding,即 rolebindingclusterrolebinding。 我们来看下集群刚初始化后的情况:

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
➜  ~ kubectl get roles --all-namespaces=true

NAMESPACE NAME AGE

kube-public kubeadm:bootstrap-signer-clusterinfo 1h

kube-public system:controller:bootstrap-signer 1h

kube-system extension-apiserver-authentication-reader 1h

kube-system kube-proxy 1h

kube-system kubeadm:kubelet-config-1.12 1h

kube-system kubeadm:nodes-kubeadm-config 1h

kube-system system::leader-locking-kube-controller-manager 1h

kube-system system::leader-locking-kube-scheduler 1h

kube-system system:controller:bootstrap-signer 1h

kube-system system:controller:cloud-provider 1h

kube-system system:controller:token-cleaner 1h

➜ ~ kubectl get rolebindings --all-namespaces=true

NAMESPACE NAME AGE

kube-public kubeadm:bootstrap-signer-clusterinfo 1h

kube-public system:controller:bootstrap-signer 1h

kube-system kube-proxy 1h

kube-system kubeadm:kubelet-config-1.12 1h

kube-system kubeadm:nodes-kubeadm-config 1h

kube-system system::leader-locking-kube-controller-manager 1h

kube-system system::leader-locking-kube-scheduler 1h

kube-system system:controller:bootstrap-signer 1h

kube-system system:controller:cloud-provider 1h

kube-system system:controller:token-cleaner 1h

可以看到默认已经存在了一些 rolerolebindings。 对于这部分暂且不做过多说明,我们来看下对于集群全局有效的 ClusterRole

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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
➜  ~ kubectl get clusterroles

NAME AGE

admin 1h

cluster-admin 1h

edit 1h

flannel 1h

system:aggregate-to-admin 1h

system:aggregate-to-edit 1h

system:aggregate-to-view 1h

system:auth-delegator 1h

system:aws-cloud-provider 1h

system:basic-user 1h

system:certificates.k8s.io:certificatesigningrequests:nodeclient 1h

system:certificates.k8s.io:certificatesigningrequests:selfnodeclient 1h

system:controller:attachdetach-controller 1h

system:controller:certificate-controller 1h

system:controller:clusterrole-aggregation-controller 1h

system:controller:cronjob-controller 1h

system:controller:daemon-set-controller 1h

system:controller:deployment-controller 1h

system:controller:disruption-controller 1h

system:controller:endpoint-controller 1h

system:controller:expand-controller 1h

system:controller:generic-garbage-collector 1h

system:controller:horizontal-pod-autoscaler 1h

system:controller:job-controller 1h

system:controller:namespace-controller 1h

system:controller:node-controller 1h

system:controller:persistent-volume-binder 1h

system:controller:pod-garbage-collector 1h

system:controller:pv-protection-controller 1h

system:controller:pvc-protection-controller 1h

system:controller:replicaset-controller 1h

system:controller:replication-controller 1h

system:controller:resourcequota-controller 1h

system:controller:route-controller 1h

system:controller:service-account-controller 1h

system:controller:service-controller 1h

system:controller:statefulset-controller 1h

system:controller:ttl-controller 1h

system:coredns 1h

system:csi-external-attacher 1h

system:csi-external-provisioner 1h

system:discovery 1h

system:heapster 1h

system:kube-aggregator 1h

system:kube-controller-manager 1h

system:kube-dns 1h

system:kube-scheduler 1h

system:kubelet-api-admin 1h

system:node 1h

system:node-bootstrapper 1h

system:node-problem-detector 1h

system:node-proxier 1h

system:persistent-volume-provisioner 1h

system:volume-scheduler 1h

view 1h

➜ ~ kubectl get clusterrolebindings

NAME AGE

cluster-admin 1h

flannel 1h

kubeadm:kubelet-bootstrap 1h

kubeadm:node-autoapprove-bootstrap 1h

kubeadm:node-autoapprove-certificate-rotation 1h

kubeadm:node-proxier 1h

system:aws-cloud-provider 1h

system:basic-user 1h

system:controller:attachdetach-controller 1h

system:controller:certificate-controller 1h

system:controller:clusterrole-aggregation-controller 1h

system:controller:cronjob-controller 1h

system:controller:daemon-set-controller 1h

system:controller:deployment-controller 1h

system:controller:disruption-controller 1h

system:controller:endpoint-controller 1h

system:controller:expand-controller 1h

system:controller:generic-garbage-collector 1h

system:controller:horizontal-pod-autoscaler 1h

system:controller:job-controller 1h

system:controller:namespace-controller 1h

system:controller:node-controller 1h

system:controller:persistent-volume-binder 1h

system:controller:pod-garbage-collector 1h

system:controller:pv-protection-controller 1h

system:controller:pvc-protection-controller 1h

system:controller:replicaset-controller 1h

system:controller:replication-controller 1h

system:controller:resourcequota-controller 1h

system:controller:route-controller 1h

system:controller:service-account-controller 1h

system:controller:service-controller 1h

system:controller:statefulset-controller 1h

system:controller:ttl-controller 1h

system:coredns 1h

system:discovery 1h

system:kube-controller-manager 1h

system:kube-dns 1h

system:kube-scheduler 1h

system:node 1h

system:node-proxier 1h

system:volume-scheduler 1h

可以看到 K8S 中默认已经有很多的 ClusterRoleclusterrolebindings 了,我们选择其中一个做下探究。

查看用户权限

我们一直都在使用 kubectl 对集群进行操作,那么当前用户是什么权限呢? 对应于 RBAC 中又是什么情况呢?

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
➜  ~ kubectl config current-context   # 获取当前上下文

[email protected] # 名为 kubernetes-admin 的用户,在名为 kubernetes 的 cluster 上

➜ ~ kubectl config view users -o yaml # 查看 user 配置,以下省略了部分内容

apiVersion: v1

clusters:

- cluster:

...

contexts:

- context:

cluster: kubernetes

user: kubernetes-admin

name: [email protected]

current-context: [email protected]

kind: Config

preferences: {}

users:

- name: kubernetes-admin

user:

client-certificate-data: REDACTED

client-key-data: REDACTED

client-certificate-data 的部分默认是不显示的,而它的内容实际是通过 base64 加密后的证书内容。我们可以通过通过以下方式进行查看

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
➜  ~ kubectl config view users --raw -o jsonpath='{ .users[?(@.name == "kubernetes-admin")].user.client-certificate-data}' |base64 -d  

-----BEGIN CERTIFICATE-----

MIIC8jCCAdqgAwIBAgIIGuC27C9B8LIwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE

...

kae1A/d4D5Cm5Qt7M5gr3SxqE5t+O7DP0YhuEPlfY7RzYDksYa8=

-----END CERTIFICATE-----

➜ ~ kubectl config view users --raw -o jsonpath='{ .users[?(@.name == "kubernetes-admin")].user.client-certificate-data}' |base64 -d |openssl x509 -text -noout # 限于篇幅 省略部分输出

Certificate:

Data:

Version: 3 (0x2)

Serial Number: 1936748965290700978 (0x1ae0b6ec2f41f0b2)

Signature Algorithm: sha256WithRSAEncryption

Issuer: CN=kubernetes

Subject: O=system:masters, CN=kubernetes-admin

...

根据前面认证部分的内容,我们知道当前的用户是 kubernetes-admin (CN 域),所属组是 system:masters (O 域) 。

我们看下 clusterrolebindings 中的 cluster-admin

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
➜  ~ kubectl get clusterrolebindings  cluster-admin  -o yaml                         

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRoleBinding

metadata:

annotations:

rbac.authorization.kubernetes.io/autoupdate: "true"

...

labels:

kubernetes.io/bootstrapping: rbac-defaults

name: cluster-admin

resourceVersion: "116"

selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/cluster-admin

uid: 71c550f1-e0e4-11e8-866a-fa163e938a99

roleRef:

apiGroup: rbac.authorization.k8s.io

kind: ClusterRole

name: cluster-admin

subjects:

- apiGroup: rbac.authorization.k8s.io

kind: Group

name: system:masters

重点内容在 roleRefsubjects 中,名为 cluster-adminClusterRole 与名为 system:mastersGroup 相绑定。我们继续探究下它们所代表的含义。

先看看这个 ClusterRole 的实际内容:

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
➜  ~ kubectl get clusterrole cluster-admin -o yaml

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRole

metadata:

annotations:

rbac.authorization.kubernetes.io/autoupdate: "true"

...

labels:

kubernetes.io/bootstrapping: rbac-defaults

name: cluster-admin

resourceVersion: "58"

selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/cluster-admin

uid: 71307108-e0e4-11e8-866a-fa163e938a99

rules:

- apiGroups:

- '*'

resources:

- '*'

verbs:

- '*'

- nonResourceURLs:

- '*'

verbs:

- '*'

rules 中定义了它所能操作的资源及对应动作,* 是通配符。

到这里,我们就可以得出结论了,当前用户 kubernetes-admin 属于 system:masters 组,而这个组与 cluster-admin 这个 ClusterRole 所绑定,所以用户也就继承了其权限。具备了对多种资源和 API 的相关操作权限。

实践:创建权限可控的用户

前面是通过实际用户来反推它所具备的权限,接下来我们开始实践的部分,创建用户并为它进行授权。

我们要创建的用户名为 backend 所属组为 dev

创建 NameSpace

为了演示,这里创建一个新的 NameSpace ,名为 work

1
2
3
4
5
6
7
8
9
➜  ~ kubectl create namespace work

namespace/work created

➜ ~ kubectl get ns work

NAME STATUS AGE

work Active 14s

创建用户

创建私钥

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
➜  ~ mkdir work

➜ ~ cd work

➜ work openssl genrsa -out backend.key 2048

Generating RSA private key, 2048 bit long modulus

..........................................+++

........................+++

e is 65537 (0x10001)

➜ work ls

backend.key
➜ work cat backend.key

-----BEGIN RSA PRIVATE KEY-----

MIIEpAIBAAKCAQEAzk7blZthwSzachPxrk6pHsuaImTVh6Iw8mNDmtn6sqOqBfZS

...

bNKDWDk8HZREugaOAwjt7xaWOlr9SPCCoXrWoaA1z2215IC4qSA2Nw==

-----END RSA PRIVATE KEY-----

使用私钥生成证书请求。前面已经讲过关于认证的部分,在这里需要指定 subject 信息,传递用户名和组名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  work openssl req -new -key backend.key -out backend.csr -subj "/CN=backend/O=dev"

➜ work ls

backend.csr backend.key

➜ work cat backend.csr

-----BEGIN CERTIFICATE REQUEST-----

MIICZTCCAU0CAQAwIDEQMA4GA1UEAwwHYmFja2VuZDEMMAoGA1UECgwDZGV2MIIB

...

lpoSVlNA0trJoiEiZjUqMfXX6ogBhQC4aeRfmbXkW2ZCNxsIm3PDk1Y=

-----END CERTIFICATE REQUEST-----

使用 CA 进行签名。K8S 默认的证书目录为 /etc/kubernetes/pki

1
2
3
4
5
6
7
8
9
10
11
➜  work openssl x509 -req -in backend.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out backend.crt -days 365

Signature ok

subject=/CN=backend/O=dev

Getting CA Private Key

➜ work ls

backend.crt backend.csr backend.key

查看生成的证书文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
➜  work openssl x509 -in backend.crt -text -noout

Certificate:

Data:

Version: 1 (0x0)

Serial Number:

d9:7f:62:f7:38:66:2a:7b

Signature Algorithm: sha256WithRSAEncryption

Issuer: CN=kubernetes

Subject: CN=backend, O=dev

...

可以看到 CN 域和 O 域已经正确设置

添加 context

1
2
3
4
5
6
7
➜  work kubectl config set-credentials backend --client-certificate=/root/work/backend.crt  --client-key=/root/work/backend.key

User "backend" set.

➜ work kubectl config set-context backend-context --cluster=kubernetes --namespace=work --user=backend

Context "backend-context" created.

使用新用户测试访问

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
➜  work kubectl --context=backend-context get pods

Error from server (Forbidden): pods is forbidden: User "backend" cannot list resource "pods" in API group "" in the namespace "work"

# 可能看得不够清楚,我们添加 `-v` 参数来显示详情

➜ work kubectl --context=backend-context get pods -n work -v 5

I1109 05:35:11.870639 18626 helpers.go:201] server response object: [{

"kind": "Status",

"apiVersion": "v1",

"metadata": {},

"status": "Failure",

"message": "pods is forbidden: User \"backend\" cannot list resource \"pods\" in API group \"\" in the namespace \"work\"",

"reason": "Forbidden",

"details": {

"kind": "pods"

},

"code": 403

}]

F1109 05:35:11.870688 18626 helpers.go:119] Error from server (Forbidden): pods is forbidden: User "backend" cannot list resource "pods" in API group "" in the namespace "work"

可以看到已经使用了新的 backend 用户,并且默认的 Namespace 设置成了 work

创建 Role

我们想要让这个用户只具备查看 Pod 的权限。先来创建一个配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
➜  work cat <<EOF > backend-role.yaml 

kind: Role

apiVersion: rbac.authorization.k8s.io/v1

metadata:

namespace: work

name: backend-role

rules:

- apiGroups: [""]

resources: ["pods"]

verbs: ["get", "list", "watch"]

EOF

创建并查看已生成的 Role

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
➜  work kubectl create -f backend-role.yaml 

role.rbac.authorization.k8s.io/backend-role created

➜ work kubectl get roles -n work -o yaml

apiVersion: v1

items:

- apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

...

name: backend-role

namespace: work

selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/work/roles/backend-role

rules:

- apiGroups:

- ""

resources:

- pods

verbs:

- get

- list

- watch

kind: List

metadata:

resourceVersion: ""

selfLink: ""

创建 Rolebinding

先创建一个配置文件。

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
➜  work cat <<EOF > backend-rolebind.yaml

kind: RoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: backend-rolebinding

namespace: work

subjects:

- kind: User

name: backend

apiGroup: ""

roleRef:

kind: Role

name: backend-role

apiGroup: ""

EOF

创建并查看已生成的 Rolebinding 。

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
➜  work kubectl create -f backend-rolebind.yaml

rolebinding.rbac.authorization.k8s.io/backend-rolebinding created

➜ work kubectl get rolebinding -o yaml -n work

apiVersion: v1

items:

- apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

name: backend-rolebinding

namespace: work

...

roleRef:

apiGroup: rbac.authorization.k8s.io

kind: Role

name: backend-role

subjects:

- apiGroup: rbac.authorization.k8s.io

kind: User

name: backend

kind: List

metadata:

resourceVersion: ""

selfLink: ""

测试用户权限

1
2
3
4
5
6
7
8
9
10
11
➜  work kubectl --context=backend-context get pods -n work

No resources found.

➜ work kubectl --context=backend-context get ns

Error from server (Forbidden): namespaces is forbidden: User "backend" cannot list resource "namespaces" in API group "" at the cluster scope

➜ work kubectl --context=backend-context get deploy -n work

Error from server (Forbidden): deployments.extensions is forbidden: User "backend" cannot list resource "deployments" in API group "extensions" in the namespace "work"

可以看到用户已经具备查看 Pod 的权限,但并不能查看 Namespace 或者 deployment 等其他资源。当然,K8S 也内置了一种很方便的调试机制。

1
2
3
4
5
6
7
➜  work kubectl auth can-i list pods -n work --as="backend"

yes

➜ work kubectl auth can-i list deploy -n work --as="backend"

no - no RBAC policy matched

--as 是一种建立在 K8S 认证机制之上的机制,可以便于系统管理员验证授权情况,或进行调试。

你也可以仿照 ~/.kube/config 文件的内容,将当前生成的证书及私钥文件等写入到配置文件中,通过指定 KUBECONFIG 的环境变量,或者给 kubectl 传递 --kubeconfig 参数来使用。

总结

本节中,我们学习了 K8S 的认证及授权逻辑,K8S 支持多种认证及授权模式,可按需使用。通过 X509 客户端证书认证的方式使用比较方便也比较推荐,在客户端证书的 CN 域和 O 域可以指定用户名和所属组名。

RBAC 的授权模式现在使用最多,可以通过对 Rolesubjects (可以是用户或组) 进行绑定,以达到授权的目的。

最后,我们实际新创建了一个用户,并对其授予了预期的权限。在此过程中也涉及到了 openssl 客户端的常规操作,在之后也会常常用到。

下节,我们将开始部署实际的项目到 K8S 中,逐步掌握生成环境中对 K8S 的使用实践。

PS: 也许你会觉得切换 Namespace 之类的操作很繁琐,有一个项目:kubectx 可帮你简化这些步骤,推荐尝试。