水有三峡 發表於 2019-6-17 07:55:00

kubernetes调度之pod优先级和资源抢占

<blockquote>
<p>系列目录</p>
</blockquote>
<p>Pod可以拥有优先级.优先意味着相对于其它pod某个pod更为重要.如果重要的pod不能被调度,则kubernetes调度器会优先于(驱离)低优先级的pod来让处于pending状态的高优先级pod被调度.</p>
<p>kubernetes 1.9以后,优先级会影响pod的调度顺序和资源耗尽时pod的驱离顺序</p>
<blockquote>
<p>警告:在一个不是所有用户都被信任的集群里,可能有恶意用户创建最高可能优先级的pod,导致其它pod被驱离或者无法调度.为了解决这个问题,需要增大资源配额来支持优先pod.集群管理员可以为特定用户创建特定优先级级别,防止他们创建高优先级的pod.这项功能在1.12版本里为beta状态.</p>
</blockquote>
<h2 id="怎样使用优先级和抢占">怎样使用优先级和抢占</h2>
<p>在1.11或以后的版本里,按下面指示来操作:</p>
<ul>
<li>
<p>创建一个或者多个<code>PriorityClasses</code></p>
</li>
<li>
<p>创建一个pod,并把<code>priorityClassName</code>设置为以上添加的<code>priorityClassName</code>中的一个.当然你不必直接创建pod,你可以把<code>priorityClassName</code>添加到集合对象(比如deployment)的template里.</p>
</li>
</ul>
<p>如果你仅想尝试这项功能并且然后把它禁用,你必须把<code>PodPriority</code>设置为false,然后重启apiserver和调度器.被禁用以后,已经存在的pod仍然保留有它们的优先级字段,但是抢占不会再生效,并且优先字段被忽略.你也不能再向新的pod添加<code>priorityClassName</code>字段</p>
<h2 id="怎样禁用抢占">怎样禁用抢占</h2>
<blockquote>
<p>在kubernetes 1.12+ 当集群处于较大资源压力时,一些关键的pod依赖抢占调度.因此强烈为建议禁用抢占</p>
</blockquote>
<p>在kubernetes1.11以后版本,抢占被kube-scheduler的的<code>disablePreemption</code>标识控制,默认设置是false.如果你不顾建议仍然想要禁用它,可以把它设置为true</p>
<p>这个选项仅仅在组件的配置里有效,在旧式的命令行下无效.下面是一个配置的示例:</p>
<pre><code class="language-yml">apiVersion: componentconfig/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
provider: DefaultProvider

...

