kubernetes-POD调度

POD选择节点

将POD运行在指定的节点上,方式有:

        nodeSelector

        亲和性和反亲和性:nodeAffinity、podAffinity

        nodeName

nodeSelector

        nodeSelector是PodSpec的一个字段,是包含键值对的映射。为了使Pod在节点上运行,节点的标签必须包含PodSpec中nodeSelector中的键值对。节点的标签可以与nodeSelector中的键值对一样,也可以多于nodeSelector描述的键值对。

亲和性和反亲和性

nodeSelector提供了以重非常简单的方法将Pod约束到特定标签的节点上。而亲和性/反亲和性极大地扩展了可以表达约束的类型。包括:

        1.语言更具表现力(不仅仅是“对完全匹配规则的AND”)

        2.可以使规则是“软需求”/“偏好”,而不是影星要求。因此,如果调度器无法满足该要求,仍然调度该Pod

        3.可以使用节点上存在的Pod的标签来进行约束,而不是使用节点本身的标签进行约束。来约束哪些Pod可以或者不可以被放置在同一节点。

nodeAffinity

节点亲和性/反亲和性

节点亲和性概念类似于nodeSelector,它可以根据节点上的标签来约束Pod可以调度到哪些节点。

目前有两种类型的节点亲和性:

        requireDuringSchedulingIgnoreDuringExecution(在调度过程中要求存在,在执行过程中忽略),可是视作为“硬需求”。

        preferredDuringSchedulingIgnoreDuringExecution(在调度过程中作为首选,在执行过程中忽略),可是视作为“软需求”。

requireDuringScheduling。调度期间,将Pod调度到一个节点上时,必须满足规则。

preferredDuringScheduling。调度期间,将定义的规则视为首选(偏好),如果不满足也不影响调度。

IgnoreDuringExecution。如果Pod在执行期间(Pod已经在节点上运行),而此时节点的标签发生变更,变得不满足Pod的亲和性规则。那么节点继续在节点上运行。

节点亲和性通过 PodSpec 的 affinity 字段下的 nodeAffinity 字段进行指定

Example

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: k8s.gcr.io/pause:2.0

此节点亲和性规则表示,Pod只能放置在具有标签键kubernetes.io/e2e-az-name,值为e2e-az1或e2e-az2的节点上。另外在满足这些标准的节点中,具有标签为another-node-label-key,标签值为another-node-label-value的节点应该优先使用。

操作符

新的节点亲和性语法支持以下操作符:In、NotIn、Exists、DoesNotExist、Gt、Lt

可以使用NotIn、DoesNotExist来实现节点反亲和性。或者使用节点污点将Pod从特定节点中驱逐。

匹配逻辑

1.如果同时制定了nodeSelector和nodeAffinity。则两者都必须满足,才能将Pod调度到候选节点上。

2.如果指定了多个与nodeAffinity关联的nodeSelectorTerms。则如果其中一个nodeSelectorTerms满足的话,Pod将可以调度到节点上。

3.如果指定了多个与nodeSelectorTerms关联的matchExpressions,则只有当所有matchExpressions满足的话,Pod才可以调度到节点上。

4.如果修改或删除了Pod所在节点的标签,在运行中的Pod不会被删除。这与上文提到的,节点亲和性类型中的"IgnoreDuringExecution"解释一致。

preferredDuringSchedulingIgnoredDuringExecution 中的 weight 字段值的 范围是 1-100。 对于每个符合所有调度要求(资源请求、RequiredDuringScheduling 亲和性表达式等) 的节点,调度器将遍历该字段的元素来计算总和,并且如果节点匹配对应的 MatchExpressions,则添加“权重”到总和。 然后将这个评分与该节点的其他优先级函数的评分进行组合。 总分最高的节点是最优选的。

podAffinity

Pod亲和性/反亲和性

Pod 间亲和性与反亲和性使你可以 基于已经在节点上运行的 Pod 的标签 来约束 Pod 可以调度到的节点,而不是基于节点上的标签。与节点不同,因为 Pod 是命名空间限定的(因此 Pod 上的标签也是命名空间限定的), 因此作用于 Pod 标签的标签选择算符必须指定选择算符应用在哪个命名空间。

