启用重调度功能

重调度(Descheduling)通常是指将部署在某个节点上调度不合理的Pod重新调度到另一个节点,适用于集群资源利用不均衡、节点负载过高或有新的调度策略需求等场景。重调度功能有助于维护集群健康、优化资源使用以及提高工作负载的服务质量。本文以节点污点校验插件RemovePodsViolatingNodeTaints为例,介绍如何基于ack-koordinator组件开启重调度功能。

阅读前提示

  • 使用本文前,建议您已参见重调度概述了解重调度的功能介绍、使用场景、工作流程和基本概念。

  • 本文以节点污点校验插件RemovePodsViolatingNodeTaints为例,请参见Kubernetes官方文档了解污点和容忍度的工作原理、驱逐效果(例如NoSchedule)等概念。

  • 如果您是社区Kubernetes Descheduler用户,建议您参见Koordinator Descheduler与Kubernetes Descheduler了解Koordinator Descheduler与Kubernetes Descheduler的差异,并完成组件的迁移。

  • 如果您已经了解基础使用方法,需要了解系统、模板概要、策略插件、驱逐器插件的高级配置参数以实现更精细化的重调度策略,可直接阅读高级配置参数

前提条件

注意事项

  • Koordinator Descheduler只负责驱逐正在运行的Pod,并不负责Pod驱逐后的重建以及调度。Pod被驱逐后的重建由其工作负载对应的Controller实现(例如Deployment、Statfulset),重建后Pod的调度流程仍然调度器负责。

  • 重调度在执行过程中会先驱逐旧Pod,再创建新Pod。请确保您的应用有充足的冗余副本(replicas),避免驱逐时影响应用可用性。

示例说明

本文以开启节点污点校验插件RemovePodsViolatingNodeTaints为例,介绍如何基于ack-koordinator组件开启重调度功能,并实现重调度策略。

RemovePodsViolatingNodeTaints策略默认检查并驱逐违反了节点上effectNoSchedule的污点的Pod。例如,对于一个已经有Pod在运行的节点,当管理员在节点上新增一个污点deschedule=not-allow:NoSchedule后,若节点上的Pod没有配置相应的容忍策略,则Pod就会被该重调度策略驱逐。更多信息,请参见RemovePodsViolatingNodeTaints

RemovePodsViolatingNodeTaints策略支持通过excludedTaints字段定义哪些节点污点不在策略的考虑范围内。如果节点上的任何污点的键(key)或键值对(key=value)与 excludedTaints 列表中的条目匹配,那么策略会自动忽略这些污点。

本示例将该插件对污点的检查配置为:

  • 节点上存在effectNoSchedule的污点属性。

  • NoSchedule的污点属性中,key不等于deschedule,且value不等于not-allow

在符合以上要求的节点上,如果已经完成调度并运行中的Pod未配置相应的容忍策略,则会被重调度器驱逐。

步骤一:安装或修改ack-koordinator组件并开启重调度

您可以参见本小节步骤安装ack-koordinator组件,使用其提供的Koordinator Descheduler重调度器功能。Koordinator Descheduler会以Deployment的形式部署在节点上。

说明

如果您已安装ack-koordinator组件,请确保组件版本为v1.2.0-ack.2及以上。

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 组件管理

  3. 定位ack-koordinator组件,单击右下角的安装,在安装对话框上面勾选开启重调度模块,按页面提示完成组件的配置和安装。

