k8s调度机制2 k8s调度机制2节点污点和pod容忍污点taint和容忍tolerations污点Taint ——它使节点能够排斥一类特定的 Pod是定义在节点的属性容忍度Toleration是应用于 Pod 上的属性。容忍度允许调度器调度 Pod到有污点的节点上。 容忍度允许调度但并不保证调度作为其功能的一部分 调度器也会评估其他参数。内置污点功能Kubernetes自1.6起支持使用污点自动标识问题节点它通过节点控制器在特定条件下自动为节点添加污点信息实现。它们都使用NoExecute效用标识因此非能容忍此类污点的现在Pod对象也会遭到驱逐。节点状态相关的某种条件为真时节点控制器会自动给节点添加一个污点node.kubernetes.io/not-ready节点进入NotReady状态时被自动添加的污点。 node.alpha.kubernetes.io/unreachable节点进入NotReachable状态时被自动添加的污点。 node.kubernetes.io/out-of-disk节点进入OutOfDisk状态时被自动添加的污点。 node.kubernetes.io/memory-pressure节点内存资源面临压力。 node.kubernetes.io/disk-pressure节点磁盘资源面临压力 node.kubernetes.io/pid-pressure节点PID资源紧张 node.kubernetes.io/network-unavailable节点网络不可用 node.kubernetes.io/unschedulable节点不可用于调度 node.cloudprovider.kubernetes.io/uninitializedkubelet由外部的云环境程序启动时它自动 为节点添加此污点待到云控制器管理器中的控制器初始化此节点时再将其删除。属性解析taint是节点上的属性kubectl explain node.spec.taints对象列表 key#定义一个keyvalue:effectvalue#定义一个值这是一个可选项effect#pod不能容忍这个污点时有三个行为值NoSchedule、PreferNoSchedule、NoExecutetimeAdded#记录污点被添加的具体时间,此属性仅与NoExecute类型的污点相关,在使用kubectl taint命令添加或删除污点时Kubernetes会自动处理TimeAdded属性的更新或移除,此字段由系统自动添加无需人为管理污点处理方式effect的属性值优先级从低到高范例查看属性#查看节点上的污点kubectl describenodemaster1.hajimi.org|grepTaint kubectl getnodemaster1.hajimi.org-oyaml... taints:#污点- effect: NoSchedule#效用标识key: node-role.kubernetes.io/master...#查看pod上的污点容忍度kubectl describe pod pod名|grep-A3Tolerations: Tolerations: node.kubernetes.io/not-ready:NoExecuteopExistsfor300stolerations容忍度属性这是pod上的属性kubectl explain pod.spec.tolerations key#被容忍的keyvalue#被容忍key的值,当operator为exists时,此value无需定义operator#Equal等值比较表示key对应的value值以及effect三者必须要和tains的值相同才能容忍,此为默认值#Exists 表示只要存在key和effect二者相同但不关注value就可容忍,必须不能定义value, 即可以调度Pod,如果没有定义key和effect,表示容忍所有污点effect#可以容忍的节点的行为值,必须和Traint中的effect值相同或高于才能容忍tolerationSeconds#被驱逐的宽限时间默认是0就是立即被驱逐容忍度的判断方式在pod对象上定义容忍度时支持两种操作符——一种是等值比较Equal表示容忍度与污点必须在key、value和effect三者之上完全匹配,此为默认值一种是存在性判断Exists表示keyeffect 二者必须完全匹配而容忍度tolerations中的value字段无需定义。特殊情况——operator为Exists且容忍度的key为空表示其可以容忍任意污点若effect为空则可以匹配所有键名相同的污点容忍度匹配原则一个节点可以配置使用多个污点而一个Pod对象也可以有多个容忍度遍历该节点的所有污点并过滤掉容忍度可匹配到的污点余下未被过滤掉的污点则由污点的effect来判定其满足状态对于剩余的不能匹配到容忍度的所有污点中若存在至少一个污点使用了NoSchedule效用标识则拒绝调度当前Pod至该节点对于不能匹配到容忍度的所有污点若都不具有NoSchedule效用标识但至少有一个污点使用了PreferNoScheduler效用标准则调度器会尽量避免将当前Pod对象调度至该节点如果至少有一个不能匹配容忍度的污点使用了NoExecute效用标识节点将立即驱逐当前Pod对象或者不允许该Pod调度至给定的节点而且即便容忍度可以匹配到使用了NoExecute效用标识的污点若在Pod上定义容忍度时同时使用tolerationSeconds属性定义了容忍时限则在超出时限后当前Pod也将会被节点所驱逐污点管理命令#查看污点Kubectl getnodenodename-ogo-template{{.spec.taints}}kubectl describe nodes|grep-itaint#添加污点#指定节点添加污点kubectl taintnodenode-namekeyvalue:effect...#所有节点添加污点kubectl taintnode-allkeyvalue:effect...#删除污点kubectl taintnodenode-namekey[:effect]- kubectl patch nodesnode-name-p{spec:{taints:[]}}#cordon封锁节点,即添加污点node.kubernetes.io/unschedulable:NoSchedule,只影响新Podkubectl cordonnode-name#删除污点node.kubernetes.io/unschedulable:NoSchedulekubectl uncordonnode-name#强制驱逐节点上pod#方法1drain 排空节点上面的 Pod,同时添加污点node.kubernetes.io/unschedulable:NoSchedule#注意:要删除node.kubernetes.io/unschedulable:NoSchedule污点,需要执行kubectl uncordonnode-name#--ignore-daemonsets 默认kubectl drain删除daemonset资源会报错,加此项可以忽略错误提示kubectl drainnodename--ignore-daemonsets --delete-emptydir-data--force#取消强制驱逐节点上Podkubectl uncordonnode-name#方法2:使用污点NoExecute实现kubectl taint nodes node3.wang.orgnamewang:NoExecute拓扑调度拓扑分布约束可以控制pod的调度实现平均分布的程度在定义pod亲和性和反亲和时有一个 topologyKey的属性但是默认情况下pod的亲和性调度仅仅针对单一的拓扑场景也就是说要么所有的pod都在这里要么所有的pod都不要在这里这样会导致应用过于集中反而导致物理资源的浪费。如果希望在进行正常pod亲和性调度的时候能够自动识别多个不同的调度节点然后均匀的分散到多个节点中从而实现资源的有效利用。通过拓扑调度来实现的功能敏置偏差Skew偏差Skew 是当前每一个拓扑域Pod数量和Pod数量最少的拓扑域之间的Pod数量的差值公式当前i拓扑域 skew[i] 拓扑域[i]中匹配的 Pod 个数 - min{拓扑域[*]中匹配的 Pod 个数}Pod分散约束策略基于允许的最大偏差(maxSkew)来定义Pod在拓扑域中的分散逻辑当无法满足最大偏差约束时whenUnsatisfable则用于定义妥协策略当无法满足最大偏差约束时whenUnsatisfable则用于定义妥协策略ScheduleAnyway根据每个节点的skew值打分排序后进行调度即软限制就是让pod分配的均匀一点不让资源分配过于极端。具体分配多少可以用公式来算属性解析kubectl explain pod.spec.topologySpreadConstraints labelSelector#根据 LabelSelector来计算出匹配的pod的数量maxSkew#描述了 pod 可能不均匀分布的程度不同拓扑域之间的各节点pod数量比例的最大限制topologyKey#用于指定带有此标签的值相同的节点在同一拓扑中。whenUnsatisfiable#指示如果 Pod 不满足扩展约束如何处理它。默认值是DoNotSchedule#maxSkew 默认值是1即各个不同的拓扑中的Pod总数量之差最大不能超过1如果这个值越大则pod的分布可能会是不均匀的。案例分析labelSelector用于查找匹配的 Pod。对于每个拓扑我们计算 与此标签选择器匹配的 Pod 数量。在上面的例子中给定 labelSelector为“app foo”“zone1”中的匹配数字为2;而 “Zone2”中的数字为 0。topologyKey是在节点标签中定义拓扑的键。如果两个 Node 的 label 同时具有该 key 并且 label 值相同就说它们在同一个拓扑域。在上图中指定 topologyKey 为 zone 具有 “zonezone1” 标签的 Node 被分在一个拓扑域具有zonezone2 标签的 Node 被分在另一个拓扑域。maxSkew描述了 Pod 在不同拓扑域中Skew不均匀分布的最大程度maxSkew 的取值必须大于0。每个拓扑域都有一个 skew计算的公式是skew[i] 拓扑域[i]中匹配的 Pod 个数 - min{拓扑域[*]中匹配的 Pod 个数}。skew 不能大于maxSkew 在上图中我们新建一个带有 “appfoo” label 的 Pod如果将传入的 Pod 放在 “zone1”则 “zone1” 上的偏斜 skew 值将变为 3 在“zone1”中匹配的 Pod为3个;在“zone2”上匹配的全局最小值为 0 个 Pod违反了“maxSkew 1”约束。如果将传入的 Pod 放置在 “zone2”则 “zone1“ 中 的 skew 值变为 1 “zone2” 上的偏斜skew 值为 0 (zone2 有 1 个匹配的 Pod拥有全局最小匹配 Pod 数的拓扑域正是 zone2 自己), 则满足“maxSkew 1”约束优先级调度背景集群资源不够用时候怎么办先到先得策略(FIFO):简单、相对公平、上手快优先级策略(Priority): 符合日常公司业务特点, 优先级值越大,优先级越高优先级调度过程(发生在Pending Pod出队列开始调度):Pod2(低优先级)和Pod1(高优先级)先后进入调度队列但均未被调度当进行一轮调度时PriorityQueue会优先将优先级更大的Pod1弹出队列进行调度调度成功后对此Pod1进行Bind并开始下一轮调度Pod2优先级抢占过程(发生在调度失败):Pod2先进行调度调度成功后分配至Node1上运行之后Pod1再进行调度由于Node1资源不足出现了调度失败此时进入抢占流程在经过抢占算法计算后选中了Pod2作为Pod1的承让者驱逐了Node1上运行的Pod2并将Pod1调度至Node1节点压力驱逐节点压力驱逐是 kubelet 主动终止 Pod 以回收节点上资源的过程当这些资源中的一个或者多个达到特定的消耗水平kubelet 可以主动驱逐节点上一个或者多个 Pod以回收资源防止出现资源饥饿。kubelet 会主动给节点打上一个或者多个污点标记这些标记的 effect 为 NoExecute内存比较紧张会打上 node.kubernetes.io/memory-pressure磁盘比较紧张会打上 node.kubernetes.io/disk-pressurepid 比较紧张会打上 node.kubernetes.io/pid-pressure而如果该节点上已有一些 Pod 在运行并且这些 Pod 没有配置以上三种对应的容忍度则 kubelet 会开始驱逐的流程一个一个的驱逐直到节点不再有存在资源压力为止才会清除污点结束驱逐。在节点压力驱逐期间kubelet 将所选 Pod 的 PodPhase 设置为 Failed。这将终止 Pod。通常还会带上一个 tolerationSeconds 它意思是在污点出现后Pod 还可以正常工作多少时间也就是延迟多久再进行驱逐。驱逐信号驱逐信号是特定资源在特定时间点的当前状态。 kubelet 使用驱逐信号通过将信号与驱逐条件进行比较来做出驱逐决定 驱逐条件是节点上应该可用资源的最小量。软驱逐条件软驱逐条件将驱逐条件与管理员所必须指定的宽限期配对。 在超过宽限期之前kubelet 不会驱逐Pod。 如果没有指定的宽限期kubelet 会在启动时返回错误。硬驱逐条件硬驱逐条件没有宽限期。当达到硬驱逐条件时 kubelet 会立即杀死 pod而不会正常终止以回收紧缺的资源驱逐pod时的选择首先考虑资源使用量超过其请求的 BestEffort 或 Burstable Pod。 这些 Pod 会根据它们的优先级以及它们的资源使用级别超过其请求的程度被逐出。指定的宽限期kubelet 会在启动时返回错误。硬驱逐条件硬驱逐条件没有宽限期。当达到硬驱逐条件时 kubelet 会立即杀死 pod而不会正常终止以回收紧缺的资源驱逐pod时的选择首先考虑资源使用量超过其请求的 BestEffort 或 Burstable Pod。 这些 Pod 会根据它们的优先级以及它们的资源使用级别超过其请求的程度被逐出。资源使用量少于请求量的 Guaranteed Pod 和 Burstable Pod 根据其优先级被最后驱逐