注意1:Pod 间亲和性与反亲和性需要大量的处理,这可能会显著减慢大规模集群中的调度。 不建议在超过数百个节点的集群中使用

注意2:Pod 反亲和性需要对节点进行一致的标记,即集群中的每个节点必须具有适当的标签能够匹配 topologyKey。如果某些或所有节点缺少指定的 topologyKey 标签,可能会导致意外行为。

与节点亲和性一样,当前有两种类型的 Pod 亲和性与反亲和性,即 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,分别表示“硬性”与“软性”要求。

Pod 间亲和性通过 PodSpec 中 affinity 字段下的 podAffinity 字段进行指定。 而 Pod 间反亲和性通过 PodSpec 中 affinity 字段下的 podAntiAffinity 字段进行指定。

Example

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: k8s.gcr.io/pause:2.0

在这个 Pod 的亲和性配置定义了一条 Pod 亲和性规则和一条 Pod 反亲和性规则。 

Pod 亲和性规则表示,仅当节点和至少一个已运行且有键为“security”且值为“S1”的标签 的 Pod 处于同一区域时,才可以将该 Pod 调度到节点上。 (更确切的说,如果节点 N 具有带有键 topology.kubernetes.io/zone 和某个值 V 的标签, 则 Pod 有资格在节点 N 上运行,以便集群中至少有一个节点具有键 topology.kubernetes.io/zone 和值为 V 的节点正在运行具有键“security”和值 “S1”的标签的 pod。)

Pod 反亲和性规则表示,如果节点处于 Pod 所在的同一可用区且具有键“security”和值“S2”的标签, 则该 pod 不应将其调度到该节点上。 (如果 topologyKey 为 topology.kubernetes.io/zone,则意味着当节点和具有键 “security”和值“S2”的标签的 Pod 处于相同的区域,Pod 不能被调度到该节点上。)

操作符

Pod 亲和性与反亲和性的合法操作符有 InNotInExistsDoesNotExist

topologyKey 限制

原则上,topologyKey 可以是任何合法的标签键。 然而,出于性能和安全原因,topologyKey 受到一些限制:

        1.对于 Pod 亲和性而言,在 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey 不允许为空。

        2.对于 Pod 反亲和性而言,requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey 也都不可以为空。

        3.对于 requiredDuringSchedulingIgnoredDuringExecution 要求的 Pod 反亲和性, 引入准入控制器 LimitPodHardAntiAffinityTopology ,确保 topologyKey 只能是 kubernetes.io/hostname。如果你希望 topologyKey 也可用于其他自定义的拓扑逻辑,你可以更改或禁用准入控制器。

        4.除上述情况外,topologyKey 可以是任何合法的标签键。

除了 labelSelector 和 topologyKey,你也可以指定表示命名空间的 namespaces 队列,labelSelector 也应该匹配它 (这个与 labelSelector 和 topologyKey 的定义位于相同的级别)。 如果忽略或者为空,则namespace默认为出现亲和/反反亲和定义的pod的名称空间。

所有与 requiredDuringSchedulingIgnoredDuringExecution 亲和性与反亲和性 关联的 matchExpressions 必须满足,才能将 pod 调度到节点上。

nodeName

nodeName 是节点选择约束的最简单方法,但是由于其自身限制,通常不使用它。 nodeName 是 PodSpec 的一个字段。 如果它不为空,调度器将忽略 Pod,并且给定节点上运行的 kubelet 进程尝试执行该 Pod。 因此,如果 nodeName 在 PodSpec 中指定了,则它优先于上面的节点选择方法。

使用 nodeName 来选择节点的一些限制:

        如果指定的节点不存在;

        如果指定的节点没有资源来容纳 Pod,Pod 将会调度失败并且其原因将显示为, 比如 OutOfmemory 或 OutOfcpu;

        云环境中的节点名称并非总是可预测或稳定的。

Example

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: kube-01

污点和容忍度

节点亲和性 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点 (这可能出于一种偏好,也可能是硬性要求)。 污点(Taint)则相反——它使节点能够排斥一类特定的 Pod。

容忍度(Toleration)是应用于 Pod 上的,允许(但并不要求)Pod 调度到带有与之匹配的污点的节点上。

污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod,是不会被该节点接受的。

概念

