ToB企服应用市场:ToB评测及商务社交产业平台

标题: kubernetes之资源限制及QOS服务质量 [打印本页]

作者: 宁睿    时间: 2022-9-16 17:13
标题: kubernetes之资源限制及QOS服务质量
1.什么是资源限制?

1.1在kubernetes集群中,为了使得系统能够稳定的运行,通常会对Pod的资源使用量进行限制。在kubernetes集群中,如果有一个程序出现异常,并且占用大量的系统资源,如果没有对该Pod进行资源限制的话,可能会影响其他的Pod正常运行,从而造成业务的不稳定性。
1.2正常情况下我们在一个宿主机的内核之上,这个宿主机可能管理了一组硬件包括CPU、内存。而后在这个宿主机的内核之上,我们可以运行多个容器,这些容器将共享底层的同一个内核,很显然,硬件是属于内核的,因此任何容器中的每一个进程默认可以请求占有这个内核管理的所有的可用硬件资源。
1.3尤其是多租户的环境当中,有人恶意的运行了一个容器,这个容器可能会大量的占用CPU和内存,进而会导致其他容器无法运行,Docker容器启动的时候默认是在内核的名称空间级别进行了隔离,在进程所运行的资源范围上并没有做太多的隔离操作。我们应该为每个应用设定内部进程运行最为合理的资源的最小保证量和最大保证量。
1.4官方文档:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-cpu-resource/
2.如何实现资源限制?

  1. spec.containers[].resources.request.cpu     # Pod申请时的CPU,如果节点没有足够大,则Pod调度失败
  2. spec.containers[].resources.request.memory  # Pod申请时的内存
  3. spec.containers[].resource.limits.cpu       # Pod最大可使用的CPU
  4. spec.containers[].resource.limits.memory    # Pod最大可使用的内存
复制代码
3.资源限制的目的

3.1我们为什么要进行资源限制?
4.资源限制单位

4.1CPU限制单位
1核CPU=1000毫核,当定义容器为0.5时,所需要的CPU资源是1核心CPU的一般,对于CPU单位,表达式0.1等价于表达式100m,可以看作是100millicpu;
  1. 1核=1000millicpu (1 Core=1000m)
  2. 0.5核=500millicpu  (0.5 Core=500m)
复制代码
4.2内存限制单位
内存的基本单位是字节数(Bytes),也可以使用E、P、T、G、M、K作为单位后缀,或Ei、Pi、Ti、Gi、Mi和Ki形式单位后缀;
  1. 1MB=1000KB=1000000Bytes
  2. 1Mi=1024KB=1048576Bytes
复制代码
5.资源限制配置案例

5.1CPU配置;

5.1.1设置容器的CPU请求与限制;
  1. 需安装Metrics-Server才能用top命令否则无法使用;
  2. 没有metrics-server会报错error: Metrics API not available
  3. # 创建一个具有一个容器的Pod,容器将请求0.5个CPU,最多限制1个CPU;
  4. root@kubernetes-master01:~# cat cpu-requests-limits.yaml
  5. apiVersion: v1
  6. kind: Pod
  7. metadata:
  8.   name: cpu-test-cpu-limits
  9. spec:
  10.   containers:
  11.   - name: cpu-test-stress
  12.     image: registry.cn-hangzhou.aliyuncs.com/lengyuye/stress:latest
  13.     args:
  14.     - -cpus         # 容器尝试使用2核CPU
  15.     - "2"
  16.     resources:
  17.        requests:  #  限制Pod最多可申请0.5核CPU
  18.          cpu: "500m"  
  19.        limits:     # 限制Pod最大可使用1核CPU
  20.          cpu: "1000m"
  21. root@kubernetes-master01:~# kubectl apply -f cpu-requests-limits.yaml
  22. pod/cpu-test-cpu-limits created
  23. # 查看资源限制情况,容器配置去尝试使用2个CPU,但是容器只能被允许使用1个CPU;
  24. root@kubernetes-master01:~# kubectl top pods cpu-test-cpu-limits
  25. NAME                  CPU(cores)   MEMORY(bytes)   
  26. cpu-test-cpu-limits   999m        1Mi   
