一 实践规划
1.1 实践需求
本实验通过资源配额和资源配置范围的配合来控制一个命名空间的资源使用。
集群管理员根据集群用户的数量来调整集群配置,以达到这个目的:能控制特定命名空间中的资源使用量,最终实现集群的公平使用和成本控制。
需要实现的功能如下:
- 限制运行状态的Pod的计算资源用量。
- 限制持久存储卷的数量以控制对存储的访问。
- 限制负载均衡器的数量以控制成本。
- 防止滥用网络端口这类稀缺资源。
- 提供默认的计算资源Requests以便于系统做出更优化的调度。
二 实验步骤
2.1 创建命名空间
[root@k8smaster01 study]# vi namespace.yaml
1 apiVersion: v1 2 kind: Namespace 3 metadata: 4 name: quota-example 5
[root@k8smaster01 study]# kubectl create -f namespace.yaml
[root@k8smaster01 study]# kubectl get namespaces
NAME STATUS AGE
……
quota-example Active 14s
2.2 设置对象数目的资源配额
通过设置限定对象的数量的资源配额,可以控制以下资源的数量:
- 持久存储卷;
- 负载均衡器;
- NodePort。
[root@k8smaster01 study]# vi object-counts.yaml
1 apiVersion: v1 2 kind: ResourceQuota 3 metadata: 4 name: object-counts 5 spec: 6 hard: 7 persistentvolumeclaims: "2" 8 services.loadbalancers: "2" 9 services.nodeports: "0" 10
[root@k8smaster01 study]# kubectl create -f object-counts.yaml --namespace=quto-example
[root@k8smaster01 study]# kubectl describe quota object-counts --namespace=quota-example
Name: object-counts
Namespace: quota-example
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 2
services.loadbalancers 0 2
services.nodeports 0 0
提示:配额系统会检测到资源项配额的创建,并且会统计和限制该命名空间中的资源消耗,创建完毕后,配额系统会自动阻止那些使资源用量超过资源配额限定值的请求。
2.3 设置计算资源的资源配额
通过设置限定计算资源的资源配额,限制该命名空间中的计算资源的使用总量。
[root@k8smaster01 study]# vi compute-resources.yaml
1 apiVersion: v1 2 kind: ResourceQuota 3 metadata: 4 name: compute-resources 5 spec: 6 hard: 7 pods: "4" 8 requests.cpu: "1" 9 requests.memory: 1Gi 10 limits.cpu: "2" 11 limits.memory: 2Gi 12
[root@k8smaster01 study]# kubectl create -f compute-resources.yaml --namespace=quota-example
[root@k8smaster01 study]# kubectl describe quota compute-resources --namespace=quota-example
Name: compute-resources
Namespace: quota-example
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
pods 0 4
requests.cpu 0 1
requests.memory 0 1Gi
解读:配额系统会自动防止在该命名空间中同时拥有超过4个非“终止态”的Pod。此外,由于该项资源配额限制了CPU和内存的Limits和Requests的总量,因此会强制要求该命名空间下的所有容器都显式定义CPU和内存的Limits和Requests(可使用默认值 Requests默认等于Limits)。
2.4 配置默认Requests和Limits
在命名空间已经配置了限定计算资源的资源配额的情况下,如果尝试在该命名空间下创建一个不指定Requests和Limits的Pod,由于Pod中没有指定CPU和内存的Requests和Limits,那么Pod的创建会失败。为了避免这种失败,可以使用LimitRange来为这个命名空间下的所有Pod都提供一个资源配置的默认值。
[root@k8smaster01 study]# vi limits.yaml
1 apiVersion: v1 2 kind: LimitRange 3 metadata: 4 name: limits 5 spec: 6 limits: 7 - default: 8 cpu: 200m 9 memory: 512Mi 10 defaultRequest: 11 cpu: 100m 12 memory: 256Mi 13 type: Container 14
[root@k8smaster01 study]# kubectl create -f limits.yaml --namespace=quota-example
[root@k8smaster01 study]# kubectl describe limitranges limits --namespace=quota-example
Name: limits
Namespace: quota-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu - - 100m 200m -
Container memory - - 256Mi 512Mi -
解读:在LimitRange创建成功后,用户在该命名空间下创建未指定资源限制的Pod的请求时,系统会自动为该Pod设置默认的资源限制。
2.5 触发limits
[root@k8smaster01 study]# kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
[root@k8smaster01 study]# kubectl run nginx \
--image=nginx \
--replicas=1 \
--requests=cpu=100m,memory=256Mi \
--limits=cpu=200m,memory=512Mi \
--namespace=quota-example
[root@k8smaster01 study]# kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
nginx-78df7bdbcf-mxcql 1/1 Running 0 21s
[root@k8smaster01 study]# kubectl describe quota --namespace=quota-example
解读:每个Pod在创建时都会消耗指定的资源量,而这些使用量都会被Kubernetes准确跟踪、监控和管理。
三 指定作用域
3.1 作用域场景
假设并不想为某个命名空间配置默认的计算资源配额,而是希望限定在命名空间内运行的QoS为BestEffort的Pod总数,例如让集群中的部分资源运行QoS为非BestEffort的服务,而让闲置的资源运行QoS为BestEffort的服务,即可避免集群的所有资源仅被大量的BestEffortPod耗尽。此需求可通过创建两个资源配额来实现。
3.2 创建命名空间
[root@k8smaster01 study]# kubectl create namespace quota-scopes
3.3 创建两个ResourceQuota
[root@k8smaster01 study]# vi best-effort.yaml
1 apiVersion: v1 2 kind: ResourceQuota 3 metadata: 4 name: best-effort 5 spec: 6 hard: 7 pods: "10" 8 scopes: 9 - BestEffort 10
[root@k8smaster01 study]# kubectl create -f best-effort.yaml --namespace=quota-scopes
[root@k8smaster01 study]# vi not-best-effort.yaml
1 apiVersion: v1 2 kind: ResourceQuota 3 metadata: 4 name: not-best-effort 5 spec: 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
[root@k8smaster01 study]# kubectl create -f not-best-effort.yaml --namespace=quota-scopes
[root@k8smaster01 study]# kubectl describe quota --namespace=quota-scopes
Name: best-effort
Namespace: quota-scopes
Scopes: BestEffort
* Matches all pods that do not have resource requirements set. These pods have a best effort quality of service.
Resource Used Hard
-------- ---- ----
pods 0 10
Name: not-best-effort
Namespace: quota-scopes
Scopes: NotBestEffort
* Matches all pods that have at least one resource requirement set. These pods have a burstable or guaranteed quality of service.
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
pods 0 4
requests.cpu 0 1
requests.memory 0 1Gi
提示:创建完成后,对于没有配置Requests的Pod将会被名为best-effort的ResourceQuota限制;而配置了Requests的Pod会被名为not-best-effort的ResourceQuota限制。
3.4 创建Pod
[root@k8smaster01 study]# kubectl run best-effort-nginx --image=nginx --replicas=8 --namespace=quota-scopes
[root@k8smaster01 study]# kubectl run not-best-effort-nginx \
--image=nginx \
--replicas=2 \
--requests=cpu=100m,memory=256Mi \
--limits=cpu=200m,memory=512Mi \
--namespace=quota-scopes
[root@k8smaster01 study]# kubectl get pods --namespace=quota-scopes
解读:名为best-effort-nginx的Deployment因为没有配置Requests和Limits,所以它的QoS级别为BestEffort,因此它的创建过程由best-effort资源配额项来限制,而not-best-effort资源配额项不会对它进行限制。best-effort资源配额项没有限制Requests和Limits,因此best-effort-nginx Deployment可以成功创建8个Pod。
名为not-best-effort-nginx的Deployment因为配置了Requests和Limits,且二者不相等,所以它的QoS级别为Burstable,因此它的创建过程由not-best-effort资源配额项限制,而best-effort资源配额项不会对它进行限制。not-best-effort资源配额项限制了Pod的Requests和Limits的总上限,not-best-effort-nginx Deployment并没有超过这个上限,所以可以成功创建两个Pod。
3.5 触发资源配额
[root@k8smaster01 study]# kubectl describe quota --namespace=quota-scopes
Name: best-effort
Namespace: quota-scopes
Scopes: BestEffort
* Matches all pods that do not have resource requirements set. These pods have a best effort quality of service.
Resource Used Hard
-------- ---- ----
pods 8 10
Name: not-best-effort
Namespace: quota-scopes
Scopes: NotBestEffort
* Matches all pods that have at least one resource requirement set. These pods have a burstable or guaranteed quality of service.
Resource Used Hard
-------- ---- ----
limits.cpu 400m 2
limits.memory 1Gi 2Gi
pods 2 4
requests.cpu 200m 1
requests.memory 512Mi 1Gi
解读:如上所示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可以实现集群资源的超售,可以有效地提高集群资源利用率。