k8s的计算资源

  其他常见问题, 内部使用
内容纲要

概要描述


计算资源概述

计算资源分为两种:资源请求(requests)和资源限制(limits)。资源请求表示容器希望被分配到的资源,可以完全保证的资源;资源限制是容器最多能使用到的资源量的上限,这个上限值会影响节点上发生资源竞争时的解决策略。

当前版本计算资源分为CPU内存;CPU单位为core,内存单位为字节

详细说明


计算资源的参数

参数:()

spec.container[].resources.requests.cpu --> --cpu-shares
spec.container[].resources.limits.cpu --> --cpu-period
spec.container[].resources.requests.memory 没有转换docker run,只给kubernets的调度器
spec.container[].resources.limits.memory  --> --memory
    spec:
      containers:
      - args:
        - boot.sh
        - SEARCH_HEAD
        env:
        - name: HEAD_PORT
          value: "9100"
        - name: HEAD_TARGET_HOST
          value: ts-mjx-22:9200
        - name: HEAD_LOG_DIR
          value: /var/log/head
        image: ts-mjx-21:5000/transwarp/search-head:transwarp-5.2.3-final
        imagePullPolicy: Always
        name: search-head-search2
        resources:
          limits:
            cpu: "2"
            memory: 1025Mi
          requests:
            cpu: "2"
            memory: 1Gi
  • 如果上面几个没配置,会使用默认的,默认值取决于集群
  • requests没配置,默认requests值=limits值
  • 在任何情况下,limits值>=requests值

如果一个容器在运行过程中使用了超出其内存limits配置的内存限制(oom),那么它可能会被杀掉,如果这个容器是一个可重启的容器,那么之后它会被kubelet重新启动起来。

案例

在docker1.13.1(tdh6.0之前用)上,当container发生oom时,并不会被重新拉起

原因:

dockerd 1.13.1 里面存在死锁,或者在内存不足的情况下一些进程会异常退出。导致 dockerd 无法获取 containerd 的最新状态。

kubernetes认为container应该重启, 要重启container的时候. dockerd会发送kill信号给对应container的pid. 但是因为和containerd的链接断掉了. dockerd会认为这个container并没有杀掉. 会继续杀这个pid, 但是实际上pid可能已经是别的进程在使用了.
container里面的进程已经挂掉了. 但是dockerd无法发现. 这样服务的container就不会被重新启动.

现象:
pod状态为0/1 Running
使用kubectl exec 进入container时无法进入:
rpc error : code = 2 desc = containerd: container not found
mark

mark

查看Up的docker进程和实际docker进程发现不一致
mark

解决方案:

升级到docker-monitor 1.0.2,重启docker-monitor和docker

