调度架构

Kubernetes调度架构

调度单元

Pod调度

当新增一个Pod时,集群会在可用的集群节点中寻找最合适的节点来运行相应的容器。Kubernetes首先会排除无效节点:

  • 节点状态为不可用的,如,节点不通或者K8s服务运行异常等;
  • 节点剩余的CPU,内存资源不足以运行容器的;
  • 容器运行时占用的宿主机端口出现冲突的;
  • 按照节点选择label不匹配的;

Pod.spec.nodeSelector通过kuberneteslabel-selector机制选择节点,由调度器调度策略匹配label,而后调度pod到目标节点,该匹配规则属于强制约束。

然后通过打分机制决定将Pod具体调度到剩余机器中的那一台,默认调度节点选择策略权重为1,节点的调度规则是采用plugin方式,允许自行编写调度策略进行打分处理。

# 标准打分公式
score = (权重 * 评价策略分值)  + (weight1 * priorityFunc1) + (weight2 * priorityFunc2) + ...

# LeastRequestedPriority
score = cpu((capacity - sum(requested)) * 10 / capacity) + memory((capacity - sum(requested)) * 10 / capacity) /2

# BalanceResourceAllocation
score = 10 -abs (cpuFraction - memoryFraction) * 10
cpuFraction = requested / capacity;           memoryFraction = requested / capacity

# CalculateSpreadPriority
score = 10 * ((maxCount -counts) / (maxCount))
  • LeastRequestedPriority: CPU可用资源为100,运行容器申请的资源为15,则cpu分值为8.5分,内存可用资源为100,运行容器申请资源为20,则内存分支为8分。则此评价规则在此节点的分数为(8.5 +8) / 2 = 8.25分。

  • BalanceResourceAllocation: CPU可用资源为100,申请10,则cpuFraction0.1,而内存可用资源为20,申请10,则memoryFraction0.5,这样由于CPU和内存使用不均衡,此节点的得分为10-abs ( 0.1 - 0.5 ) * 10 = 6分。假如CPU和内存资源比较均衡,例如两者都为0.5,那么代入公式,则得分为10分。

  • CalculateSpreadPriority:一个web服务,可能存在5个实例,例如当前节点已经分配了2个实例了,则本节点的得分为10 _ ((5-2) / 5) = 6分,而没有分配实例的节点,则得分为10 _ ((5-0) / 5) = 10分。没有分配实例的节点得分越高。

资源保障

目前,Kubernetes只支持CPUMemory两种资源的申请,Kubernetes中,根据应用对资源的诉求不同,把应用的QoS按照优先级从高到低分为三大类:Guaranteed, BurstableBest-Effort。三种类别分别表示资源配额必须交付、尽量交付以及不保障。QoS等级是通过resourceslimitsrequests参数间接计算出来的。CPU为可压缩资源,Node上的所有Pods共享CPU时间片,原理是通过设置cpu.cfs_quota_uscpu.cfs_period_us实现,一个CPU逻辑核嘀嗒时间被切了N份,只要按照百分比例设置cpu.cfs_quota_us的值就可以实现CPU时间片的比例分配,如设置2N表示利用两个CPU逻辑核的时间。Memory为不可压缩资源,kubernetes中主要利用memory.limit_in_bytes实现内存的限制。当应用内存超过了它的limits,那么会被系统OOM。内存是不可压缩资源,它的保障的机制最为复杂,kubernetes利用内核oom_score机制,实现了对Pod容器内(进程)内存oom kill的优先级管控,内核中OOM Score的取值范围是[-1000, 1000],值越大,被系统KILL的概率就越高。

Guaranteed

如果Pod中每一个容器都只设置了limits参数,或者 同时设置了limitsrequests并且limitsrequests的值一样,那么这个Pod就是Guaranteed类型的。

containers:
  name: foo
    resources:
      limits: //只设置了limits
        cpu: 10m
        memory: 1Gi
  name: bar
    resources:
      limits:
        cpu: 100m
        memory: 100Mi
      requests:  //requests  limits均已设定,并且值相同
        cpu: 100m
        memory: 100Mi

Burstable

当以下情形设置,Pod会为定位成Burstable类型, Busrtable类型保障了资源的最小需求,但不会超过limits

  • Pod里的一个或多个容器只设置了requests参数。
  • Pod里的一个或多个容器同时设置了requestslimits参数,但是两者值不一样。
  • Pod里的所有容器均设置了limits,但是他们的类型不一样,不如容器1只定义了CPU,容器2只定义了Memory
  • Pod里存在多个容器时,其中存在容器可被定义为Bustable条件的Pod也是Bustable类型,比如有两个容器,容器1设置了limits,容器2没有任何设置。
containers:
  name: foo
    resources:
      limits:
        memory: 1Gi

  name: bar
    resources:
      limits:
        cpu: 100m

  name: duck

BestEffort

Pod中所有的容器均没设置requestslimits,那么这个Pod即为BestEffort类型,他们可消费所在Node上所有资源,但在资源紧张的时候,也是最优先被杀死。

containers:
  name: foo
    resources:
  name: bar
    resources:

Links

下一页