Kubernetes资源管理

资源requests如何影响调度

调度器如何判断Pod调度到某个节点上

  1. 通过设置资源requests,可以设置Pod的最小资源分配请求,调度器在调度时只考虑那些未分配资源量满足Pod需求量的节点
  2. 调度器在调度时并不关心各类资源在当前的实际使用量,而是关注节点上部署所有Pod的资源requests的总和,当一个节点的request > capacity那么调度器将不予Pod分配该节点,否则会启动失败

调度器在调度时如何选择最佳节点

  1. 二个函数LeastRequestedPriority & MostRequestedPriority
  2. LeastRequestedPriority 优先将Pod调度到requests相对较少的节点上
  3. MostRequestedPriority 优质将Pod调度到requests相对较多的节点上
  4. 但是调度器在调度时只有选择一种函数,那么在什么情况下会使用MostRequestedPriority函数呢,在云计算环境背景下,计算实例是按节点计费的,通过让Pod紧凑型编排,这时就可以使用MostRequestedPriority函数以节省费用的开销

如果查看节点的资源使用状态

  1. 在Kubernetes集群中调度器apiserver需要知道每个集群节点的资源使用情况,比如有多少CPU & MEM并且已被分配了多少量,在Kubernetes每个节点上都安装一个kubelet的组件,Kubelet会定时向API-server发送节点的资源状态数据,并通过节点资源对外访问(schedule controller通信)
  2. 查看节点的资源使用情况,如下命令
     1 <root@HK-K8S-CP ~># kubectl describe nodes hk-k8s-wn1 
     2 Name:               hk-k8s-wn1
     3 Roles:              worker
     4 Labels:             beta.kubernetes.io/arch=amd64
     5                     beta.kubernetes.io/os=linux
     6                     kubernetes.io/arch=amd64
     7                     kubernetes.io/hostname=hk-k8s-wn1
     8                     kubernetes.io/ingress=pre
     9                     kubernetes.io/os=linux
    10                     node-role.kubernetes.io/worker=
    11                     topology.diskplugin.csi.alibabacloud.com/zone=cn-hongkong-c
    12 Annotations:        csi.volume.kubernetes.io/nodeid: {"diskplugin.csi.alibabacloud.com":"i-j6cg230darhjdqdf9n75"}
    13                     io.cilium.network.ipv4-cilium-host: 172.20.0.105
    14                     io.cilium.network.ipv4-health-ip: 172.20.0.102
    15                     io.cilium.network.ipv4-pod-cidr: 172.20.0.64/26
    16                     kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
    17                     node.alpha.kubernetes.io/ttl: 0
    18                     volumes.kubernetes.io/controller-managed-attach-detach: true
    19 CreationTimestamp:  Tue, 16 Mar 2021 14:04:25 +0800
    20 Taints:             <none>
    21 Unschedulable:      false
    22 Lease:
    23   HolderIdentity:  hk-k8s-wn1
    24   AcquireTime:     <unset>
    25   RenewTime:       Fri, 13 Aug 2021 15:29:41 +0800
    26 Conditions:
    27   Type                 Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
    28   ----                 ------  -----------------                 ------------------                ------                       -------
    29   NetworkUnavailable   False   Tue, 16 Mar 2021 23:44:59 +0800   Tue, 16 Mar 2021 23:44:59 +0800   CiliumIsUp                   Cilium is running on this node
    30   MemoryPressure       False   Fri, 13 Aug 2021 15:28:39 +0800   Tue, 16 Mar 2021 14:04:25 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available
    31   DiskPressure         False   Fri, 13 Aug 2021 15:28:39 +0800   Tue, 16 Mar 2021 14:04:25 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure
    32   PIDPressure          False   Fri, 13 Aug 2021 15:28:39 +0800   Tue, 16 Mar 2021 14:04:25 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available
    33   Ready                True    Fri, 13 Aug 2021 15:28:39 +0800   Tue, 16 Mar 2021 23:44:57 +0800   KubeletReady                 kubelet is posting ready status
    34 Addresses:
    35   InternalIP:  172.19.1.120
    36   Hostname:    hk-k8s-wn1
    37 Capacity:
    38   cpu:                2
    39   ephemeral-storage:  41152812Ki
    40   hugepages-1Gi:      0
    41   hugepages-2Mi:      0
    42   memory:             3883608Ki
    43   pods:               110
    44 Allocatable:
    45   cpu:                2
    46   ephemeral-storage:  37926431477
    47   hugepages-1Gi:      0
    48   hugepages-2Mi:      0
    49   memory:             3781208Ki
    50   pods:               110
    51 System Info:
    52   Machine ID:                 20191225111607875619293640639763
    53   System UUID:                dcbce1f0-bd51-4124-b199-a0d81cf89874
    54   Boot ID:                    b0ee5748-9383-46a9-91cb-a984f869ed40
    55   Kernel Version:             5.11.1-1.el7.elrepo.x86_64
    56   OS Image:                   CentOS Linux 7 (Core)
    57   Operating System:           linux
    58   Architecture:               amd64
    59   Container Runtime Version:  docker://19.3.12
    60   Kubelet Version:            v1.18.5
    61   Kube-Proxy Version:         v1.18.5
    62 PodCIDR:                      172.20.1.0/24
    63 PodCIDRs:                     172.20.1.0/24
    64 Non-terminated Pods:          (10 in total)
    65   Namespace                   Name                                             CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
    66   ---------                   ----                                             ------------  ----------  ---------------  -------------  ---
    67   default                     prometheus-kube-state-metrics-858f88ff6-gb2lh    0 (0%)        0 (0%)      0 (0%)           0 (0%)         56d
    68   default                     prometheus-node-exporter-cq6fp                   0 (0%)        0 (0%)      0 (0%)           0 (0%)         56d
    69   default                     rabbitmq-1                                       1 (50%)       1 (50%)     2Gi (55%)        2Gi (55%)      56d
    70   default                     zk-1                                             100m (5%)     0 (0%)      128M (3%)        0 (0%)         77d
    71   kube-system                 cilium-operator-789c9b45c9-fvjkx                 0 (0%)        0 (0%)      0 (0%)           0 (0%)         149d
    72   kube-system                 cilium-wcrm7                                     100m (5%)     0 (0%)      100Mi (2%)       0 (0%)         149d
    73   kube-system                 csi-plugin-tsjwb                                 100m (5%)     500m (25%)  128Mi (3%)       1Gi (27%)      88d
    74   kube-system                 hubble-relay-7995686985-bhp4k                    0 (0%)        0 (0%)      0 (0%)           0 (0%)         146d
    75   kube-system                 hubble-ui-769fb95577-kqn7m                       0 (0%)        0 (0%)      0 (0%)           0 (0%)         146d
    76   kube-system                 kube-router-njnhh                                250m (12%)    0 (0%)      250Mi (6%)       0 (0%)         149d
    77 Allocated resources:
    78   (Total limits may be over 100 percent, i.e., overcommitted.)
    79   Resource           Requests         Limits
    80   --------           --------         ------
    81   cpu                1550m (77%)      1500m (75%)
    82   memory             2711624Ki (71%)  3Gi (83%)
    83   ephemeral-storage  0 (0%)           0 (0%)
    84   hugepages-1Gi      0 (0%)           0 (0%)
    85   hugepages-2Mi      0 (0%)           0 (0%)
    86 Events:              <none>

 CPU requests如何影响CPU时间分配

  1. 比如在一个节点上,创建了二个Pod,一个Pod的CPU是200m;一个Pod是1000m(requests只是在调度分配时指定最小请求值并不能限制Pod实际使用上限)requests不仅在调度时起作用,它还决定Pod是如何请求CPU分配时间,如果二个Pod同时负载情况下消耗CPU时,那么在请求分配CPU时间片时,会按照requests的比例来分配CPU,意味着就是1:5的比例分配CPU