复制代码
5.1.2创建一个Pod,设置该Pod中容器请求为100核,这个值会大于集群中所有内存的总和;
  1. root@kubernetes-master01:~# cat cpu-requests-limits.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: cpu-test-cpu-limits
  6. spec:
  7.   containers:
  8.   - name: cpu-demo-ctr
  9.     image: registry.cn-hangzhou.aliyuncs.com/lengyuye/stress:latest
  10.     args:
  11.     - -cpus
  12.     - "2"
  13.     resources:
  14.        requests:
  15.          cpu: "100"   # 设置Pod申请100GB,我们集群上没有100GB的资源
  16.        limits:
  17.          cpu: "100"   # 最大使用100GB,集群资源不足,无法创建;
  18. root@kubernetes-master01:~# kubectl apply -f cpu-requests-limits.yaml
  19. pod/cpu-test-cpu-limits created
  20. # 查看Pod的状态,为Pending,Pod未被调度到任何节点上;
  21. root@kubernetes-master01:~# kubectl get pods
  22. cpu-test-cpu-limits                          0/1     Pending   0          4s
  23. # 查看Events,输出显示由于3节点的CPU资源不足,无法进行调度;
  24. root@kubernetes-master01:~# kubectl describe pods cpu-test-cpu-limits
  25.   Type     Reason            Age   From               Message
  26.   ----     ------            ----  ----               -------
  27.   Warning  FailedScheduling  113s  default-scheduler  0/3 nodes are available: 3 Insufficient cpu.
  28.   Warning  FailedScheduling  113s  default-scheduler  0/3 nodes are available: 3 Insufficient cpu.
复制代码
5.1.3如果不指定CPU的Limits?
如果没有为容器配置CPU限制,那么容器在可以使用的CPU资源是没有上限的,因而可以使用所在节点上的所有可用CPU资源,这样会造成某一个Pod占用了大量的CPU,可能会影响其他Pod的正常允许,从而造成业务的不稳定性。
5.2内存配置;

5.2.1设置容器的内存请求与限制;
创建一个1个容器Pod,容器会将请求100MB内存,并且最大可用内存为200MB以内;
  1. root@kubernetes-master01:~# cat memory-requests-limits.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: pod-memory-resource
  6. spec:
  7.   containers:
  8.   - name: momory-demo-stress
  9.     image: registry.cn-hangzhou.aliyuncs.com/lengyuye/stress:latest
  10.     command: ["stress"]
  11.     args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1" ]
  12.     resources:
  13.       requests:
  14.         memory: "100Mi"   # 设置最小请求为100Mi
  15.       limits:
  16.         memory: "200Mi"   # 最大可使用200Mi
  17. root@kubernetes-master01:~# kubectl apply -f memory-requests-limits.yaml
  18. pod/pod-memory-resource created
  19. # 获取Pod的内存使用信息,输出结果显示Pod正在使用的内存约为150Mi,大于Pod请求的100Mi,但是在Pod限制的200Mi之内。
  20. root@kubernetes-master01:~# kubectl top po pod-memory-resource
  21. NAME                  CPU(cores)   MEMORY(bytes)   
  22. pod-memory-resource   43m          151Mi
  23. # 也可用通过Yaml文件的方式来看limits最大可使用为200Mi
  24.     resources:
  25.       limits:
  26.         memory: 200Mi
  27.       requests:
  28.         memory: 100Mi
复制代码
5.2.2运行超过容器内存限制的应用
当节点拥有足够的可用内存时,容器可用使用其请求的内存,但是,容器不允许使用超过其限制的内存。如果容器分配的内存超过其限制,该容器会成为被终止的候选容器。如果容器继续消耗超过其限制的内存,则终止容器。如果终止的容器可以被重启,则kubelet会重新启动它。
5.2.2.1创建一个Pod,拥有一个Containers,该容器的内存请求为100Mi,内存限制为200Mi,尝试分配超出其限制的内存;
  1. root@kubernetes-master01:~# cat memory-requests-limits.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: pod-memory-resource
  6. spec:
  7.   containers:
  8.   - name: momory-demo-ctr
  9.     image: registry.cn-hangzhou.aliyuncs.com/lengyuye/stress:latest
  10.     command: ["stress"]
  11.     args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1" ]  # 强行分配250M
  12.     resources:
  13.       requests:
  14.         memory: "100Mi"
  15.       limits:
  16.         memory: "200Mi"  # 我们上限不能超过200,超过200Mi会发生OOM Kill
  17. root@kubernetes-master01:~# kubectl apply -f memory-requests-limits.yaml
  18. # 查看Pod,此时容器被杀死;
  19. root@kubernetes-master01:~# kubectl get pods -w
  20. pod-memory-resource                          0/1     OOMKilled           0          9s
  21. pod-memory-resource                          0/1     OOMKilled           1          11s
  22. pod-memory-resource                          0/1     CrashLoopBackOff    1          12s
  23. # 查看更详细的信息,显示为OOMKilled;
  24. root@kubernetes-master01:~#kubectl get  pod pod-memory-resource -o yaml
  25. lastState:
  26.       terminated:
  27.         containerID: docker://3d6e53a12a101f474d24c00b8e9c5b1e6da2ef26735b6e2cb6790184c6d69cfa
  28.         exitCode: 1
  29.         finishedAt: "2022-07-27T06:40:07Z"
  30.         reason: OOMKilled