disablePreemption: true
</code></pre>
<h2 id="抢占">抢占</h2>
<p>当pod被创建,他们进入队列等待被调度.调度器从队列取出一个pod并且尝试把它调度到一个节点上.如果没有节点能够满足这个pod的所有要求,抢占逻辑被触发,我们把这个挂起的pod称作P.调度器尝试寻找移除一个或者多个比P低的pod后能够使得P被调度的节点.如果找到了一个这样的节点,一个或者多个优先级低的节点被驱离,然后P被调度到这个节点上.</p>
<p>当pod P抢占了Node N上的一个或者多个pod的资源,P的<code>nominatedNodeName(候选节点)</code>字段被设置为节点N的名字.这个字段帮助调度器追踪为P预留的资源信息,并给用户提供集群资源抢占的一些信息.</p>
<p>需要注意的是pod P并不总是调度到候选节点(nominated Node)上,当受害的pod被抢占,他们进入终止阶段.当受害pod停止的过程中其它节点变得可用,这时候调度器就会使用这个可用的节点来接收pod P,这样就造成<code>nominatedNodeName</code>和<code>nodeName</code>并不总是相同.并且,pod P抢占了节点N上的优先级低的pod的资源时,这时候有更高优先级的pod到达,这时候调度器可能会把节点N让给这个更高优先级的pod使用.这时候调度器会清除pod P的<code>nominatedNodeName</code>字段,这样,调度器使用pod P可以抢占其它节点上的资源.</p>
<h2 id="抢占限制">抢占限制</h2>
<h3 id="受害pod的优雅终止">受害pod的优雅终止</h3>
<p>当被抢占,受害pod进入优雅终止期,它们将有时间完成工作并退出.否则,会被杀掉.这个优雅终止期在调度器抢占受害pod资源和优先pod被调度到Node N之间创建了一个时间间隔.同时,调度器继续调度其它状态为<code>pending</code>的pod.为了缩短这个时间间隔,用户可以把优雅终止期设置为0或者一个很小的时间</p>
<h3 id="低优先级pod的pod间亲和性">低优先级pod的pod间亲和性</h3>
<p>问题:如果所有低优先级的pod都从一个节点上移除了,那么挂起(pending)的pod是否可以调度到此节点上?</p>
<blockquote>
<p>这个问题的意义在于如果所有的pod都被移除,资源仍然不够容纳挂起的pod会怎么样?</p>
</blockquote>
<p>仅当以上问题的答案是肯定的(yes)的时候,节点的抢占才会发生(也就是如果全部低优先级的pod都被驱离仍然不够容纳新的pod时,节点上不会发生抢占)</p>
<blockquote>
<p>需要注意的是,并不是总是要移除节点上的所有低优先级的pod.如果仅仅移除一些pod就足以容纳挂起的pod时,仅有部分低优先级的pod被移除.但是以上问题的答案仍然需要是肯定的(也就是说低优先级pod的移除建立在移除后资源足以容纳新的挂起的节点的基础上的)</p>
</blockquote>
<p>如果挂起的pod(即将被调度的)和一个或者多个节点N上的低优先级的pod有pod间亲和关系,如果低优先级pod离开后pod间的亲和关系不能被满足时,调度器这时候不会再抢占节点N上的pod.调度器可能会找到一个其它的合适的节点,也可能找不到.这就无法保证挂起的pod被调度.</p>
<blockquote>
<p>对于这个问题我们的建议是创建pod间亲和关系时,只向同等优先级和更高优先级的pod创建.</p>
</blockquote>
<h3 id="跨节点抢占">跨节点抢占</h3>
<p>假设Node N 上准备抢占以便是pod P可以被调度到N上,但是P依赖于其它节点上的pod被驱离才可以被调度到N上,以下示例说明这个问题</p>
<ul>
<li>
<p>Pod P准备调度到节点N上</p>
</li>
<li>
<p>pod Q们于和节点N同一区域的其它节点上</p>
</li>
<li>
<p>pod P和pod Q有区域级别的反亲和关系(topologyKey: <code>failure-domain.beta.kubernetes.io/zone</code>)</p>
</li>
<li>
<p>pod P和同一区域内的其它pod没有反亲和关系</p>
</li>
<li>
<p>为了把pod P调度到节点N上,Pod Q可以被抢占,但是调度器不会执行跨节点抢占,因此pod P不会被调度到节点N上.</p>
</li>
<li>
<p>如果pod Q从它的节点上移除,这时候违反亲和关系也消失,此时pod P可能会被调度到节点N上</p>
</li>
<li>
<p>在未来的版本中如果能找到一个能保证性能的算法,我们可能会考虑增加跨节点驱离.但是目前我们什么都不能保证.</p>
</li>
</ul>
<h2 id="调度pod优先级和抢占">调度pod优先级和抢占</h2>
<p>pod优先级和资源抢占的编排如果有bug的话则往往是导致节点调度中断的主要原因之一</p>
<h3 id="pod优先级和资源抢占可能导致的问题">pod优先级和资源抢占可能导致的问题</h3>
<p>以下是如果pod优先级和资源抢占包含bug可能导致的问题的不完全罗列:</p>
<ul>
<li>pod被非必要地抢占</li>
</ul>
<p>当集群出现资源压力时,调度器会移除优先级低的pod来为优先级高的pod腾出资源,如果用户错误地给分配给一些pod过高的优先权,这些无意分配的高优先权会导致集群抢占.像上面提到的,pod的优先权通过设置<code>podSpec</code>字段的<code>priorityClassName</code>来实现的,优先级的整数字段然被解析后传入到<code>podSpec</code>字段的<code>priority</code>字段里</p>
<p>为了解决这个问题,<code>priorityClassName</code>字段必须改变到更小的优先级或者留空,<code>priorityClassName</code>字段留空会被解析为0</p>
<p>当一个pod被抢占,则它会产生一条event记录来记录这个事件.仅当集群没有足够的资源时抢占才会发生.这种情况仅发生在(挂起)的pod的优先级高于受害pod.如果没有挂起的pod,则抢占事件一定不能发生.如果没有挂起pod,或者挂起pod的优先级等于或小于受害pod时发生抢占事件,则是系统bug,请提交一个issue给我们.</p>
<h3 id="pod被抢占但是抢占的pod并没有被调度">pod被抢占,但是抢占的pod并没有被调度</h3>
<p>当pod被抢占,他们将接收到一个优雅停止的时间段,默认是30秒,但是也可以是任意在podSpec里指定的值.如果受害pod没有在指定的时段里停止,他们会被强行终止.当所有受害者都被移除,优先pod可以被调度.</p>
<p>当优先pod等待受害者被移除时,一个适合调度到这个节点上的更高优先级的pod被创建.这时候调度器会优先调度这个更高优先级的pod</p>
<h3 id="高优先级的pod比优先级更低的pod被抢占">高优先级的pod比优先级更低的pod被抢占</h3>
<p>调度器会尽力寻找适合的节点来调度挂起的pod,如果找不一节点来调度,调度器会从一个包含低优先级的节点上移除pod来为挂起的pod腾出空间.如果有低优先级pod的节点不适合被调度,调度器可能会选择一个更高优先级的节点来抢占(这里说的更高是相对前面找到的低优先级的pod而言的,而不是对优先pod而言的).被抢占的pod仍然必须要比优先pod(指挂起的需要调度的pod)优先级别低</p>
<p>当有多个节点可以被抢占时,调度器会尝试选择有最低优先级pod的节点来调度.但是如果pod有<code>PodDisruptionBudget</code>并且抢占可能会违反<code>PodDisruptionBudget</code>时,调度器可能会选择一个更高优先级的pod来抢占.</p>
<p>当有多个节点可以被抢占并且没有出现以上情形,则调度器会选择优先级最低的pod来抢占,如果不是这样的,则意味着调度器本身存在bug.</p>
<h2 id="pod优先级和qos交互">pod优先级和Qos交互</h2>
<p>pod优先级和QoS是两个正交的功能,几乎没有交叉.调度器的抢占逻辑当选择抢占对象时不会考虑QoS.抢占会考虑pod的优先级并选择出一系列低优先级抢占目标.只有当即便移除低优先级pod也不足以运行挂起的pod或者低优先级的pod被<code>PodDisruptionBudget</code>保护时,调度器才会选择更高优先级的pod作为抢占对象.</p>
<p>仅有Kubelet的 out-of-resource eviction组件才会同时考虑pod优先级和QoS,kubelet首先会根据使用的资源是否超过请求的值来对要驱离的pod进行排序,然后根据优先级.Kubelet out-of-resource eviction 不会驱离使用资源低于请求资源的pod,如果一个低优先级的pod使用的资源没有超过它请求的,则它不会被驱离.其它的使用资源超过其申请资源的更高优先级的pod可能会被驱离.</p><br><br>
来源:https://www.cnblogs.com/tylerzhou/p/11037731.html
頁: [1]
查看完整版本: kubernetes调度之pod优先级和资源抢占