可以使用kubectl taint给节点新增或者删除污点:

节点新增污点:给节点 node1 增加一个污点,它的键名是 key1,键值是 value1,效果是 NoSchedule。 这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到 node1 这个节点。

kubectl taint nodes node1 key1=value1:NoSchedule

节点删除污点:

kubectl taint nodes node1 key1=value1:NoSchedule-

污点类型:

        NoSchedule:新的 Pod 不调度到该 Node 上,不影响正在运行的

        PodPreferNoSchedule:soft 版的 NoSchedule,尽量不调度到该 Node 上

        NoExecute:新的 Pod 不调度到该 Node 上,并且删除(evict)已在运行的 Pod。Pod 可以增加一个时间(tolerationSeconds)

可以在PodSpec中定义Pod的容忍度。

Example

以下两个例子都可以容忍上述新增的节点污点,使pod调度到node1上。

##key1值等于value1,且效果是不调度
tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"

##存在标签key1,且效果是不调度
tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoSchedule"

operator 的默认值是 Equal。

一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:

        如果 operator 是 Exists (此时容忍度不能指定 value),或者
        如果 operator 是 Equal ,则它们的 value 应该相等

说明两种特殊情况:

        1.key为空,operator为Exists。表示key、value可以是任意值;

        2.如果effect为空,表示效果可以是NoSchedule、PodPreferNoSchedule、NoExecute中任意一个。

多污点和多容忍度

您可以给一个节点添加多个污点,也可以给一个 Pod 添加多个容忍度设置。 Kubernetes 处理多个污点和容忍度的过程就像一个过滤器:从一个节点的所有污点开始遍历, 过滤掉那些 Pod 中存在与之相匹配的容忍度的污点。余下未被过滤的污点的 effect 值决定了 Pod 是否会被分配到该节点,特别是以下情况:

  • 如果未被过滤的污点中存在至少一个 effect 值为 NoSchedule 的污点, 则 Kubernetes 不会将 Pod 分配到该节点。
  • 如果未被过滤的污点中不存在 effect 值为 NoSchedule 的污点, 但是存在 effect 值为 PreferNoSchedule 的污点, 则 Kubernetes 会 尝试 不将 Pod 分配到该节点。
  • 如果未被过滤的污点中存在至少一个 effect 值为 NoExecute 的污点, 则 Kubernetes 不会将 Pod 分配到该节点(如果 Pod 还未在节点上运行), 或者将 Pod 从该节点驱逐(如果 Pod 已经在节点上运行)。

使用场景

通过污点和容忍度,可以灵活地让 Pod 避开 某些节点或者将 Pod 从某些节点驱逐。下面是几个使用例子:

  • 专用节点:如果您想将某些节点专门分配给特定的一组用户使用,您可以给这些节点添加一个污点(即, kubectl taint nodes nodename dedicated=groupName:NoSchedule), 然后给这组用户的 Pod 添加一个相对应的 toleration(通过编写一个自定义的 准入控制器,很容易就能做到)。 拥有上述容忍度的 Pod 就能够被分配到上述专用节点,同时也能够被分配到集群中的其它节点。 如果您希望这些 Pod 只能被分配到上述专用节点,那么您还需要给这些专用节点另外添加一个和上述 污点类似的 label (例如:dedicated=groupName),同时 还要在上述准入控制器中给 Pod 增加节点亲和性要求上述 Pod 只能被分配到添加了 dedicated=groupName 标签的节点上。
  • 配备了特殊硬件的节点:在部分节点配备了特殊硬件(比如 GPU)的集群中, 我们希望不需要这类硬件的 Pod 不要被分配到这些特殊节点,以便为后继需要这类硬件的 Pod 保留资源。 要达到这个目的,可以先给配备了特殊硬件的节点添加 taint (例如 kubectl taint nodes nodename special=true:NoSchedule 或 kubectl taint nodes nodename special=true:PreferNoSchedule), 然后给使用了这类特殊硬件的 Pod 添加一个相匹配的 toleration。 和专用节点的例子类似,添加这个容忍度的最简单的方法是使用自定义 准入控制器。
  • 基于污点的驱逐: 这是在每个 Pod 中配置的在节点出现问题时的驱逐行为。

基于污点的驱逐