步骤二:开启重调度插件RemovePodsViolatingNodeTaints

  1. 使用如下YAML文件,创建koord-descheduler-config.yaml。

    koord-descheduler-config.yaml是ConfigMap格式的对象,用于启用和配置重调度插件RemovePodsViolatingNodeTaints

    # koord-descheduler-config.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: koord-descheduler-config
      namespace: kube-system
    data:
      koord-descheduler-config: |
        # 以下为Koordinator Descheduler系统配置,请保持不变。
        apiVersion: descheduler/v1alpha2
        kind: DeschedulerConfiguration
        leaderElection:
          resourceLock: leases
          resourceName: koord-descheduler
          resourceNamespace: kube-system
        deschedulingInterval: 120s # 执行周期间隔,120s执行一次重调度插件。
        dryRun: false # 全局只读模式开关,开启后Koordinator Descheduler整体不做任何操作。
        # 以上为系统配置。
    
        profiles:
        - name: koord-descheduler
          plugins:
            deschedule:
              enabled:
                - name: RemovePodsViolatingNodeTaints  # 配置开启节点污点校验插件。        
    
          pluginConfig:             
          - name: RemovePodsViolatingNodeTaints # 节点污点校验插件配置。
            args:        
              excludedTaints: 
              - deschedule=not-allow # 忽略包含key为"deschedule"且value为"not-allow"的污点的节点。
  2. 执行如下命令,部署koord-descheduler-config.yaml,将配置更新到集群中。

    kubectl apply -f koord-descheduler-config.yaml
  3. 执行如下命令,重启重调度器模块Koordinator Descheduler

    kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 0
    # 预期输出
    # deployment.apps/ack-koord-descheduler scaled
    kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 1
    # 预期输出
    # deployment.apps/ack-koord-descheduler scaled

    通过将ack-koord-descheduler的Deployment副本数量设置为0,然后再设置为1,重调度器模块Koordinator Descheduler将重启启动,并在启动后使用最新配置。

步骤三:验证重调度能力

下文以拥有3台节点的集群为例进行说明。

  1. 使用如下YAML文件,创建stress-demo.yaml。

    stress-demo.yaml中定义了一个示例应用程序。

    展开查看YAML示例

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: stress-demo
      namespace: default
      labels:
        app: stress-demo
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: stress-demo
      template:
        metadata:
          name: stress-demo
          labels:
            app: stress-demo
        spec:
          containers:
            - args:
                - '--vm'
                - '2'
                - '--vm-bytes'
                - '1600M'
                - '-c'
                - '2'
                - '--vm-hang'
                - '2'
              command:
                - stress
              image: registry-cn-beijing.ack.aliyuncs.com/acs/stress:v1.0.4
              imagePullPolicy: Always
              name: stress
              resources:
                limits:
                  cpu: '2'
                  memory: 4Gi
                requests:
                  cpu: '2'
                  memory: 4Gi
          restartPolicy: Always
  2. 执行以下命令,部署stress-demo.yaml,创建测试Pod。

    kubectl create -f stress-demo.yaml
  3. 执行如下命令,观察Pod的状态,直至开始运行。

    kubectl get pod -o wide

    预期输出:

    NAME                         READY   STATUS    RESTARTS   AGE    IP              NODE                        NOMINATED NODE   READINESS GATES
    stress-demo-5f6cddf9-9****   1/1     Running   0          10s    192.XX.XX.27   cn-beijing.192.XX.XX.247   <none>           <none>
    stress-demo-5f6cddf9-h****   1/1     Running   0          10s    192.XX.XX.20   cn-beijing.192.XX.XX.249   <none>           <none>
    stress-demo-5f6cddf9-v****   1/1     Running   0          10s    192.XX.XX.32   cn-beijing.192.XX.XX.248   <none>           <none>
  4. 执行如下命令,分别为节点增加污点key=value:NoSchedule

    • 为节点cn-beijing.192.XX.XX.247增加deschedule=not-allow:NoSchedule污点。

      kubectl taint nodes cn-beijing.192.XX.XX.247 deschedule=not-allow:NoSchedule

      预期输出:

      node/cn-beijing.192.XX.XX.247 tainted
    • 为节点cn-beijing.192.XX.XX.248增加deschedule=allow:NoSchedule污点。

      kubectl taint nodes cn-beijing.192.XX.XX.248 deschedule=allow:NoSchedule

      预期输出:

      node/cn-beijing.192.XX.XX.248 tainted
  5. 执行如下命令,观察Pod变化。

    kubectl get pod -o wide -w

    等待重调度器检查节点污点,并执行驱逐迁移操作。

    预期输出:

    NAME                         READY   STATUS              RESTARTS   AGE     IP             NODE                    NOMINATED NODE   READINESS GATES
    stress-demo-5f6cddf9-9****   1/1     Running             0          5m34s   192.XX.XX.27   cn-beijing.192.XX.XX.247   <none>           <none>
    stress-demo-5f6cddf9-h****   1/1     Running             0          5m34s   192.XX.XX.20   cn-beijing.192.XX.XX.249   <none>           <none>
    stress-demo-5f6cddf9-v****   1/1     Running             0          5m34s   192.XX.XX.32   cn-beijing.192.XX.XX.248   <none>           <none>
    stress-demo-5f6cddf9-v****   1/1     Terminating         0          7m58s   192.XX.XX.32   cn-beijing.192.XX.XX.248   <none>           <none>
    stress-demo-5f6cddf9-j****   0/1     ContainerCreating   0          0s      <none>         cn-beijing.192.XX.XX.249   <none>           <none>
    stress-demo-5f6cddf9-j****   1/1     Running             0          2s      192.XX.XX.32   cn-beijing.192.XX.XX.249   <none>           <none>

    预期输出表明:

    • 增加了deschedule=allow:NoSchedule污点的节点cn-beijing.192.XX.XX.248上的Podstress-demo-5f6cddf9-v****被驱逐。

    • 增加了deschedule=not-allow:NoSchedule污点的节点cn-beijing.192.XX.XX.247上的Podstress-demo-5f6cddf9-9****没有被驱逐。

    • 被驱逐的Podstress-demo-5f6cddf9-v****重新调度到没有NoSchedule污点的节点cn-beijing.192.XX.XX.249

  6. 执行如下命令,观察被驱逐Pod的Event。

    kubectl get event | grep stress-demo-5f6cddf9-v****

    预期输出:

    3m24s       Normal    Evicting            podmigrationjob/b0fba65f-7fab-4a99-96a9-c71a3798****   Pod "default/stress-demo-5f6cddf9-v****" evicted from node "cn-beijing.192.XX.XX.248" by the reason "RemovePodsViolatingNodeTaints"
    2m51s       Normal    EvictComplete       podmigrationjob/b0fba65f-7fab-4a99-96a9-c71a3798****   Pod "default/stress-demo-5f6cddf9-v****" has been evicted
    3m24s       Normal    Descheduled         pod/stress-demo-5f6cddf9-v****                         Pod evicted from node "cn-beijing.192.XX.XX.248" by the reason "RemovePodsViolatingNodeTaints"
    3m24s       Normal    Killing             pod/stress-demo-5f6cddf9-v****                         Stopping container stress

    预期输出中显示了Pod的迁移记录,此Pod所在节点cn-beijing.192.XX.XX.248没有容忍污点deschedule=not-allow,导致该Pod被重调度到其他节点。结果符合预期。

