kubernetes namespace quota

概述:

当多个用户共享一个集群时,会担心其中某个用户将资源全部抢占,影响其他用户,namespace quota就是帮助我们解决这个问题的。namespace quota,就像我们在Iaas中针对每个project设置quota一样,来达到租户使用资源控制。

环境:

os:ubuntu 16.04
docker:17.03
kubernetes:11.02

使用:

目前kubernetes提供两种资源配额控制策略
LimitRange:用来给namespace内的pod设置一个默认的request和limit值
ResourceQuota:用来限制namespace中资源的占用

ResourceQuota:
注意点:
1、当创建的资源超过配额所限制的数量时,请求将失败,会抛出403错误。
2、在配置namespace quota之前创建的资源对象还会被算到used里面。
3、使用ResourceQuota后创建pod时必须配置Resource的request和limit不然会创建失败,当然你可以直接结合LimitRange使用,因为配置了limirange后会自动给pod配置limit和request。
4、在集群资源总容量小于namespace的配额的情况下,可能会存在资源占用情况,以先到先得方式处理。

ResourceQuota能控制三种类型的资源
计算资源配额
主要控制一些物理资源如CPU、内存这些

存储资源配额
主要配置请求存储的总量,pvc的数量

对象数量配额
主要配置kubernetes内的资源的数量,比如控制namespace内能启动多少pod


先创建一个namespace

1
kubectl create namespace quota-object-example

使用以下yaml文件创建一个namespace quota,应用到quota-object-example这个namespace

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-quota-demo
spec:
hard:
persistentvolumeclaims: "1"
services.loadbalancers: "2"
services.nodeports: "0"

1
kubectl apply -f 1.yaml --namespace=quota-object-example

简单分析一下,这里限制只能创建一个pvc、一个loadblance。不能创建nodeport

1
kubectl get resourcequota object-quota-demo --namespace=quota-object-example --output=yaml

1
2
3
4
5
6
7
8
9
status:
hard:
persistentvolumeclaims: "1"
services.loadbalancers: "2"
services.nodeports: "0"
used:
persistentvolumeclaims: "0"
services.loadbalancers: "0"
services.nodeports: "0"

测试
创建应用,并用nodeport方式暴露

1
kubectl run test --image nginx

1
kubectl expose deployment test --port=80 --type=NodePort

因为我们设置的namespace的quota services.nodeports:0所以这里创建失败直接抛403错误了。
创建pvc
使用下面文件创建一个pvc

1
2
3
4
5
6
7
8
9
10
11
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-quota-demo
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
1
kubectl apply -f 1.yaml --namespace=quota-object-example

查看资源情况

1
kubectl get resourcequota object-quota-demo --namespace=quota-object-example --output=yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
hard:
persistentvolumeclaims: "1"
services.loadbalancers: "2"
services.nodeports: "0"
status:
hard:
persistentvolumeclaims: "1"
services.loadbalancers: "2"
services.nodeports: "0"
used:
persistentvolumeclaims: "1"
services.loadbalancers: "0"
services.nodeports: "0"

可以看见的是在used这栏persistentvolumeclaims使用已经是1了,我们设置的配额是1如果我们再在这个namespace里面创建个pvc就会抛403了。

LimitRange:
前面已经说过了,LimitRange是用来给namespace内的pod设置一个默认的request和limit值,所以这里我们简单介绍几个场景

先创建namespace

1
kubectl create namespace default-cpu-example

使用以下yaml文件创建limitRange,指定一个默认的cpu request和cpu limit

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-limit-range
spec:
limits:
- default:
cpu: 1
defaultRequest:
cpu: 0.5
type: Container

应用到default-cpu-example这个namespace

1
kubectl apply -f 1.yaml --namespace=default-cpu-example

场景一:在此命名空间创建pod,不设置Resource的limit和request
使用以下yaml文件创建pod

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Pod
metadata:
name: default-cpu-demo
spec:
containers:
- name: default-cpu-demo-ctr
image: nginx

部署pod

1
kubectl apply -f 1.yaml --namespace=default-cpu-example

查看pod yaml配置

1
kubectl get pod default-cpu-demo --output=yaml --namespace=default-cpu-example

可以看见Resource这里自动配置了limit和request,这个就是继承LimitRange

1
2
3
4
5
resources:
limits:
cpu: "1"
requests:
cpu: 500m

场景二:只配置pod Resource的limit不配置request
使用以下yaml文件创建pod

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
name: default-cpu-demo-2
spec:
containers:
- name: default-cpu-demo-2-ctr
image: nginx
resources:
limits:
cpu: "1"

部署pod

1
kubectl apply -f 1.yaml --namespace=default-cpu-example

查看pod yaml配置

1
kubectl get pod default-cpu-demo-2 --output=yaml --namespace=default-cpu-example

需要注意的是这里request值没有继承LimitRange配置的值0.5而是直接根limit相等。

1
2
3
4
5
resources:
limits:
cpu: "1"
requests:
cpu: "1"

场景三:指定容器请求值,不指定容器限额值
使用以下yaml文件创建pod

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
name: default-cpu-demo-3
spec:
containers:
- name: default-cpu-demo-3-ctr
image: nginx
resources:
requests:
cpu: "0.75"

部署pod

1
kubectl apply -f 1.yaml --namespace=default-cpu-example

查看pod yaml配置

1
kubectl get pod default-cpu-demo-2 --output=yaml --namespace=default-cpu-example

需要注意的是这里request值没有继承LimitRange配置的值,而是直接是我们在pod中配置的值,limit继承的是LimitRange的值

1
2
3
4
5
resources:
limits:
cpu: "1"
requests:
cpu: 750m

总结:

  • 如果没有在pod内设置request和limit默认就继承在namespace中配置的LimitRange。
  • 如果在pod只配置了Resource的limit没配置request,这时request值不会继承LimitRange配置的值而是直接根pod中配置limit相等。
  • 如果在pod中配置了request没有配置limit,这时request值以pod中配置的为准,limit值以namespace中的LimitRange为主。

https://kubernetes.io/docs/tasks/administer-cluster/quota-api-object/
https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/