ResourceQuota和LimitRange实践
根据前面对资源管理的介绍,这里将通过一个完整的例子来说明如何通过资源配额和资源配置范围的配合来控制一个命名空间的资源使用。
集群管理员根据集群用户的数量来调整集群配置,以达到这个目的:能控制特定命名空间中的资源使用量,最终实现集群的公平使用和成本控制。
需要实现的功能如下:
◎ 限制运行状态的Pod的计算资源用量。
◎ 限制持久存储卷的数量以控制对存储的访问。
◎ 限制负载均衡器的数量以控制成本。
◎ 防止滥用网络端口这类稀缺资源。
◎ 提供默认的计算资源Requests以便于系统做出更优化的调度。
1.创建命名空间
创建名为quota-example的命名空间,namespace.yaml文件
1
2
3
4
5
6
7 1apiVersion: v1
2kind: Namespace
3metadata:
4 name: quota-example
5
6kubectl create -f namespace.yaml
7
2.设置限定对象数目的资源配额
通过设置限定对象的数量的资源配额,可以控制以下资源的数量:
◎ 持久存储卷;
◎ 负载均衡器;
◎ NodePort。
创建名为object-counts的ResourceQuota:
1
2
3
4
5
6
7
8
9
10
11
12 1apiVersion: v1
2kind: ResourceQuta
3metadata:
4 name: object-counts
5spec:
6 hard:
7 persistentvolumeclaim: "2"
8 services.loadbalancers: "2"
9 services.nodeports: "0"
10
11# kubectl create -f object-counts.yaml --namespace=quto-example
12
配额系统会检测到资源项配额的创建,并且会统计和限制该命名空间中的资源消耗。
查看该配额是否生效:
1
2 1kubectl describe quota object-counts --ns=quota-example
2
至此,配额系统会自动阻止那些使资源用量超过资源配额限定值的请求。
3. 设置限定计算资源的资源配额
下面再创建一项限定计算资源的资源配额,以限制该命名空间中的计算资源的使用总量。
创建名为compute-resources的ResourceQuota:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 1apiVersion: v1
2kind: ResourceQuota
3metadata:
4 name: compute-resources
5spec:
6 hard:
7 pods: "4"
8 requests.cpu "1"
9 requests.memory: 1Gi
10 limits.cpu: "2"
11 limits.memory: 2Gi
12
13
14# kubectl create -f compute-resources.yaml --ns=quota-example
15
查看该配额是否生效:
1
2 1kubectl describe quota compute-resources --ns=quota-example
2
配额系统会自动防止在该命名空间中同时拥有超过4个非“终止态”的Pod。此外,由于该项资源配额限制了CPU和内存的Limits和Requests的总量,因此会强制要求该命名空间下的所有容器都显式定义CPU和内存的Limits和Requests(可使用默认值,Requests默认等于Limits)。
创建一个Nginx的Deployment
1
2 1kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
2
查看创建的Pod,会发现Pod没有创建成功:
1
2 1kubectl get pod --ns=quota-example
2
再查看一下Deployment的详细信息
1
2 1kubectl describe deployment nginx --ns=quota-example
2
该Deployment尝试创建一个Pod,但是失败了,查看其中ReplicaSet的详细信息:
1
2 1kubectl describe rs <nginx-name> --ns=quota-example
2
可以看到Pod创建失败的原因:Master拒绝这个ReplicaSet创建Pod,因为在这个Pod中没有指定CPU和内存的Requests和Limits。
为了避免这种失败,我们可以使用LimitRange来为这个命名空间下的所有Pod都提供一个资源配置的默认值。下面的例子展示了如何为这个命名空间添加一个指定默认资源配置的LimitRange。
创建一个名为limits的LimitRange:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1apiVersion: v1
2kind: LimitRange
3metadata:
4 name: limits
5spec:
6 limits:
7 - default:
8 cpu: 200m
9 memory: 512Mi
10 defaultRequest:
11 cpu: 100m
12 memory: 256Mi
13 type: Container
14
15# kubectl create -f limits.yaml --ns=quota-example
16
在LimitRange创建成功后,用户在该命名空间下创建未指定资源限制的Pod的请求时,系统会自动为该Pod设置默认的资源限制。
例如,每个新建的未指定资源限制的Pod都等价于使用下面的资源限制:
1
2
3
4
5
6
7 1kubectl run nginx \
2--image=nginx \
3--replicas=1 \
4--requests=cpu=100m,memory=256Mi \
5--limits=cpu=200m,memory=512Mi \
6--namespace=quota-example
7
至此,我们已经为该命名空间配置好默认的计算资源了,我们的ReplicaSet应该能够创建Pod了。查看一下,创建Pod成功:
1
2 1kubectl get pods -ns=quota-example
2
接下来可以随时查看资源配额的使用情况:
1
2 1kubectl describe quota --namespace=quota-example
2
可以看到每个Pod在创建时都会消耗指定的资源量,而这些使用量都会被Kubernetes准确跟踪、监控和管理。
5.指定资源配额的作用域
假设我们并不想为某个命名空间配置默认的计算资源配额,而是希望限定在命名空间内运行的QoS为BestEffort的Pod总数,例如让集群中的部分资源运行QoS为非BestEffort的服务,而让闲置的资源运行QoS为BestEffort的服务,即可避免集群的所有资源仅被大量的BestEffort Pod耗尽。这可以通过创建两个资源配额来实现,如下所述。
创建一个名为quota-scopes的命名空间:
1
2 1kubectl create ns quota-scopes
2
创建一名为best-effort的ResourceQuota,指定Scope为BestEffort:
1
2
3
4
5
6
7
8
9
10 1apiVersion: v1
2kind: ResourceQuota
3metadata:
4 name: best-effort
5spec:
6 hard:
7 pods: "10"
8 scopes:
9 - BestEffort
10
再创建一个名为not-best-effort的ResourceQuota,指定Scope为NotBestEffort:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1apiVersion: v1
2kind: ResourceQuota
3metadata:
4 name: not-best-effort
5spec:
6 hard:
7 pods: "4"
8 requests.cpu: "1"
9 requests.memory: 1Gi
10 limits.cpu: "2"
11 limits.memory: 2Gi
12 scopes:
13 - NotBestEffort
14
15
16kubectl create -f not-best-effort.yaml --namespace=quota-scopes
17
18
查看创建成功的ResourceQuota:
1
2 1kubectl describe quota --ns=quota-scopes
2
可以看到best-effort资源配额项已经统计了在best-effort-nginx Deployment中创建的8个Pod的资源使用信息,not-best-effort资源配额项也已经统计了在not-best-effort-nginx Deployment中创建的两个Pod的资源使用信息。
通过这个例子我们可以看到:资源配额的作用域(Scopes)提供了一种将资源集合分割的机制,可以使集群管理员更加方便地监控和限制不同类型的对象对各类资源的使用情况,同时为资源分配和限制提供更大的灵活度和便利性。
资源管理总结
Kubernetes中资源管理的基础是容器和Pod的资源配置(Requests和Limits)。容器的资源配置指定了容器请求的资源和容器能使用的资源上限,Pod的资源配置则是Pod中所有容器的资源配置总和上限。
通过资源配额机制,我们可以对命名空间中所有Pod使用资源的总量进行限制,也可以对这个命名空间中指定类型的对象的数量进行限制。使用作用域可以让资源配额只对符合特定范围的对象加以限制,因此作用域机制可以使资源配额的策略更加丰富、灵活。
如果需要对用户的Pod或容器的资源配置做更多的限制,则可以使用资源配置范围(LimitRange)来达到这个目的。LimitRange可以有效地限制Pod和容器的资源配置的最大、最小范围,也可以限制Pod和容器的Limits与Requests的最大比例上限,此外LimitRange还可以为Pod中的容器提供默认的资源配置。
Kubernetes基于Pod的资源配置实现了资源服务质量(QoS)。不同QoS级别的Pod在系统中拥有不同的优先级:高优先级的Pod有更高的可靠性,可以用于运行可靠性要求较高的服务;低优先级的Pod可以实现集群资源的超售,可以有效地提高集群资源利用率。
上面的多种机制共同组成了当前版本Kubernetes的资源管理体系。这个资源管理体系可以满足大部分的资源管理需求。同时,Kubernetes的资源管理体系仍然在不停地发展和进化,对于目前无法满足的更复杂、更个性化的需求,我们可以继续关注Kubernetes未来的发展和变化。
小结:
资源管理的内容到此结束,谢谢大家的浏览~