限制容器可用资源

  1. CPU是一种可压缩的资源,意味着可以在不对容器内运行的进程产生不利的影响的同时,对其进行使用量的限制,而内存明显不同是一种不可压缩的资源,一旦系统为进程分配了一块内存后,在未被进程主动释放前操作系统不会主动回收这部分空间,这就是为什么需要针对内存设置limits
  2. 如果不对Pod的CPU & MEM设置limits限制,由于Pod是在部署一个共有的节点上,那么在突发事件故障时,由于一个Pod将该节点的资源消耗完,那么势必会造成其它Pod无法正常运行1 resources:
    1           resources:
    2             limits:
    3               cpu: '1'
    4               memory: 1Gi
    5             requests:
    6               cpu: 100m
    7               memory: 512Mi

Kubernetes如何处理 overlimits

  1. CPU的反应:进程不等待IO操作时消耗所有的CPU时间是非常常见的,如果在Kubernetes集群Pod设置CPU limits值时,如果该Pod遇到CPU负载时, 那么此时该Pod只会被限制在limits值内,不会分配到大于limits的CPU

  2. 内存的反应:内存则并不相同,当进程尝试申请分配大于limits的值时,此时会触发OOM,kill掉Pod,如果Pod的重启策略是Always或者是OnFailure时,Pod会自动重启,如果反重启则会触发Kubernetes内部策略机制,则增加下次重启的时间间隔(具体时间kubelet在第一次会以10s时间间隔等待,如果反复重启则会以倍数时间增加即20,40,80,160一致至300s,后面会以300s的时间间隔进行重启,直到Pod正常或者被delete),这种情况下就会看到Pod处于CrashLoopBackOff状态

  3. 定位Pod的crash的原因也很简单,执行kubectl des pod_name