计算资源常见问题

  • pod状态为Pending,错误信息为FailedScheduling

    原因:scheduler 未能找到合适的节点,或选择的节点没有足够的资源来调度,此时会产生一个Events
    kubectl describe pod [pod名] | grep -A 3 Events

    这个是代表这个节点上的CPU已经不足以调度这个pod,同理memory(PodExceedsFreeMemory)

    Events:
      FirstSeen    LastSeen    Count From   Subobject    PathReason    Message
      36s      5s      6       {scheduler}   FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others

    解决办法:

    • 若是动态pod,且非label固定pod,那么可以增加更多的节点;
    • 停止一些不必要的pod,释放资源;
    • 检查pod的配置(pod配置cpu require 为2,但是节点上只有1,那么这个pod将永远无法在这个节点上调度)

    可以使用kubectl describe nodes [node名]

    总资源:

    Capacity:
    cpu:                12
    ephemeral-storage:  153525Mi
    memory:             32781488Ki
    pods:               200
    storage:            1006802Mi

    可分配资源:

    Allocatable:
    cpu:                12
    ephemeral-storage:  153525Mi
    memory:             32781488Ki
    pods:               200
    storage:            1006802Mi

    已分配资源

    Allocated resources:
    (Total limits may be over 100 percent, i.e., overcommitted.)
    CPU Requests  CPU Limits  Memory Requests  Memory Limits
    ------------  ----------  ---------------  -------------
    0 (0%)        0 (0%)      0 (0%)           0 (0%)
    

    mark

    ps:TDH没有对container做任何限制,是通过限制进程的内存和CPU来限制资源。

  • pod状态为Terminated
    当容器使用的资源超过了它配置的Limits,那么它可能会被强制终止,状态为Terminated。但状态为Terminated的原因不用一定是因为使用的资源超过了它配置的Limits。

    kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name:"}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' [pod名]

    [root@ts-mjx-21 ~]#  kubectl get pod  -o go-template='{{range.status.containerStatuses}}{{"Container Name:"}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' inceptor-server-inceptor1-7b67b546f6-h8q5j
    Container Name:inceptor-server-inceptor1
    LastState: map[terminated:map[finishedAt:2019-09-04T09:07:19Z reason:Error startedAt:2019-09-04T09:07:03Z containerID:docker://b1378a99e33302c2afc1abbae19227c4a59025f157e3908e97dd9c988e615b21 exitCode:1]]
    [root@ts-mjx-21 ~]#
    

    这个是未能启动docker container,即docker container出现了问题,需要排查container的问题

资源限制

创建namespace

  [root@ts-mjx-21 yaml]# kubectl create namespace front
  namespace "front" created
  [root@ts-mjx-21 yaml]#

创建资源限制文件:limit.yaml

  apiVersion: v1
  kind: LimitRange
  metadata:
      name: mylimits
  spec:
      limits:
      - max:
           cpu: "4"
           memory: 2Gi
        min:
           cpu: 20m
           memory: 6Mi
        maxLimitRequestRatio: 
          cpu: 3      ---limits值:requests值<=3
          memory: 2
        type: Pod  
       ---------------
      - default:
          cpu: 300m
          memory: 200Mi
        defaultRequest:
           cpu: 200m
           memory: 100Mi
        max:
           cpu: 2
           memory: 1Gi
        min:
           cpu: 100m
           memory: 3Mi
        maxLimitRequestRatio:
           cpu: 5
           memory: 4
        type: Container

pod不能设置default request和default limit

  [root@ts-mjx-21 yaml]# kubectl create -f limits.yaml --namespace=front
  limitrange "mylimits" created
  [root@ts-mjx-21 yaml]# kubectl describe limits mylimit --namespace=front
  Name:       mylimits
  Namespace:  front
  Type        Resource  Min   Max  Default Request  Default Limit  Max Limit/Request Ratio
  ----        --------  ---   ---  ---------------  -------------  -----------------------
  Pod         cpu       20m   4    -                -              3
  Pod         memory    6Mi   2Gi  -                -              2
  Container   cpu       100m  2    200m             300m           5
  Container   memory    3Mi   1Gi  100Mi            200Mi          4

  [root@ts-mjx-21 yaml]#
  [root@ts-mjx-21 yaml]# kubectl run zk --image=ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final --namespace=front
  deployment "zk" created
  [root@ts-mjx-21 yaml]# kubectl get pod -n front
  NAME                 READY     STATUS              RESTARTS   AGE
  zk-69b8c766c-9xhsx   0/1       ContainerCreating   0          13s
  [root@ts-mjx-21 yaml]# kubectl get pod -n front
  NAME                 READY     STATUS              RESTARTS   AGE
  zk-69b8c766c-9xhsx   0/1       ContainerCreating   0          32s
  [root@ts-mjx-21 yaml]# kubectl get pod zk-69b8c766c-9xhsx -n front -o yaml | grep resources -C 8
    resourceVersion: "5418021"
    selfLink: /api/v1/namespaces/front/pods/zk-69b8c766c-9xhsx
    uid: 59d9615c-cf06-11e9-920b-005056a6098a
  spec:
    containers:
    - image: ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final
      imagePullPolicy: IfNotPresent
      name: zk
      resources:
        limits:
          cpu: 300m
          memory: 200Mi
        requests:
          cpu: 200m
          memory: 100Mi
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
  [root@ts-mjx-21 yaml]#

失败案例:

  [root@ts-mjx-21 yaml]# cat invalid-pod.yaml
  apiVersion: v1
  kind: Pod
  metadata:
    name: invalid-zk
  spec:
    containers:
    - name: invalid-zk
      image: ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final
      resources:
        limits:
          cpu: "3"
          memory: 100Mi
  [root@ts-mjx-21 yaml]# kubectl create -f invalid-pod.yaml --namespace=front
  Error from server (Forbidden): error when creating "invalid-pod.yaml": pods "invalid-zk" is forbidden: maximum cpu usage per Container is 2, but limit is 3.

可以看到无法创建pod,资源限制,同样可以调整limits和requets的比例,超过2时会报错

  [root@ts-mjx-21 yaml]# cat invalid-pod-limit.yaml
  apiVersion: v1
  kind: Pod
  metadata:
    name: invalid-zk
  spec:
    containers:
    - name: invalid-zk
      image: ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final
      resources:
        limits:
          cpu: "1"
          memory: 512Mi
        requests:
          cpu: "0.8"
          memory: 250Mi
  [root@ts-mjx-21 yaml]# kubectl create -f invalid-pod-limit.yaml --namespace=front
  Error from server (Forbidden): error when creating "invalid-pod-limit.yaml": pods "invalid-zk" is forbidden: memory max limit to request ratio per Pod is 2, but provided ratio is 2.048000.
  [root@ts-mjx-21 yaml]#

Resource QoS

requests和limits对不同计算资源类型的限制机制
在配置资源时要确保:

​ requests ​ requests <= limits

  • 可压缩资源

    • 可压缩资源只有CPU

    • pod可以得到requests配置的CPU使用量,是否能使用超过Requests的值的部分取决于系统的负载和调度

    • 空闲CPU资源按照容器Requests值的比例分配,最大不超过limits值

    • 如果pod使用了超过limits值,那么cgroups会对pod中的容器的CPU做限流,如果pod没有配置limits,那么pod会抢占所有空闲的CPU资源(从v1.2版本开始默认是开启--cpu-cfs-quata,因此默认情况必须配置Limits)

    • 不可压缩资源

    • 不可压缩资源目前有内存

    • 如果pod使用了少于requests值的内存,那么这个pod可以正常运行,但是当pod使用超过requests值而小于limits,那么当其他少于requests 内存的pod需要申请requests内的内存资源或者需要部署pod到这个节点上,那么kubernetes可能会杀掉这个pod,来释放内存

    • 当pod使用了超过limits值的内存时,kernel会杀掉pod所有容器的所有进程中使用内存最多的一个,直到pod内存使用不超过limits为止。

    • 对调度策略的影响

    • kubelet通过计算pod中所有容器的requests的总和来决定对pod的调度

    • 不管是CPU和内存,scheduler和kubelet都会确保节点上所有的pod的requests的综合不会超过该节点上可分配给容器使用的资源容量上限

    • QoS Classes

    在一个over committed的系统中,由于容器负载的波动可能导致操作系统的资源不足,那么最终可能有部分container被杀掉,有下面几个衡量container重要性的等级。
    • Guaranteed(非常可靠)
      pod中所有容器都定义了requests和limits,且requests和limits值相等不为0,或只定义limits,未定义requests(未定义requests时,requests和limits一致)
    • Burstable(较可靠的),
      pod的一部分容器在一种或多种资源类型的资源配置中定义了requests和limits,且requests小于limits(都不为0);pod一部分容器未定义资源配置(requests和limits都未定义)
    • Best-Effort(不太可靠)
      pod中所有容器都未定义requests和limits

      TDH所有pod都是Best-Effort

      查看qosclass等级:
      kubectl get pod [pod名] -o yaml | grep -C 5 qosClass

      [root@ts-mjx-21 ~]# kubectl get pod inceptor-server-inceptor2-75d98bcb7b-sg579 -o yaml | grep -C 5 qosClass
      running:
        startedAt: 2019-08-29T10:49:06Z
      hostIP: 172.22.21.23
      phase: Running
      podIP: 172.22.21.23
      qosClass: BestEffort
      startTime: 2019-08-29T10:49:05Z
    [root@ts-mjx-21 ~]#
    • 特点
      当CPU Requests无法得到满足时,容器得到的CPU会被压缩限流

      当内存资源不足时

      • Best-Effort的pod会被第一优先级杀掉。(由于没有设置limits,这类pod在资源充足情况下可以充分使用所有闲置资源)
      • Burstable的Pod,当系统资源不足,且没有Best-Effort pod可以被杀死时,这类pod会被杀掉
      • Guaranteed 一般情况下这类pod不会被杀死,但是当资源紧缺,又没有更低等级的pod时,也会被杀掉
    • OOM记分值

      oom基础分 = 进程消耗内存百分比 * 100 * 10 (0-1000)

      oom最终分 = oom基础分 + oom_score_adj (0-1000)

      • Guaranteed pod的最终分一般是0或1
      • BestEffort pod的最终分肯定是1000
      • Burstable Pod的最终分范围是2-1000

      oom_score_adj:

QoS oom_score_adj
Guaranteed -998
Burstable min(max(2,1000-(1000 * memoryRequestBytes) / machineMenmoryCapacityBytes), 999)
BestEffort 1000

如果一个Burstable Pod的某个容器中某个进程使用的内存比容器的request值高,那么这个进 程的OOM最终分数会是1000,否则它的OOM最终分会小于1000

OOM的特殊记分规则:

  • kubelet和docker的OOM_SCORE_ADJ为-998
  • 如果配置进程调整值OOM_SCORE_ADJ为-999,那么这类进程不会被OOM Killer 杀掉

这篇文章对您有帮助吗?

平均评分 0 / 5. 次数: 0

尚无评价,您可以第一个评哦!

非常抱歉,这篇文章对您没有帮助.

烦请您告诉我们您的建议与意见,以便我们改进,谢谢您。