高级配置参数

除了上述标准操作之外,您还可以使用ConfigMap对Koordinator Descheduler进行高级配置。

高级配置参数示例

下方YAML展示了Koordinator Descheduler的高级配置参数示例。该配置通过DeschedulerConfigurationAPI修改Koordinator Descheduler的行为,开启了RemovePodsViolatingNodeTaint节点污点校验重调度策略,并使用MigrationController作为Pod的驱逐器。

您可结合后续章节的说明,了解示例配置中各字段的详细含义。

展开查看YAML示例

# koord-descheduler-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: koord-descheduler-config
  namespace: kube-system
data:
  koord-descheduler-config: |
    # 以下为Koordinator Descheduler系统配置,请保持不变。
    apiVersion: descheduler/v1alpha2
    kind: DeschedulerConfiguration
    leaderElection:
      resourceLock: leases
      resourceName: koord-descheduler
      resourceNamespace: kube-system
    dryRun: false # 全局只读模式开关,开启后Koordinator Descheduler整体不做任何操作。  
    deschedulingInterval: 120s # 执行周期间隔,120s执行一次重调度插件。
    nodeSelector: # 全局参与重调度的节点。默认对全部节点进行重调度。
      deschedule: allow # 表示只处理含有key为deschedule,value为allow的节点。
    maxNoOfPodsToEvictPerNode: 10 # 全局生效的单节点最大可驱逐Pod数量限制,默认不限制。
    maxNoOfPodsToEvictPerNamespace: 10 # 全局生效的单命名空间最大可驱逐Pod数量限制,默认不限制。
    # 以上为系统配置。

    # 以下为模板列表。
    profiles: 
    - name: koord-descheduler # 模板名称。
      # 以下为模板概要配置,表示具体启用的插件。
      plugins: 
        deschedule: # deschedule类型策略。默认全部禁用。
          enabled: # enabled表示开启的插件。不在enabled中显式开启的其他插件会被全部禁用。
            - name: RemovePodsViolatingNodeTaints  # 配置开启节点污点校验插件。
        balance: # balance类型策略。默认全部禁用。
          disabled: # disabled表示禁用的插件。
            - name: "*" # *表示全部禁用。
        evict:          
          enabled:
            - name: MigrationController # 驱逐器。默认开启驱逐迁移控制器。
        filter: 
          enabled:
            - name: MigrationController # 驱逐筛选策略。默认使用驱逐迁移控制器的驱逐筛选策略。
      # 以上为模板概要配置。

      # 以下为插件列表,包括策略插件和驱逐器插件。
      pluginConfig: 
      # 以下为策略插件RemovePodsViolatingNodeTaints的配置。
      - name: RemovePodsViolatingNodeTaints
        args:
          excludedTaints:
          - deschedule=not-allow # 忽略包含key为"deschedule"且value为"not-allow"的污点的节点
          - reserved # 忽略包含key为"reserved"的污点的节点
          includePreferNoSchedule: false # 是否考虑effect为PreferNoSchedule的污点。默认只考虑effect为NoSchedule的污点。
          namespaces: # 参与重调度的Namespace,include和exclude是互斥的,只能配置其中一种。
            include: # include表示只处理下面配置的Namespace。
              - "namespace1"
              - "namespace2"
            # exclude: # exclude表示需要排除的Namespace。
            #   - "namespace1"
            #   - "namespace2"
          labelSelector: # 参与重调度的Pod。默认全部Pod参与重调度。
            accelerator: nvidia-tesla-p100 # 表示只处理含有key为accelerator,value为nvidia-tesla-p100的标签的Pod。     
    
      # 以下为驱逐器插件MigrationController的配置。     
      - name: MigrationController # 重调度迁移控制参数。
        args:
          apiVersion: descheduler/v1alpha2
          kind: MigrationControllerArgs  
          evictLocalStoragePods: false # 是否允许配置了HostPath或EmptyDir的Pod参与重调度        
          maxMigratingPerNode: 1 # 每个节点处于迁移状态的Pod的最大数量。
          maxMigratingPerNamespace: 1  # 每个Namespace处于迁移状态的Pod的最大数量。
          maxMigratingPerWorkload: 1 # 每个Workload(例如Deployment)中处于迁移状态的Pod的最大数量。
          maxUnavailablePerWorkload: 2 # 每个Workload(例如Deployment)最大不可用副本数。
          objectLimiters:
            workload: # Workload级别Pod迁移的流量控制。默认为首次驱逐后,5分钟内最多迁移1个副本。
              duration: 5m
              maxMigrating: 1
          evictionPolicy: Eviction # 底层的Pod驱逐方法。默认为调用Eviction API驱逐。       

