kubernetes 了解容器资源需求与限制(43)

2023年 7月 16日 122.4k 0

之前介绍的pod资源调度,此篇主要记录的是kubernetes上运行pod的对象的时,如何去监控系统级的一些资源指标,业务指标的获取,以及监控。

容器在启动的时候,可以根据资源需求,配置资源限额的,如CPU,内存。而CPU资源属于可压缩资源,一个容器在本应该获取指定的资源获取不到的时候,进行等待即可,而内存则不一样。内存属于非可压缩资源,如果内存资源因为指定的大小而不够的时候会因为内存资源耗尽而被Kill。此前我们知道,在kubernetes中资源可定义为起始和终结值。

  • requests

定义cpu和内存的使用率。至少需要用的资源需求。

  • limits

限制,最高消耗区间。并且是硬限制一般来讲limis应该大于等于requests,尽管这些限制是应用在容器之上的,但是我们称之pod资源需求,也是应用到pod上的。

CPU

在kubernetes上一个单位的CPU相当于一颗虚拟CPU(虚拟CPU指一个核心或者一个超线程。一个两核双线程的CPU可以虚拟4颗逻辑CPU)。而且一个CPU并且能够被划分子单位,一核,相当于1000 millcores(微核),那么500m就相当于0.5个CPU

内存

内存的计量单位是E,P,T,G,M,K Ei,Pi,Ti,Gi,Mi,Ki

假设,我们限制每个pod的cpu只能使用0.5个核心,设置成cpu.limits=500m,这个cpu.limits=500m指的是硬上限,也就是说最多使用500m,不用就不用。如下图:

资源限制.png

除此之外还有requests,requests是说,如果想要确保正常运行容器,至少要给0.2个核心。但是这个0.2个核心并不是说直接就是用到0.2个,而是说至s少要保证有0.2个能够被使用,并且调度的目标节点至少有0.2个空闲的cpu资源可用。

每一个节点已经有多少CPU资源被分配出去,就是计算这个节点上所运行的所有容器的CPU requests加起来的,这个加起来的值被总核心减掉,剩下的就是未被分配的。如:调度4个容器,每个容器至少需要0.5核心,那就意味着还剩下2核心空闲。如果此刻pod中至少有一个容器要使用三个CPU,那么这个节点就不被预选,无法满足Pod。

  • 定义的资源需求,只是定义了资源的请求下限。如果我们明确说只要200m(requests)资源来运行,系统有4核心,而运行的pod因为bug的原因,是有可能将4核心全部占用的。因为只是定义了200m的资源需求。一般情况下,需求和上限都需要同时定义,否则就有可能推掉节点的所有资源

requests需求确保在调度时候,对应节点上需已经拥有这么多的资源以便于满足这个pod运行的基本需求。而limits用于限制这个容器无论怎么运行绝对不能超过的资源阈值。

定义测试

资源需求是定义在容器级别的,在pods.spec.containers.resources:

  • pec.containers[].resources.limits.cpu
  • spec.containers[].resources.limits.memory
  • spec.containers[].resources.requests.cpu
  • spec.containers[].resources.requests.memory

参考Pod和Container的资源请求和限制,

定义资源限制需要在容器级别加resources,而后requests下定义两个维度的需求,分别是cpu和memory(可以同时定义也可以定义一个)。再者,为了屏蔽,定义limits限制上限多少,达到这个上限就不再分配资源。

  • 并且也可只定义需求,而不定义限制。也可以只定义限制而不定义需求。需求和限制都可以只定义一个 ,一般来讲,都会定义完整。

很多情况下,requests和limits分别对应的是需求级别和上限级别,一般的话requests和limits定义相同是合适的

如下:

定义requests的CPU为300m,也就是0.3核心的CPU,内存为256M,而限制定义为最多用1核心的CPU,最多使用512的内存。

延续内容:如果这个pod一直使用300m。那么定义的限制上限资源就不起作用,剩下的200M只是存在于定义的列表中,并不是说还有200M在等待,200M仍然可别其他所使用。仅仅作为上限限制。

spec:
  containers:
  - name: linuxea-pod1-com
    image: "marksugar/nginx:1.14.a"   
   resources:
      requests:
        cpu: "300m"
        memory: "256Mi"
      limits:
        cpu: "1"
        memory: "512Mi"

我们借用别人的pod进行压测一下,yml如下

apiVersion: v1
kind: Pod
metadata: 
  name: pod-demo-linuxea
  namespace: default
  labels:
    www: linuxea-com
    tier: backend
spec:
  containers:
  - name: linuxea-pod1-com
    image: "ikubernetes/stress-ng"
    command: ["/usr/bin/stress-ng","-c 1","--metrics-brief"]
    ports:
      - containerPort: 88
    resources:
      requests:
        cpu: "300m"
        memory: "256Mi"
      limits:
        cpu: "1"
        memory: "512Mi"