前文提到过污点的 effect 值 NoExecute会影响已经在节点上运行的 Pod

  • 如果 Pod 不能忍受 effect 值为 NoExecute 的污点,那么 Pod 将马上被驱逐
  • 如果 Pod 能够忍受 effect 值为 NoExecute 的污点,但是在容忍度定义中没有指定 tolerationSeconds,则 Pod 还会一直在这个节点上运行。
  • 如果 Pod 能够忍受 effect 值为 NoExecute 的污点,而且指定了 tolerationSeconds, 则 Pod 还能在这个节点上继续运行这个指定的时间长度。

当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括:

  • node.kubernetes.io/not-ready:节点未准备好。这相当于节点状态 Ready 的值为 "False"。
  • node.kubernetes.io/unreachable:节点控制器访问不到节点. 这相当于节点状态 Ready 的值为 "Unknown"。
  • 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/uninitialized:如果 kubelet 启动时指定了一个 "外部" 云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点。

使用这个功能特性,结合 tolerationSeconds,Pod 就可以指定当节点出现一个 或全部上述问题时还将在这个节点上运行多长的时间。

Example

tolerations:
- key: "node.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 6000

说明:

Kubernetes 会自动给 Pod 添加一个 key 为 node.kubernetes.io/not-ready 的容忍度 并配置 tolerationSeconds=300,除非用户提供的 Pod 配置中已经已存在了 key 为 node.kubernetes.io/not-ready 的容忍度。

Kubernetes 会给 Pod 添加一个 key 为 node.kubernetes.io/unreachable 的容忍度 并配置 tolerationSeconds=300,除非用户提供的 Pod 配置中已经已存在了 key 为 node.kubernetes.io/unreachable 的容忍度。

DaemonSet 中的 Pod 被创建时, 针对以下污点自动添加的 NoExecute 的容忍度将不会指定 tolerationSeconds,以防 DaemonSet 崩溃:

  • node.kubernetes.io/memory-pressure
  • node.kubernetes.io/disk-pressure
  • node.kubernetes.io/pid-pressure (1.14 或更高版本)
  • node.kubernetes.io/unschedulable (1.10 或更高版本)
  • node.kubernetes.io/network-unavailable (只适合主机网络配置)

优先级和抢占

Pod 可以有 优先级。 优先级表示一个 Pod 相对于其他 Pod 的重要性。 如果一个 Pod 无法被调度,调度程序会尝试抢占(驱逐)较低优先级的 Pod, 以使悬决 Pod 可以被调度。

如何使用优先级和抢占:

        1.新增一个或多个 PriorityClass。

        2.创建 Pod,并将其 priorityClassName 设置为新增的 PriorityClass。

Kubernetes 已经提供了 2 个 PriorityClass: system-cluster-critical 和 system-node-critical。 这些是常见的类,用于确保始终优先调度关键组件。

PriorityClass

PriorityClass 是一个无名称空间对象,它定义了从优先级类名称到优先级整数值的映射。 名称在 PriorityClass 对象元数据的 name 字段中指定。 值在必填的 value 字段中指定。值越大,优先级越高。 PriorityClass 对象的名称必须是有效的 DNS 子域名, 并且它不能以 system- 为前缀。

PriorityClass 对象可以设置任何小于或等于 10 亿的 32 位整数值。 较大的数字是为通常不应被抢占或驱逐的关键的系统 Pod 所保留的。 集群管理员应该为这类映射分别创建独立的 PriorityClass 对象。

PriorityClass 还有两个可选字段:globalDefault 和 description

globalDefault 字段表示这个 PriorityClass 的值应该用于没有 priorityClassName 的 Pod。 系统中只能存在一个 globalDefault 设置为 true 的 PriorityClass。 如果不存在设置了 globalDefault 的 PriorityClass, 则没有 priorityClassName 的 Pod 的优先级为零。

description 字段是一个任意字符串。 它用来告诉集群用户何时应该使用此 PriorityClass。

Example

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false
description: "此优先级类应仅用于 XYZ 服务 Pod。"