系统配置

DeschedulerConfiguration中支持对Koordinator Descheduler全局的系统级行为进行配置。

参数

类型

取值

说明

示例值

dryRun

boolean

  • true

  • false(默认值)

只读模式开关,开启后将不会发起Pod迁移。

false

deschedulingInterval

time.Duration

>0s

重调度的执行周期。

120s

nodeSelector

结构体

不涉及

限制重调度器生效的节点。重调度策略只会在Node Selector指定的节点中生效。关于Node Selector的更多信息,请参见Kubernetes labelSelector

nodeSelector:
  deschedule: allow

maxNoOfPodsToEvictPerNode

int

≥0(默认不限制)

限制节点上能够同时驱逐的Pod的最大数量。在驱逐过程中生效。

10

maxNoOfPodsToEvictPerNamespace

int

≥0(默认不限制)

限制命名空间内能够同时驱逐的Pod的最大数量。在驱逐过程中生效。

10

模板概要配置

Koordinator Descheduler使用重调度模板管理重调度策略和Pod驱逐器。在DeschedulerConfigurationprofiles字段中支持定义一个或多个重调度模板。在每个重调度模板中,重调度策略和Pod驱逐器都以插件的形式进行配置。重调度模板中包含以下三部分。

  • name

    string类型。自定义重调度模板的名称。

  • plugins

    配置需要启用或禁用的重调度策略(deschedulebalance)、Pod驱逐插件(evict)以及Pod驱逐前的筛选策略(filter)。支持配置的参数与说明如下所示。

    参数

    类型

    取值

    说明

    示例值

    deschedule

    结构体,数据结构为:

    type PluginList struct {
        Enabled  []Plugin
        Disabled []Plugin
    }
    
    type Plugin struct {
        Name string
    }

    其中,EnabledDisabled均为Plugin结构体类型的列表,分别表示开启和禁用插件。

    默认全部禁用。选择开启的Deschedule类型的重调度策略。

    plugins:
      deschedule: 
        enabled:
          - name: PodLifeTime 
          - name: RemovePodsViolatingNodeTaints  

    RemovePodsViolatingInterPodAntiAffinity

    驱逐违反Pod间反亲和性的Pod。

    RemovePodsViolatingNodeAffinity

    驱逐违反节点亲和性的Pod。

    RemovePodsViolatingNodeTaints

    驱逐违反节点污点的Pod。

    RemovePodsHavingTooManyRestarts

    驱逐重启次数过多的Pod。

    PodLifeTime

    驱逐超出存活时间限制的Pod。

    RemoveFailedPod

    驱逐状态为Failed的Pod。

    balance

    结构体,数据结构为:

    type PluginList struct {
        Enabled  []Plugin
        Disabled []Plugin
    }
    
    type Plugin struct {
        Name string
    }

    其中,EnabledDisabled均为Plugin结构体类型的列表,分别表示开启和禁用插件。

    默认全部禁用。选择开启的Balance类型的重调度策略。

    plugins:
      balance: 
        enabled:
          - name: RemoveDuplicates 
          - name: LowNodeLoad

    RemoveDuplicates

    应用副本打散

    LowNodeUtilization

    按节点资源分配率进行热点打散。

    HighNodeUtilization

    按节点资源分配率进行负载聚合,即在策略允许的情况下将Pods从资源利用率较低的节点调度或迁移到资源利用率较高的节点。

    RemovePodsViolatingTopologySpreadConstraint

    驱逐违反拓扑分布约束的Pod。

    LowNodeLoad

    按节点资源利用率进行热点打散。

    evict

    结构体,数据结构为:

    type PluginList struct {
        Enabled  []Plugin
        Disabled []Plugin
    }
    
    type Plugin struct {
        Name string
    }

    其中,Enabled和Disabled均为Plugin结构体类型的列表。在Enabled列表中开启插件,在Disabled中禁用插件。

    • MigrationController

    • DefaultEvictor

    选择开启的Pod驱逐器。默认启用MigrationController

    请勿同时开启多个evict插件。

    plugins:
      evict: 
        enabled: 
          - name: MigrationController

    filter

    结构体,数据结构为:

    type PluginList struct {
        Enabled  []Plugin
        Disabled []Plugin
    }
    
    type Plugin struct {
        Name string
    }

    其中,Enabled和Disabled均为Plugin结构体类型的列表。在Enabled列表中开启插件,在Disabled中禁用插件。

    • MigrationController

    • DefaultEvictor

    选择Pod驱逐前的筛选策略。默认启用MigrationController

    请勿同时开启多个filter插件。

    plugins:
      filter: 
        enabled: 
          - name: MigrationController
  • pluginConfig

    配置每个插件的高级参数。以name字段指定所配置的插件名。关于如何在args字段配置插件。请参见策略插件配置驱逐器插件配置

