更新时间:2024-07-20 GMT+08:00
分享

设置工作负载亲和/反亲和调度

工作负载亲和/反亲和调度是Kubernetes提供的任务调度方式,可以使用工作负载作为亲和对象,灵活地将新建的工作负载调度到与其相关或无关的节点上,可以有效地提高集群的性能和利用率。

例如,通信频繁的前端Pod和后端Pod可优先调度到同一个节点或同一个可用区,减少网络延迟。工作负载亲和/反亲和的示意如下:

  1. 首先,拓扑域(topologyKey)通过节点的标签和标签值划分节点范围,将节点分为不同的拓扑域。
  2. 然后,根据工作负载标签名、操作符、标签值确定需要亲和/反亲和的工作负载对象。
  3. 最后,调度器选择目标工作负载所处的拓扑域进行亲和性调度,或者选择不存在目标工作负载的拓扑域进行反亲和性调度。
图1 工作负载亲和/反亲和示意图

通过控制台配置负载亲和/反亲和调度策略

  1. 在创建工作负载时,在“高级设置”中找到“调度策略”。创建工作负载的步骤详情请参见创建工作负载
  2. 选择负载亲和调度的策略类型。

    • 不配置:不设置负载亲和策略。
    • 优先多可用区部署:该策略通过Pod自身反亲和实现,并以可用区作为拓扑域,可优先将工作负载的Pod调度到不同可用区的节点上。
    • 强制多可用区部署:该策略通过Pod自身反亲和实现,并以可用区作为拓扑域,可强制将工作负载的Pod调度到不同可用区的节点上。使用该调度策略时,如果节点数小于实例数或节点资源不足,Pod将无法全部运行。
    • 自定义亲和策略:根据Pod标签实现灵活的调度策略,支持的调度策略类型请参见表1。选择合适的策略类型后,单击添加调度策略,参数详情请参见表2
      表1 负载亲和策略类型

      策略

      规则类型

      说明

      工作负载亲和性

      必须满足

      即硬约束,设置必须满足的条件,对应YAML定义中的requiredDuringSchedulingIgnoredDuringExecution字段。

      通过标签筛选需要亲和的Pod,如果满足筛选条件的Pod已经运行在拓扑域中的某个节点上,调度器会将本次创建的Pod强制调度到该拓扑域。

      说明:

      添加多条亲和性规则时,即设置多个标签筛选需要亲和的Pod,则本次创建的Pod必须要同时亲和所有满足标签筛选的Pod,即所有满足标签筛选的Pod要处于同一拓扑域中才可以调度。

      尽量满足

      即软约束,设置尽量满足的条件,对应YAML定义中的preferredDuringSchedulingIgnoredDuringExecution字段。

      通过标签筛选需要亲和的Pod,如果满足筛选条件的Pod已经运行在拓扑域中的某个节点上,调度器会将本次创建的Pod优先调度到该拓扑域。

      说明:

      添加多条亲和性规则时,即设置多个标签筛选需要亲和的Pod,则本次创建的Pod会尽量同时亲和多个满足标签筛选的Pod。但即使所有Pod都不满足标签筛选条件,也会选择一个拓扑域进行调度。

      工作负载反亲和性

      必须满足

      即硬约束,设置必须满足的条件,对应YAML定义中的requiredDuringSchedulingIgnoredDuringExecution字段。

      通过标签筛选需要反亲和的一个或多个Pod,如果满足筛选条件的Pod已经运行在拓扑域中的某个节点上,调度器不会将本次创建的Pod调度到该拓扑域。

      说明:

      添加多条反亲和性规则时,即设置多个标签筛选需要反亲和的Pod,则本次创建的Pod必须要同时反亲和所有满足标签筛选的Pod,即所有满足标签筛选的Pod所处的拓扑域都不会被调度。

      尽量满足

      即软约束,设置尽量满足的条件,对应YAML定义中的preferredDuringSchedulingIgnoredDuringExecution字段。

      通过标签筛选需要反亲和的一个或多个Pod,如果满足筛选条件的Pod已经运行在拓扑域中的某个节点上,调度器会将本次创建的Pod优先调度到其他拓扑域。

      说明:

      添加多条反亲和性规则时,即设置多个标签筛选需要反亲和的Pod,则本次创建的Pod会尽量同时反亲和多个满足标签筛选的Pod。但即使每个拓扑域都存在需要反亲和的Pod,也会选择一个拓扑域进行调度。

      表2 负载亲和/反亲和调度策略设置参数说明

      参数名

      参数描述

      权重

      仅支持在“尽量满足”策略中添加。权重的取值范围为1-100,调度器在进行调度时会将该权重视为一个附加的评分项,并将其与节点的其他优先级函数评分相加。最终,调度器会将Pod调度到总分最大的节点上。

      命名空间

      指定调度策略生效的命名空间。

      拓扑域

      拓扑域(topologyKey)通过节点的标签和标签值先圈定调度的节点范围,然后再通过标签名、操作符、标签值确定亲和/反亲和的对象,最后根据目标对象所处的拓扑域进行调度。

      • 如果标签指定为kubernetes.io/hostname,此时标签值为节点名称,则将不同名称的节点划分为不同的拓扑域,由于节点名称不可重复,此时一个拓扑域中仅包含一个节点,因此可以实现单个节点级别的负载亲和性调度。
      • 如果指定标签为kubernetes.io/os,此时标签值为节点的操作系统类型,则将不同操作系统的节点划分为不同的拓扑域,此时一个拓扑域中可能包含多个节点,因此可以将多个节点作为一个整体进行负载亲和性调度。

        例如,某个拓扑域中的一个节点上运行着满足负载亲和性规则的Pod,则该拓扑域中的节点均可以被调度。

      标签名

      设置工作负载亲和/反亲和性时,填写需要匹配的工作负载标签。

      该标签可以使用系统默认的标签,也可以使用自定义标签。

      操作符

      可以设置四种匹配关系(In、NotIn、Exists、DoesNotExist)。

      • In:亲和/反亲和对象的标签在标签值列表(values字段)中。
      • NotIn:亲和/反亲和对象的标签不在标签值列表(values字段)中。
      • Exists:亲和/反亲和对象存在指定标签名。
      • DoesNotExist:亲和/反亲和对象不存在指定标签名。

      标签值

      设置工作负载亲和/反亲和性时,填写工作负载标签对应的标签值。

  3. 调度策略添加完成后,单击“创建工作负载”。