关于 PodPriority 和现有集群的注意事项

  • 如果你升级一个已经存在的但尚未使用此特性的集群,该集群中已经存在的 Pod 的优先级等效于零。
  • 添加一个将 globalDefault 设置为 true 的 PriorityClass 不会改变现有 Pod 的优先级。 此类 PriorityClass 的值仅用于添加 PriorityClass 后创建的 Pod。
  • 如果你删除了某个 PriorityClass 对象,则使用被删除的 PriorityClass 名称的现有 Pod 保持不变, 但是你不能再创建使用已删除的 PriorityClass 名称的 Pod。

PodSpec定义PriorityClass

优先级准入控制器使用 priorityClassName 字段并填充优先级的整数值。

Example

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority

非抢占式的PriorityClass

配置了 PreemptionPolicy: Never 的 Pod 将被放置在调度队列中较低优先级 Pod 之前, 但它们不能抢占其他 Pod。等待调度的非抢占式 Pod 将留在调度队列中,直到有足够的可用资源, 它才可以被调度。非抢占式 Pod,像其他 Pod 一样,受调度程序回退的影响。 这意味着如果调度程序尝试这些 Pod 并且无法调度它们,它们将以更低的频率被重试, 从而允许其他优先级较低的 Pod 排在它们之前。

非抢占式 Pod 仍可能被其他高优先级 Pod 抢占。

PreemptionPolicy 默认为 PreemptLowerPriority, 这将允许该 PriorityClass 的 Pod 抢占较低优先级的 Pod(现有默认行为也是如此)。 如果 PreemptionPolicy 设置为 Never,则该 PriorityClass 中的 Pod 将是非抢占式的。

场景:科学计算。数据科学工作负载是一个示例用例。用户可以提交他们希望优先于其他工作负载的作业, 但不希望因为抢占运行中的 Pod 而导致现有工作被丢弃。 设置为 PreemptionPolicy: Never 的高优先级作业将在其他排队的 Pod 之前被调度, 只要足够的集群资源“自然地”变得可用。

Example

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority-nonpreempting
value: 1000000
preemptionPolicy: Never
globalDefault: false
description: "This priority class will not cause other pods to be preempted."

Pod优先级对调度顺序的影响

当启用 Pod 优先级时,调度程序会按优先级对悬决 Pod 进行排序, 并且每个悬决的 Pod 会被放置在调度队列中其他优先级较低的悬决 Pod 之前。 因此,如果满足调度要求,较高优先级的 Pod 可能会比具有较低优先级的 Pod 更早调度。 如果无法调度此类 Pod,调度程序将继续并尝试调度其他较低优先级的 Pod。

抢占

Pod P被创建后会进入队列等待调度。如无法找到满足需求的调度节点,则触发抢占逻辑。抢占逻辑试图找到一个节点,删除节点上一个或多个优先级较低的Pod,这些Pod被驱逐释放资源后,Pod P则被调度到节点上。

当Pod P抢占N节点上一个或多个Pod时,Pod P状态的nominatedNodeName字段会被设置程节点N的名称。

但是如果在节点N释放出足够的资源给Pod P之前,有其他节点有足够的节点调度Pod P的话,那么Pod P会被调度到其他节点上。但是Pod P的nominatedNodeName字段不会发生变化。

此外,如果调度程序抢占节点 N 上的 Pod,但随后比 Pod P 更高优先级的 Pod 到达, 则调度程序可能会将节点 N 分配给新的更高优先级的 Pod。 在这种情况下,调度程序会清除 Pod P 的 nominatedNodeName。 通过这样做,调度程序使 Pod P 有资格抢占另一个节点上的 Pod。

抢占的限制

被抢占牺牲者体面终止

当 Pod 被抢占时,牺牲者会得到他们的 体面终止期。 它们可以在体面终止期内完成工作并退出。如果它们不这样做就会被杀死。 这个体面终止期在调度程序抢占 Pod 的时间点和待处理的 Pod (P) 可以在节点 (N) 上调度的时间点之间划分出了一个时间跨度。 同时,调度器会继续调度其他待处理的 Pod。当牺牲者退出或被终止时, 调度程序会尝试在待处理队列中调度 Pod。 因此,调度器抢占牺牲者的时间点与 Pod P 被调度的时间点之间通常存在时间间隔。 为了最小化这个差距,可以将低优先级 Pod 的体面终止时间设置为零或一个小数字。

支持 PodDisruptionBudget,但不保证