策略插件配置

Koordinator Descheduler支持6种Deschedule策略插件和5种Balance策略插件。其中,热点打散重调度策略插件LowNodeLoad由社区Koordinator提供,请参见使用负载热点打散重调度了解详细配置;其他重调度策略插件由社区Kubernetes Descheduler提供,如下所示。

策略类型

策略功能

策略配置

Deschedule

驱逐违反Pod间反亲和性的Pod

RemovePodsViolatingInterPodAntiAffinity

驱逐违反节点亲和性的Pod

RemovePodsViolatingNodeAffinity

驱逐违反节点污点的Pod

RemovePodsViolatingNodeTaints

驱逐重启次数过多的Pod

RemovePodsHavingTooManyRestarts

驱逐超出存活时间限制的Pod

PodLifeTime

驱逐状态为Failed的Pod

RemoveFailedPod

Balance

应用副本打散

RemoveDuplicates

按节点资源分配率进行热点打散

LowNodeUtilization

按节点资源分配率进行负载聚合

HighNodeUtilization

驱逐违反拓扑分布约束的Pod

RemovePodsViolatingTopologySpreadConstraint

驱逐器插件配置

Koordinator Descheduler支持DefaultEvictorMigrationController两种驱逐器插件。

MigrationController

MigrationController驱逐器插件的高级配置参数如下所示。