通过YAML配置负载亲和/反亲和调度策略

  • 工作负载亲和性

    Kubernetes支持Pod和Pod之间的亲和,例如将应用的前端和后端部署在一起,从而减少访问延迟。

    假设有个应用的后端已经创建,且带有app=backend的标签。您可以使用.spec.affinity.podAffinity字段来设置工作负载亲和性,将前端Pod(标签为app=frontend)和后端Pod(标签为app=backend)部署在一起。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      labels:
        app: frontend
    spec:
      selector:
        matchLabels:
          app: frontend
      replicas: 3
      template:
        metadata:
          labels:
            app: frontend
        spec:
          containers:
          - image: nginx:alpine
            name: frontend
            resources:
              requests:
                cpu: 100m
                memory: 200Mi
              limits:
                cpu: 100m
                memory: 200Mi
          imagePullSecrets:
          - name: default-secret
          affinity:  # 设置调度策略
            podAffinity:  # 工作负载亲和性调度规则
              requiredDuringSchedulingIgnoredDuringExecution:   # 表示必须满足的调度策略
              - topologyKey: prefer    # 根据节点标签划分拓扑域,示例中prefer为自定义标签
                labelSelector:  # 根据工作负载标签选择满足条件的工作负载
                  matchExpressions: # 工作负载标签匹配规则
                  - key: app # 工作负载标签的键为app
                    operator: In # 表示存在values列表中的值即满足规则
                    values: # 工作负载标签的值列表
                    - backend
              preferredDuringSchedulingIgnoredDuringExecution:    # 表示尽量满足的调度策略
              - weight: 100  # 使用尽量满足策略时可设置优先级,取值为1-100,数值越大优先级越高
                podAffinityTerm:  # 使用尽量满足策略时的亲和项
                  topologyKey: topology.kubernetes.io/zone   # 根据节点标签划分拓扑域,以节点的可用区为粒度
                  labelSelector:
                    matchExpressions:
                    - key: app
                      operator: In
                      values:
                      - backend

    上述示例中的工作负载调度时,必须满足规则会根据prefer标签划分节点拓扑域,如果当拓扑域中某个节点运行着后端Pod(标签为app=backend),即使该拓扑域中并非所有节点均运行了后端Pod,前端Pod(标签为app=frontend)同样会部署在此拓扑域中。而尽量满足规则根据topology.kubernetes.io/zone划分拓扑域,以节点的可用区为粒度进行调度,表示尽量将前后端部署至同一可用区的节点。

    对于工作负载亲和来说,使用requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution规则时, topologyKey字段不允许为空。

    topologyKey字段用于划分拓扑域,当节点上存在topologyKey字段指定的标签,且键、值均相同时,这些节点会被认为属于同一拓扑域,然后调度器会根据工作负载的标签选择需要调度的拓扑域。一个拓扑域中可能包含多个节点,当拓扑域中的一个节点上运行了满足标签选择规则的工作负载时,则该拓扑域中的节点均可以被调度。

    例如,当topologyKey的标签为topology.kubernetes.io/zone时,表示以节点的可用区作为拓扑域,工作负载在部署时会以可用区为粒度进行调度。

  • 工作负载反亲和性

    在某些情况下,需要将Pod分开部署,例如Pod之间部署在一起会影响性能的情况。

    假设有个应用的前端已经创建,且带有app=frontend的标签。您可以使用.spec.affinity.podAntiAffinity字段来设置工作负载反亲和性,将各个Pod部署在不同的节点,且优先多可用区。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name:   frontend
      labels:
        app:  frontend
    spec:
      selector:
        matchLabels:
          app: frontend
      replicas: 5
      template:
        metadata:
          labels:
            app:  frontend
        spec:
          containers:
          - image:  nginx:alpine
            name:  frontend
            resources:
              requests:
                cpu:  100m
                memory:  200Mi
              limits:
                cpu:  100m
                memory:  200Mi
          imagePullSecrets:
          - name: default-secret
          affinity:
            podAntiAffinity:  # 工作负载反亲和性调度规则
              requiredDuringSchedulingIgnoredDuringExecution:   # 表示必须满足的调度策略
              - topologyKey: kubernetes.io/hostname    # 根据节点标签划分拓扑域
                labelSelector:    # Pod标签匹配规则
                  matchExpressions:  # 工作负载标签的键为app
                  - key: app  # 工作负载标签的键为app
                    operator: In  # 表示存在values列表中的值即满足规则
                    values:  # 工作负载标签的值列表
                    - frontend
              preferredDuringSchedulingIgnoredDuringExecution:    # 表示尽量满足的调度策略
              - weight: 100  # 使用尽量满足策略时可设置优先级,取值为1-100,数值越大优先级越高
                podAffinityTerm:  # 使用尽量满足策略时的亲和项
                  topologyKey: topology.kubernetes.io/zone   # 根据节点标签划分拓扑域
                  labelSelector:
                    matchExpressions:
                    - key: app
                      operator: In
                      values:
                      - frontend

    以上示例中定义了反亲和规则,必须满足的规则表示根据kubernetes.io/hostname标签划分节点拓扑域。由于拥有kubernetes.io/hostname标签的节点中,每个节点的标签值均不同,因此一个拓扑域中只有一个节点。当一个拓扑域中(此处为一个节点)已经存在frontend标签的Pod时,该拓扑域不会被继续调度具有相同标签的Pod。而尽量满足规则根据topology.kubernetes.io/zone划分拓扑域,以节点的可用区为粒度进行调度,表示尽量将Pod分布至不同可用区的节点。

    对于工作负载反亲和来说,使用requiredDuringSchedulingIgnoredDuringExecution规则时, Kubernetes默认的准入控制器 LimitPodHardAntiAffinityTopology要求topologyKey字段只能是kubernetes.io/hostname。如果您希望使用其他定制拓扑逻辑,可以更改或者禁用该准入控制器。

分享:

    相关文档

    相关产品