复制代码
5.2.3超过节点的内存分配
Pod的调度基于请求,只有当前节点拥有足够满足Pod内存请求的内存时,才会将Pod调度至该节点运行;
5.2.3.1创建一个Pod,其拥有一个请求1000GB内存的容器,超出了集群任何一个节点所拥有的内存;
  1. root@kubernetes-master01:~/cloud-Native/resource# cat memory-requests-limits.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: pod-memory-resource
  6. spec:
  7.   containers:
  8.   - name: momory-demo-ctr
  9.     image: registry.cn-hangzhou.aliyuncs.com/lengyuye/stress:latest
  10.     command: ["stress"]
  11.     args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1" ]
  12.     resources:
  13.       requests:
  14.         memory: "100Gi"
  15.       limits:
  16.         memory: "200Gi"
  17. root@kubernetes-master01:~# kubectl apply -f memory-requests-limits.yaml
  18. # 查看Pod状态,发现处于pending,这意味着该Pod未被调度至任何节点;
  19. root@kubernetes-master01:~# kubectl get pods -w
  20. pod-memory-resource                          0/1     Pending   0          6s
  21. # 通过describe查看更详细信息;显示为由于节点内存不足,该容器无法被调度;
  22. root@kubernetes-master01:~# kubectl describe pods pod-memory-resource
  23. Events:
  24.   Type     Reason            Age    From               Message
  25.   ----     ------            ----   ----               -------
  26.   Warning  FailedScheduling  2m21s  default-scheduler  0/3 nodes are available: 3 Insufficient memory.
  27.   Warning  FailedScheduling  2m20s  default-scheduler  0/3 nodes are available: 3 Insufficient memory.
复制代码
5.2.4如果没有指定内存限制;
如果为容器指定内存限制,容器可以无限的使用其所在节点的所有可用内存,进而可能导致该节点调用OOM Killer。此外如果发生OOM Kill,没有配置资源限制的容器将被杀死的可能性会更大。
6.QOS服务质量

6.1什么是QOS?

kubernetes允许节点资源对limits的过载使用,这意味着节点无法同时满足其上的所有Pod对象以资源满载的方式运行,于是在内存资源紧缺时,应该以何种次序先后终止哪些Pod对象?
kubernetes无法自行对此做出决策,它需要借助于Pod对象的优先级判定,根据Pod对象的Requests和Limits属性,kubernetes将Pod对象归类到BestEffort、Burstable和Guaranteed三个服务质量(Quality of Service,QOS);
6.1.1Guaranteed: Pod对象为每个容器都设置了CPU资源需求和资源限制,且两者的值相同,还同时为每个容器设置了内存需求与内存限制,并且两者的值相同,这类Pod对象具有最高级别服务质量。
6.1.2Burstable: 至少有一个容器设置了CPU或内存资源Requests属性,但不满足Guaranteed,这类Pod具有中级服务质量;
6.1.3BestEffort: 没有为任何容器设置Requests和Limits属性,这类Pod对象服务质量是最低级别。
1.当kubernetes集群内存资源紧缺,优先杀死BestEffort类别的容器,因为系统不为该类资源提供任何服务保证,但是此类资源最大的好处就是能够尽可能的使用资源。
2.如果系统中没有BestEffort类别的容器,接下来就轮到Burstable类别的容器,如果有多个Burstable类别的容器,就看谁的资源占用多就优先杀死谁。对于Guaranteed类别的容器拥有最高优先级,他们不会被杀死,除非其内存需求超限,或OMM时没有其他更低优先级的Pod对象存在,才干掉Guaranteed类容器;

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4