参数

类型

取值

说明

示例值

evictLocalStoragePods

boolean

  • true

  • false(默认值)

是否允许配置了HostPath或EmptyDir的Pod参与重调度。出于安全性考量,默认不开启。

false

maxMigratingPerNode

int64

≥0(默认值为2)

每个节点处于迁移状态的Pod的最大数量。0表示不限制。

2

maxMigratingPerNamespace

int64

≥0(默认不限制)

每个命名空间处于迁移状态的Pod的最大数量。0表示不限制。

1

maxMigratingPerWorkload

intOrString

≥0(默认值为10%)

每个工作负载(例如Deployment)中处于迁移状态的Pod的最大数量或百分比。0表示不限制。

若工作负载只有单副本,则不参与重调度。

1或10%

maxUnavailablePerWorkload

intOrString

≥0(默认值为10%),且小于工作负载对应的副本总数

每个工作负载(例如Deployment)最大不可用副本数或百分比。0表示不限制。

1或10%

objectLimiters.workload

结构体,数据格式为:

type MigrationObjectLimiter struct {
    Duration time.Duration `json:"duration,omitempty"`
    MaxMigrating *intstr.IntOrString `json:"maxMigrating,omitempty"`
}
  • Duration的值大于0秒(默认值5m)

  • MaxMigrating的值≥0(默认值为10%)

工作负载级别Pod迁移的流量控制。

  • Duration:时间窗口长度,例如5m表示5分钟。

  • MaxMigrating:副本数量或百分比,可设置为整数或百分比(默认值取自maxMigratingPerWorkload的值)。

objectLimiters:
  workload:
    duration: 5m
    maxMigrating: 1

表示5分钟内单个工作负载内最多迁移1个副本。

evictionPolicy

string

目前支持三种模式:

  • Eviction(默认值)

  • Delete

  • Soft

  • Eviction:调用Eviction API,优雅地迁移Pod。

  • Delete:调用Pod的Delete方法,直接删除Pod。

  • Soft:只对Pod添加Annotation scheduling.koordinator.sh/soft-eviction。您可以根据该Annotation接管Pod后续的驱逐操作。

Eviction

DefaultEvictor

DefaultEvictor插件由社区Kubernetes Descheduler提供,请参见DefaultEvictor了解详细配置。

差异对比

DefaultEvictor与MigrationController在Pod驱逐能力方面的详细对比如下所示。

对比项

DefaultEvictor

MigrationController

驱逐方法

调用Eviction API驱逐Pod。

支持多种驱逐方法,请参见驱逐器插件配置

驱逐限额

  • 支持限制每个节点处于迁移状态的Pod的最大数量。

  • 支持限制每个命名空间处于迁移状态的Pod的最大数量。

  • 支持限制每个节点处于迁移状态的Pod的最大数量。

  • 支持限制每个命名空间处于迁移状态的Pod的最大数量。

  • 支持限制每个工作负载中处于迁移状态的Pod的最大数量。

  • 支持限制每个工作负载中最大不可用副本数或百分比。

驱逐限流

不支持

支持基于时间窗口的流控机制,保证同一工作负载中Pod的迁移不会过于频繁。

驱逐观测

支持通过组件日志观测Pod驱逐信息。

  • 支持通过组件日志观测Pod驱逐信息。

  • 支持通过Event观测重调度的迁移过程,并在详细信息中查看迁移的具体原因和当前状态。

相关文档