[root@linuxea metrics]# kubectl apply -f pod-demo.yaml 
pod/pod-demo-linuxea created
[root@linuxea metrics]# kubectl get pods
NAME                              READY     STATUS    RESTARTS   AGE
dpment-linuxea-7748786749-4s2qv   1/1       Running   0          5d
dpment-linuxea-7748786749-6llcz   1/1       Running   0          5d
dpment-linuxea-7748786749-dv4nf   1/1       Running   0          5d
pod-demo-linuxea                  1/1       Running   0          38s

而后使用top命令查看压测结果

  • 此刻CPU的占用率是%25 。我机器上4核CPU,在yaml的limits中最大用1核心,100的4分之一是25%
[root@linuxea metrics]# kubectl exec pod-demo-linuxea top
Mem: 3191756K used, 4982256K free, 405912K shrd, 944K buff, 2204020K cached
CPU:  25% usr   0% sys   0% nic  75% idle   0% io   0% irq   0% sirq
Load average: 1.00 0.71 0.33 3/533 31
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
    7     1 root     R     6896   0%   2  25% {stress-ng-cpu} /usr/bin/stress-ng
    1     0 root     S     6256   0%   3   0% /usr/bin/stress-ng -c 1 --metrics-
    8     0 root     S     1516   0%   2   0% top
   14     0 root     S     1516   0%   2   0% top
   20     0 root     S     1516   0%   1   0% top
   26     0 root     R     1512   0%   0   0% top

resources定义能够被调度器作为基础衡量条件的调度指数使用的。对于每个节点来讲,会将所有容器的资源需求量加起来作为已分配出去的配额,limits上限是非常有效的

容器可见资源和可用资源

当使用resources限制了资源需求和限额后,使用free命令查看,显示的是节点上的所有内存,并不是容器的配额内存。这样是有问题的。

如:jvm在跑起来的时候,虚拟机启动时候就会创建堆,而后类,数组等都由此分配。堆的分配当然使用的是物理机的内存,或者多少。如果jvm跑在容器内,jvm拿到的内存是节点物理内存量,而不是容器limits的配额内存,那么计算的结果肯定是有问题的,吞掉容器所有内存都不够,甚至出现其他问题。

Qos

qos是作为服务质量的一个简称当限制了一些资源后,默认会自动属于某个Qos的类。默认情况下,类别有三个:

  • Guranteed:每个容器

每个相同资源,同时设置了相同的resources,limits,必须满足相同的条件:

   cpu.limits=cpu.requests
   memory.limits=memory.requests

大致如此:

    resources:
      requests:
        cpu: "1"
        memory: "512Mi"
      limits:
        cpu: "1"
        memory: "512Mi"

这样相同的配置就会自动归类的Guranteed,这类pod拥有最高优先级。如: 资源不够的时候,优先运行这类资源

  • Burstable:至少有一个容器

至少有一个容器设置了cpu或者内存的limits属性,或者至少有一个容器设置了cpu或者内存的requests属性,这类的具有中等优先级。

此前,我们创建的pod,cpu内存的requests和limits不相同,便是Burstable类型

[root@linuxea metrics]# kubectl describe pods pod-demo-linuxea |grep QoS
QoS Class:       Burstable
  • BestEffort: 没有任何一个容器

没有任何一个容器设置了requests或者limits;最低优先级别。

当资源不够用的时候,属于BestEffort的容器将会被优先关闭。优先让属于其他两种pod类型的资源运行。

如果资源仍然不够,就会关闭Burstable类的pod容器。

如果此时Burstable的容器已经全部关闭,或者说只有Guranteed,但是在资源还是不够用。就会依据已占用量和需求量的比例大的优先被关闭。如下:

limits.png

上面pod limits是1G,requests基本使用是512M,而占用了最低需求的500M。基本需求并不会启动就全部占用

下面pod limits是2G,requests基本使用是1G,而占用了基本需求的800M。

第一个pod的已经分配的量已经接近使用的量,requests是512M,已经使用了500M。而后面的pod已经占用量与基本要求的量差距较大,requests是1G,占用量是800M。因此资源紧缺的情况下,关闭第一个pod。这种方式给予已占用量与需求量的比例来做决策,比例大的优先被关闭。

  • 此前节点有污点,为了方便使用,将污点untainted
[root@linuxea metrics]# kubectl taint node linuxea.node-1.com node_type-
node/linuxea.node-1.com untainted
[root@linuxea metrics]# kubectl taint node linuxea.node-2.com node_type-
node/linuxea.node-2.com untainted
[root@linuxea metrics]# kubectl taint node linuxea.node-3.com node_type-
node/linuxea.node-3.com untainted
[root@linuxea metrics]# 

相关文章

LeaferJS 1.0 重磅发布:强悍的前端 Canvas 渲染引擎
10分钟搞定支持通配符的永久有效免费HTTPS证书
300 多个 Microsoft Excel 快捷方式
一步步配置基于kubeadmin的kubevip高可用
istio全链路传递cookie和header灰度
REST Web 服务版本控制

发布评论