0%

kubernetes中多用户的实践

有时候需要多个用户共用一个集群,这种情况需要为其分配一个新的用户;为了集群的安全性还需要限制新用户的权限范围;多个用户难免会有资源竞争的情况,这时还需要限制其资源使用。

Kubernetes提供了一系列机制以满足多用户的使用,包括多用户,鉴权,命名空间,资源限制等等。

接下来将创建一个名为staight的用户,其拥有practice命名空间下的管理员权限,该命名空间有着CPU,内存,Pod数量等限制。


创建用户

Kubernetes中的用户创建大体包括静态创建和动态创建两类。其中静态创建需要apiserver启动时提供用户信息文件;动态创建则可以在apiserver启动后动态添加。

动态创建的认证方式包括客户端证书认证和Service Account Token认证。如果能够登录至master的话建议使用客户端证书认证,这里尝试使用Service Account Token认证方式创建用户。

Service Account隶属于命名空间之下,因此首先创建namespace/practice:

1
2
[root@node k8s]# kubectl create namespace practice
namespace/practice created

每创建一个命名空间,都会为其新建一个serviceaccount/default,不过这里新建serviceaccount/staight:

1
2
[root@node k8s]# kubectl create -n practice serviceaccount staight
serviceaccount/staight created

此时一个新的用户staight就已经创建好了,只不过在apiserver看来,他的用户名全称应为:system:serviceaccount:practice:staight


切换用户

创建用户后还需要切换至该用户,kubectl命令提供了config子命令以完成这一目的,该命令本质上是修改了位于~/.kube/config的kubeconfig文件,因此也可以为新用户创建一个新的Linux用户,为其放置kubeconfig文件,以实现针对不同Linux用户使用不同的Kubernetes用户。

首先需要获取serviceaccount/staight用户的token:

1
2
3
4
5
6
7
8
9
10
11
12
[root@node k8s]# kubectl describe -n practice serviceaccount/staight |grep Token
Tokens: staight-token-fhd4c
[root@node k8s]# kubectl describe -n practice secret/staight-token-fhd4c
Name: staight-token-fhd4c
Namespace: practice
Type: kubernetes.io/service-account-token

Data
====
ca.crt: 1025 bytes
namespace: 8 bytes
token: <TOKEN_CONTENT>

<TOKEN_CONTENT>就是serviceaccount/staight的token,设置kubeconfig的user,其名称为staight:

1
2
[root@node k8s]# kubectl config set-credentials staight --token=<TOKEN_CONTENT>
User "staight" set.

然后设置context,名称为practice-context,引用user为staight,cluster为默认的local,命名空间为practice(使用kubectl命令时如不指定namespace,则默认为practice):

1
2
[root@node k8s]# kubectl config set-context practice-context --user=staight --cluster=local --namespace=practice
Context "practice-context" created.

最后,切换至该context:

1
2
[root@node k8s]# kubectl config use-context practice-context
Switched to context "practice-context".

尝试获取pod列表,发现无权限,不过可以验证用户切换成功:

1
2
[root@node k8s]# kubectl get pod
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:practice:staight" cannot list resource "pods" in API group "" in the namespace "practice"

授予权限

新创建的用户没有任何权限,因此需要为其授予权限,Kubernetes提供了多种权限授予方式,包括ABAC,Webhook,RBAC等等。

RBAC为Kubernetes默认且推荐的权限授予方式,如果想要使用其他方式,需修改apiserver启动参数。这里使用RBAC模式。

首先需要新建一个Role/ClusterRole资源并指定允许的权限,Kubernetes预设了clusterrole/admin,允许单个命名空间内除了资源配额和命名空间本身的写访问,很适合作为单个命名空间的管理员使用。因此这里不再新建role。

如果想知道clusterrole/admin到底授予了什么样的权限,可以使用describe命令查看:

1
2
3
4
5
6
7
8
[root@node k8s]# kubectl describe clusterrole admin
Name: admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
...

接下来需要将clusterrole/admin绑定至serviceaccount/staight上:

1
2
[root@node k8s]# kubectl create rolebinding practice-admin --clusterrole=admin --serviceaccount=practice:staight --namespace=practice
rolebinding.rbac.authorization.k8s.io/practice-admin created

如上,为staight用户授予了practice命名空间的admin角色,如果需要让该用户管理多个命名空间,更改--namespace参数再次创建即可。

切换至staight用户,尝试获取practice命名空间下的Service Account:

1
2
3
4
5
6
[root@node k8s]# kubectl config use-context practice-context 
Switched to context "practice-context".
[root@node k8s]# kubectl get serviceaccounts
NAME SECRETS AGE
default 1 54m
staight 1 49m

成功获取,授权成功。

大部分情况下,完成新用户对单个命名空间的管理权限就已经可以了,不过如果需要对其资源使用做进一步的限制的话,还需修改命名空间的资源配额。


资源配额

资源配额是一个用于限制一个命名空间下资源使用的机制,其包括如下两个对象:

  • ResourceQuota:限制单个命名空间下的资源使用量。包括CPU,内存,存储,资源对象的个数等等。
  • LimitRanger:为容器的Limits和Requests设置默认值和范围约束。

ResourceQuota

示例:为practice命名空间设置资源配额

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
namespace: practice
spec:
hard:
pods: "2"
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi

如上,对pod数量和使用的requests与limits值做了限制。可以使用describe命令查看目前的资源使用量和限制:

1
2
3
4
5
6
7
8
9
10
[root@node k8s]# kubectl describe resourcequotas 
Name: compute-resources
Namespace: practice
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
pods 0 2
requests.cpu 0 1
requests.memory 0 1Gi

尝试创建两个Pod,再次创建后报错:

1
2
[root@node k8s]# kubectl create -f pod.yml 
Error from server (Forbidden): error when creating "pod.yml": pods "alpine2" is forbidden: exceeded quota: compute-resources, requested: pods=1, used: pods=2, limited: pods=2

resourcequota对相当多的资源提供了限制,详细内容可参考文档:https://kubernetes.io/docs/concepts/policy/resource-quotas/#compute-resource-quota

LimitRanger

LimitRanger用于为容器设置默认的requests和limits值,以及限制其范围。

示例:限制practice命名空间下容器的requests值和limits值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: LimitRange
metadata:
name: memory-range
namespace: practice
spec:
limits:
- max: # 限制容器最大limits值
memory: 20Mi
min: # 限制容器最小limits值
memory: 10Mi
default: # 默认limits值
memory: 10Mi
defaultRequest: # 默认requests值
memory: 10Mi
type: Container

如上,如创建Pod时未指定limits和requests值,则自动为其添加requests.memory: 10Milimits.memory: 10Mi;如创建时limits.memory值小于10Mi或大于20Mi,则会拒绝该请求:

1
2
[root@node k8s]# kubectl create -f pod.yml 
Error from server (Forbidden): error when creating "pod.yml": pods "alpine2" is forbidden: maximum memory usage per Container is 20Mi, but limit is 30Mi.

小结

Kubernetes多用户的实践包括创建用户,授予权限,资源配额。本文章做了一个初步的演示,但在实际环境中,应当对用户认证方式的选择,授予什么样的权限,和资源的配额做更为周全的打算。


参考文档

Resource Quotas:https://kubernetes.io/docs/concepts/policy/resource-quotas/

RBAC——基于角色的访问控制:https://jimmysong.io/kubernetes-handbook/concepts/rbac.html

Configure Memory and CPU Quotas for a Namespace:https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/

Configure Minimum and Maximum Memory Constraints for a Namespace:https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/memory-constraint-namespace/