容器中的应用如何看待limits

  1. 在设置了limits值时,但是exec到容器中top发现实际的内存或是CPU玩玩超出设置的limits值,结论是:在容器中看到的资源始终是节点的,而非Pod本身的资源

  2. 在java应用时需要注意,在早期的jdk版本时,并不支持 -XX:+UseContainerSupport 参数,这将无法控制ava进程堆外内存,会出现OOM的情况,好在jdk新版本之后1.8_191之后支持该参数以识别Pod的limits值来避免这一类问题

  3. CPU的limits并非限制使用几个CPU的核数及其它,而是限制Pod使用所在节点的CPU时间切片,比如一个64C的节点,而为Pod限制了1000m,此Pod只是获得了1/64的CPU时间,但是容器内的进程不会运行在一个核上,而是分散在多个核上执行,但是一些垃圾程序是通过查询系统CPU核数决定启动多少个线程,针对这种情况可以从Pod获取具体CPU的信息如(/sys/fs/cgroup/cpu/cpu.cfs_quota/period_us)或者使用其它方法

 Pod QoS等级

背景介绍:在上文已经说明了,CPU可以overlimits,优点就是在一个节点上所有的Pod不可能把所有的CPU消耗完,多个Pod可以共同使用,那么会衍生另一个问题(在资源消耗殆尽时)比如:Pod-A使用了该节点的90%内存,Pod-B突发事件受到内存压力情况下可能会消耗节点的%20的内存乃至需求更多的内存,此时Kubernetes该终结哪一个Pod呢,以释放内存保留其中一个Pod呢,Kubernetes引入了QoS概念,Qos一共分三个等级如下

  • BestEffort(优先级最低)
  • Burstable
  • Guaranteed(优先级最高)

如何定义Pod的Qos等级

先了解一下Qos的等级优势,BestEffort最低等级,优先被Kill掉,最没有资源保障,其次是Burstable,再次Guaranteed,那如何定义Qos的等级,如下

  1. Pod没有定义requests & limits配置,定义等级就为BestEffort
  2. Pod定义requests 没有定义limits;或者二者的值不等;或者Pod多容器的状态下(定义,未定义,定义不等)都视为 Burstable等级
  3. Pod定义了requests & limits值,并且二者相等,定义等级为Guaranteed

资源不足Kill顺序

BestEffort > Burstable > Guaranteed

如果都是Guaranteed 等级的话,就对比进程的OOM分数值,谁高杀谁

CPU requests vs. limits mem requests vs. limits   Qos level
none none   BestEffort
none requests < limits Burstable
none requests = limits Burstable
requests < limits none Burstable
requests < limits requests < limits Burstable
requests < limits requests = limits Burstable
requests = limits requests = limits Guaranteed
posted @ 2021-08-13 15:03  MacoPlus  阅读(201)  评论(0编辑  收藏  举报