如何做地方网站推广,厦门网站制作系统,制作网页所用的语言是什么,天猫网上购物商城购物一、前言 K8S集群中着这各类资源#xff0c;比如计算资源#xff0c;API资源等#xff0c;其中最重要的是计算资源#xff0c;包括CPU#xff0c;缓存#xff0c;存储等。管理这些资源就是要在资源创建时进行约束和限制#xff0c;在运行时监控这些资源的指标#xff0…一、前言 K8S集群中着这各类资源比如计算资源API资源等其中最重要的是计算资源包括CPU缓存存储等。管理这些资源就是要在资源创建时进行约束和限制在运行时监控这些资源的指标确保资源在高于或低于既定范围内能自动伸缩有序调度使得整个集群健康可控。 本章重点讲述K8S如何进行计算资源的管理。
二、request和limit 我们之前在创建Pod时都没有对容器的使用的CPU和Memory进行约束容器对于这些计算资源的使用可以随心所欲但是K8S集群中每个节点的资源是有限的一旦超额使用有可能导致节点上其他Pod异常乃至节点甚至集群崩溃。 K8S对于Pod中每个容器通过设置Requet和Limit来进行限制。Requests表示容器申请时的最小需求量Limits表示容器运行的最大限制量。其关系如下图所示limit资源限制量要高于request资源限制量。 这里的资源包括 CPU和MemoryCPU的资源单位一般为m(毫核1000毫核1个核)Memory的资源单位为MiGi等(1Mi1024*1024B)。 1、Requests Requests是申请时的最小值限制值节点上的剩余资源需要满足Pod的Requests要求才能被调度上来。如下图所示 节点1的CPU和Memory可以满足Pod的Requests节点2剩余的CPU满足Pod的Requests要求但是Memory却不满足所以该Pod可以被调度到节点1上但无法调度到节点2上。 Requests的资源值是为K8S管理调度而服务的一旦节点的所有Pod的Requests资源和超过节点的总资源量将不再有Pod调度到该节点即使这些Pod在实际运行中消耗的资源比申请时的要少。我们来看下面的实例。 一个节点资源总数CPU为2个核Memory为3Gi其上已调度两个Pod运行此时有个PodC需要调度能否调度到该节点其资源分析:
request资源使用资源CPUMemoryCPUMemoryPod A11.50.51Pod B0.50.50.10.3当前总量1.520.61.3Pod C1111调度后总量2.52331.622.33 答案是否定的虽然从使用资源上Pod C是可以调度到该节点后但是调度时看的是Requests资源量而非实际使用量。接下来我们看下Requests的两个资源值定义.
(1)spec.container[].resources.requests.cpu request的CPU是设置在container上的一方面是服务于K8S的管理调度(如上面所说)另一方面作为参数传给容器用于定义时间比例。 在容器运行中CPU的分配是按照时间分配的而并不是实际的CPU个数。比如某个容器定义了200m而该节点有2个核如果其他的容器不负载那么该容器是可以使用2核CPU的。 在多个容器产生CPU竞争时CPU的时间是如何划分的呢比如某个节点下有两个容器分别申请200m,400m的CPU资源那么就按照1:2的比例将CPU资源分配给这两个容器使用。
(2)spec.container[].resources.requests.memory 这个参数值只提供给Kubernetes调度器作为调度和管理的依据不会作为任何参数传 递给 Docker也不会对运行时内存分配产生影响 。 下面我们就来实践一个案例。首先我们看下node的资源 [rootk8s-master yaml]# kubectl describe node k8s-node1
...
Allocatable:cpu: 2ephemeral-storage: 37986740981hugepages-1Gi: 0hugepages-2Mi: 0memory: 3911712Kipods: 110
....
Resource Requests Limits-------- -------- ------cpu 350m (17%) 0 (0%)memory 90Mi (2%) 0 (0%)ephemeral-storage 0 (0%) 0 (0%)hugepages-1Gi 0 (0%) 0 (0%)hugepages-2Mi 0 (0%) 0 (0%) k8s-node1节点一共2核4Mi(近似),已经用去了350m核90Mi注意这是个Requests额度。所以理论上还能申请的只有1650m核以及3910Mi。 我们创建一个pod使其request资源数超过剩余资源数(cpu为2000Mi)其yaml文件如下 [rootk8s-master yaml]# cat request-nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: request-nginx-podlabels: app: nginx-pod
spec:containers:- name: nginximage: nginx:1.8resources:requests:memory: 500Micpu: 2000m 我们执行下这个文件并创建Pod [rootk8s-master yaml]# kubectl apply -f request-nginx-pod.yaml
pod/request-nginx-pod created
[rootk8s-master yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
request-nginx-pod 0/1 Pending 0 8s
[rootk8s-master yaml]# kubectl describe pod request-nginx-pod
Events:Type Reason Age From Message---- ------ ---- ---- -------Warning FailedScheduling 55s (x2 over 77s) default-scheduler 0/2 nodes are available: 1 Insufficient cpu, 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didnt tolerate. 可以看到两个node都无法满足k8s-node1是因为CPU不满足要求(1 Insufficient cpu)而k8s-master是因为主节点不满足调度容忍度要求。 我们修改下CPU的Requests值为500m核 [rootk8s-master yaml]# cat request-nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: request-nginx-podlabels: app: request-nginx-pod
spec:containers:- name: nginximage: nginx:1.8resources:requests:memory: 500Micpu: 500m 再次执行后正确调度并运行。 [rootk8s-master yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
request-nginx-pod 1/1 Running 0 8m34s 此时我们在看下节点的已使用额度。 [rootk8s-master yaml]# kubectl describe node k8s-node1
...
Allocated resources:(Total limits may be over 100 percent, i.e., overcommitted.)Resource Requests Limits-------- -------- ------cpu 850m (42%) 0 (0%)memory 590Mi (15%) 0 (0%)
... 此时的已用资源已经加上了刚才pod申请的资源。 2、limits Pod要想调度到节点上节点的资源必须满足Requests要求。但是Pod运行起来后其耗用的资源量有可能小于request定义值也有可能大于。如果小于情况下对于节点运行没有影响最坏是引起资源的浪费但是大于的情况下就有可能由于某个Pod的资源过多导致节点崩溃。 为了确保节点运行正常K8S提供了 limits配置limits可以认为是动态量最大值限制。与Requests类似可以设置cpu和memory两个值。
(1)spec.container[].resources.limits.cpu 这里cpu最终会转化为容器的–cpu-period参数(一个周期内能运行的时间)它会与–cpu-period(一个周期时间)一起决定在一个周期内最多分配给该容器的运行时间。
(2)spec.container[].resources.limits.memory 该值会转化为容器的--memory参数为内存的限制值由于内存是不可压缩资源一旦超标就会导致容器kill或者重启但是不一定是当前的超标容器这需要看容器的QoS等级。
3、Qos等级 在一个超卖的系统中QoS等级决定着哪个容器第一个被杀掉这样释放出的资源可以提供给高优先级的Pod使用。那如何判断谁的优先级高呢K8S将容器划分为3个QoS等级从高到低分别为Guaranteed完全可靠的、Burstable弹性波动、较可靠的和BestEffort尽力而为、不太可靠的.
(1)Guaranteed Guaranteed这个等级是指 Pod中所有容器的资源都都定义了Limits和Requests且所有容器的Limits值都和Requests值相等需要注意的是容器中仅定义Limits没有定义Requests那么Requests默认等于Limits。也是属于Guaranteed级别如下面的例子
[rootk8s-master yaml]# cat guaranteed-ngnix-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: guaranteed-nginx-podlabels: app: guaranteed-nginx-pod
spec:containers:- name: nginximage: nginx:1.8resources:requests:memory: 50Micpu: 50mlimits:memory: 50Micpu: 50m
(2)BestEffort
如果Pod中所有容器都未定义配置资源即Request和Limits都未定义那么该Pod就是BestEffort。前面章节中我们定义Pod都属于这类。 [rootk8s-master yaml]# cat bestEffort-ngnix-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: bestEffort-nginx-podlabels: app: bestEffort-nginx-pod
spec:containers:- name: nginximage: nginx:1.8 (3)Burstable 除了以上两种状态其他的都属于Burstable这类的配置情况比较多比如一部分容器都配置了Requests和Limits值其Requests小于Limits值一部分容器仅配置了Request值另一部分容器仅配置了Limits值等等。如下面的例子: [rootk8s-master yaml]# cat burstable-ngnix-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: burstable-nginx-podlabels: app: burstable-nginx-pod
spec:containers:- name: nginximage: nginx:1.8resources:requests:memory: 30Micpu: 30mlimits:memory: 50Micpu: 50m (4)Qos的工作特点 Qos主要是针对不可压缩资源也就是内存当内存资源紧缺的情况下会按照优先级从低到高也就是BestEffort-Burstable-Guaranteed进行Pod的回收。 对于同一级别的Pod计算内存实际使用量与内存申请量比例比例高的会优先kill(与内存实际使用量绝对值没有关系)。如下图所示 三、LimitRange 以上介绍我们了解了Requests和Limits的作用但是需要为每个Pod中的容器配置其工作是相当繁琐的一方面默认的情况下容器是没有配置的对于重要容器的Qos无法得到保证另一方面容器资源配置没有限制理论上可以配置整个节点的资源。为了解决这些问题K8S提供了LimitRange准入控制器以命名空间为维度进行全局的限制。我们来创建一个LimitRange对象。 [rootk8s-master yaml]# cat limitrang-dev.yaml
apiVersion: v1
kind: LimitRange
metadata:name: limitrang-devnamespace: dev
spec:limits:- type: Pod # 对于Pod的资源限制定义min: # Pod中所有容器的Requests值的总和下限cpu: 100mmemory: 50Mimax: # Pod中所有容器的Limits值的总和上限cpu: 4memory: 4GimaxLimitRequestRatio: #Pod中所有容器的Limits值与Requests值比例上限cpu: 10memory: 20 - type: Container # 对于Container的资源限制定义default: # 容器没有指定limits值的默认值cpu: 500mmemory: 500Mi defaultRequest: # 容器没有指定Requests值的默认值cpu: 100mmemory: 50Mi max: # 容器中的Limits的上限值cpu: 1memory: 1Gimin: # 容器中的Requests的下限值cpu: 50mmemory: 30MimaxLimitRequestRatio: #容器的Limits值与Requests值比例上限cpu: 10memory: 20 相关参数的意义参见注释。limitRange可以对Pod和Container进行资源限制Max是对limits值上限的限制Min是对Requests值的下限限制maxLimitRequestRatio是对Limits与Requests比例值的最大值的限制。除此之外对于容器还增加了default和defaultRequest属性如果没有定义则使用默认值。 执行该文件创建 limitRange对象。 [rootk8s-master yaml]#
[rootk8s-master yaml]# kubectl apply -f limitrang-dev.yaml
limitrange/limitrang-dev created
[rootk8s-master yaml]# kubectl get limits --namespacedev
NAME CREATED AT
limitrang-dev 2023-07-02T04:35:15Z 下面我们分别来测试几种场景看下limitRange是否能按照配置的进行准入限制。 1、不配置Requests和Llimits值 此种情况下看下能否按照默认值进行配置创建Pod的yaml文件内容如下 [rootk8s-master yaml]# cat limitrange-default-nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: limitrange-default-nginx-podlabels: app: limitrange-default-nginx-podnamespace: dev
spec:containers:- name: nginximage: nginx:1.8 创建完成后看下Pod的详情 [rootk8s-master yaml]# kubectl describe pod limitrange-default-nginx-pod --namespacedev
...
Containers:nginx:Container ID: docker://5a6e415f45125b8d824f73f081dc3ead845b21487537552b2b0cc23e015ffdcaImage: nginx:1.8Image ID: docker-pullable://nginxsha256:c97ee70c4048fe79765f7c2ec0931957c2898f47400128f4f3640d0ae5d60d10Port: noneHost Port: noneState: RunningStarted: Sun, 02 Jul 2023 12:59:17 0800Ready: TrueRestart Count: 0Limits:cpu: 500mmemory: 500MiRequests:cpu: 100mmemory: 50MiEnvironment: noneMounts:/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-5ckfr (ro)
.... 可以看到正确的写入了limitRange的默认值。 2、创建超过限制资源配置的Pod 创建Pod其yaml文件内容如下 [rootk8s-master yaml]# cat limitrange-nok-nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: limitrange-nok-nginx-podlabels: app: limitrange-nok-nginx-podnamespace: dev
spec:containers:- name: nginximage: nginx:1.8resources:requests:memory: 30Micpu: 30mlimits:memory: 50Micpu: 50m 执行该文件创建Pod [rootk8s-master yaml]# kubectl apply -f limitrange-nok-nginx-pod.yaml
Error from server (Forbidden): error when creating limitrange-nok-nginx-pod.yaml: pods limitrange-nok-nginx-pod is forbidden: [minimum cpu usage per Pod is 100m, but request is 30m, minimum memory usage per Pod is 50Mi, but request is 31457280, minimum cpu usage per Container is 50m, but request is 30m] 可以看到该Pod中只有一个容器所以即违反了Pod总量最小值要求又违反了容器对于cpu的最低要求创建失败。 3、创建一个正常的Pod 创建Pod其yaml内容如下 [rootk8s-master yaml]# cat limitrange-ok-nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: limitrange-ok-nginx-podlabels: app: limitrange-ok-nginx-podnamespace: dev
spec:containers:- name: nginximage: nginx:1.8resources:requests:memory: 50Micpu: 100mlimits:memory: 500Micpu: 500m 执行该文件创建Pod [rootk8s-master yaml]# kubectl apply -f limitrange-ok-nginx-pod.yaml
pod/limitrange-ok-nginx-pod created
[rootk8s-master yaml]# kubectl describe pod limitrange-ok-nginx-pod --namespacedev
...Restart Count: 0Limits:cpu: 500mmemory: 500MiRequests:cpu: 100mmemory: 50Mi
... 可以看到Pod创建成功。 四、ResourceQuota 通过limitRange可以实现在命名空间下对于每个Pod和以及Pod下每个容器的资源限制但是无法限制所有Pod的资源总额在实际工程中在同一集群中给予不同命名空间(不同业务)的总资源是需要约束的否则容器出现资源被某类业务独占其他业务无法申请的情况。limitRange与ResourceQuota的关系如下图所示 创建ResourceQuota对象其yaml如下 [rootk8s-master yaml]# cat resourcequota-dev.yaml
apiVersion: v1
kind: ResourceQuota
metadata:name: resourcequota-resource-devnamespace: dev
spec: hard: requests.cpu: 200m requests.memory: 200Mi limits.cpu: 400m limits.memory: 400Mi 这里定义了在namespace:dev下Requests以及Limits的cpu和memory总和。 我们先删除dev命名空间下所有的pod再执行该文件。 [rootk8s-master yaml]# kubectl apply -f resourcequota-dev.yaml
resourcequota/resourcequota-resource-dev created
[rootk8s-master yaml]# kubectl get resourcequota --namespacedev
NAME AGE REQUEST LIMIT
resourcequota-resource-dev 41s requests.cpu: 0/200m, requests.memory: 0/200Mi limits.cpu: 0/400m, limits.memory: 0/400Mi 我们再来创建 前一章节的limitrange-ok-nginx-pod看下能否创建成功
[rootk8s-master yaml]# kubectl apply -f limitrange-ok-nginx-pod.yaml
Error from server (Forbidden): error when creating limitrange-ok-nginx-pod.yaml: pods limitrange-ok-nginx-pod is forbidden: exceeded quota: resourcequota-resource-dev, requested: limits.cpu500m,limits.memory500Mi, used: limits.cpu0,limits.memory0, limited: limits.cpu400m,limits.memory400Mi 因为在resourcequota中定义了limits的cpu和memory总和分别为400m和400Mi但是在limitrange-ok-nginx-pod中配置limit资源分别为500m和500Mi这样就超过了总和的限制导致创建失败。
ResourceQuota除了限制计算资源总和还可以限制对象资源的个数主要包括
PodReplicationControllerSecretConfigMapPersistent Volumn ClainService
接下来我们在创建一个限制对象资源总和的ResourceQuota的例子其yaml内容如下:
[rootk8s-master yaml]# cat resourcequota-object-dev.yaml
apiVersion: v1
kind: ResourceQuota
metadata:name: resourcequota-object-devnamespace: dev
spec: hard:pods: 2services: 5
大家感兴趣可以自行完成对象资源的验证。
五、总结 本篇主要介绍了K8S对于计算资源的管理主要是针对CPU和Memory资源。 Requests和Limits作为资源管理最基本两个设置Requests是容器申请时最小限制主要用于K8S在Pod调度时节点的剩余资源能否满足Pod的要求。Limits是容器运行时的最大限制主要控制Pod运行时对于资源超额使用的限制一旦超过Limits定义的量就有可能引起Pod的kill或者重启。 K8S将Pod划分为三个QoS等级优先级从高到低分别为Guaranteed、Burstable和BestEffort。一旦资源超卖就会从低到高选择Pod进行kill将资源保障给高优先级的Pod。 LimitRange是以命名空间的维度对Pod进行统一配置限制值和默认值从而避免逐个配置Pod的繁琐。 ResourceQuota是以命名空间的维度对于资源总额进行限制。 附:
K8S初级入门系列之一-概述
K8S初级入门系列之二-集群搭建
K8S初级入门系列之三-Pod的基本概念和操作
K8S初级入门系列之四-Namespace/ConfigMap/Secret
K8S初级入门系列之五-Pod的高级特性
K8S初级入门系列之六-控制器(RC/RS/Deployment)
K8S初级入门系列之七-控制器(Job/CronJob/Daemonset)
K8S初级入门系列之八-网络
K8S初级入门系列之九-共享存储
K8S初级入门系列之十-控制器(StatefulSet)
K8S初级入门系列之十一-安全
K8S初级入门系列之十二-计算资源管理