PodDisruptionBudget (PDB) 允许多副本应用程序的所有者限制因自愿性质的干扰而同时终止的 Pod 数量。 Kubernetes 在抢占 Pod 时支持 PDB,但对 PDB 的支持是基于尽力而为原则的。 调度器会尝试寻找不会因被抢占而违反 PDB 的牺牲者,但如果没有找到这样的牺牲者, 抢占仍然会发生,并且即使违反了 PDB 约束也会删除优先级较低的 Pod。

与低优先级 Pod 之间的 Pod 间亲和性

如果悬决 Pod 与节点上的一个或多个较低优先级 Pod 具有 Pod 间亲和性, 则在没有这些较低优先级 Pod 的情况下,无法满足 Pod 间亲和性规则。 在这种情况下,调度程序不会抢占节点上的任何 Pod。 相反,它寻找另一个节点。调度程序可能会找到合适的节点, 也可能不会。无法保证悬决 Pod 可以被调度。

不能跨界点抢占

假设正在考虑在一个节点 N 上执行抢占,以便可以在 N 上调度待处理的 Pod P。(反亲和性) 只有当另一个节点上的 Pod Q被抢占时,P 才可能在 N 上变得可行。

调度器不会进行跨界点抢占。因此,此情况下不会进行调度。节点N视为不满足调度需求。

Pod的抢占会造成一些低优先级的Pod被不必要的抢占,所以个人觉得慎用。

多调度器

在配置多个调度方案时, 你可以将某个方案与节点亲和性关联起来,如果某个调度方案仅适用于某组 特殊的节点时,这样做是很有用的。 要实现这点,可以在调度器配置中为 NodeAffinity 插件 添加 addedAffinity 参数。 例如:

apiVersion: kubescheduler.config.k8s.io/v1beta1
kind: KubeSchedulerConfiguration

profiles:
  - schedulerName: default-scheduler
  - schedulerName: foo-scheduler
    pluginConfig:
      - name: NodeAffinity
        args:
          addedAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
              nodeSelectorTerms:
              - matchExpressions:
                - key: scheduler-profile
                  operator: In
                  values:
                  - foo

这里的 addedAffinity 除遵从 Pod 规约中设置的节点亲和性。通过 podSpec.schedulerName 来选择使用哪一个调度器(默认使用内置的调度器)。

注意:DaemonSet 控制器为 DaemonSet 创建 Pods, 但该控制器不理会调度方案。因此,建议你保留一个调度方案,例如 default-scheduler,不要在其中设置 addedAffinity。 这样,DaemonSet 的 Pod 模板将会使用此调度器名称。 否则,DaemonSet 控制器所创建的某些 Pods 可能持续处于不可调度状态。

参考文档

https://kubernetes.feisky.xyz/concepts/components/schedulericon-default.png?t=L9C2https://kubernetes.feisky.xyz/concepts/components/scheduler

将 Pod 分配给节点 | Kubernetesicon-default.png?t=L9C2https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/

污点和容忍度 | KubernetesPods that *attracts* them to a set of nodes (either as a preference or a hard requirement). _Taints_ are the opposite -- they allow a node to repel a set of pods. -- 节点亲和性 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点 (这可能出于一种偏好,也可能是硬性要求)。 污点(Taint)则相反——它使节点能够排斥一类特定的 Pod。容忍度(Toleration)是应用于 Pod 上的,允许(但并不要求)Pod 调度到带有与之匹配的污点的节点上。污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod,是不会被该节点接受的。概念 您可以使用命令 kubectl taint 给节点增加一个污点。比如,kubectl taint nodes node1 key1=value1:NoSchedule 给节点 node1 增加一个污点,它的键名是 key1,键值是 value1,效果是 NoSchedule。 这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到 node1 这个节点。https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/Pod 优先级和抢占 | Kubernetesicon-default.png?t=L9C2https://kubernetes.io/zh/docs/concepts/scheduling-eviction/pod-priority-preemption/#%E8%A2%AB%E6%8A%A2%E5%8D%A0%E7%89%BA%E7%89%B2%E8%80%85%E7%9A%84%E4%BD%93%E9%9D%A2%E7%BB%88%E6%AD%A2

你可能感兴趣的:(#,kubernetes,kubernetes,容器,云原生)