为了解决实际运行中集群资源无法充分利用或浪费的问题,可以使用Descheduler组件对集群的Pod进行调度优化,使部分不合理Pod能够重新调度到合适的节点上。本文介绍如何安装和使用Descheduler组件。

前提条件

安装ack-descheduler组件

  1. 登录容器服务管理控制台
  2. 在控制台左侧导航栏中,选择市场 > 应用市场
  3. 应用市场页面单击应用目录页签,选中ack-descheduler应用。
  4. ack-descheduler页面,单击创建
  5. 创建面板中,选择集群和命名空间,然后单击下一步
  6. 参数配置页面,设置相应参数,然后单击确定
    安装完成后,默认会在kube-systemnamespace下部署执行周期为两分钟的Cronjob。创建成功后,会自动跳转到目标集群的ack-descheduler-default页面,检查安装结果。若下图中所有资源创建成功,则说明组件安装成功。ack-descheduler.png

通过ack-descheduler优化Pod调度

  1. 查看配置项(ConfigMap)文件,了解当前的调度策略(DeschedulerPolicy)。
    kubectl describe cm ack-descheduler-default -n kube-system

    预期输出:

    Name:         descheduler
    Namespace:    kube-system
    Labels:       app.kubernetes.io/instance=descheduler
                  app.kubernetes.io/managed-by=Helm
                  app.kuberne
    
    
    tes.io/name=descheduler
                  app.kubernetes.io/version=0.20.0
                  helm.sh/chart=descheduler-0.20.0
    Annotations:  meta.helm.sh/release-name: descheduler
                  meta.helm.sh/release-namespace: kube-system
    Data
    ====
    policy.yaml:
    ----
    apiVersion: "descheduler/v1alpha1"
    kind: "DeschedulerPolicy"
    strategies:
      "RemoveDuplicates":  
         enabled: true
      "RemovePodsViolatingInterPodAntiAffinity": 
         enabled: true
      "LowNodeUtilization": 
         enabled: true
         params:
           nodeResourceUtilizationThresholds:
             thresholds:
               "cpu" : 20
               "memory": 20
               "pods": 20
             targetThresholds:
               "cpu" : 50
               "memory": 50
               "pods": 50
      "RemovePodsHavingTooManyRestarts":
         enabled: true
         params:
           podsHavingTooManyRestarts:
             podRestartThreshold: 100
             includingInitContainers: true
    Events:  <none>

    当前的调度策略如下表所示。关于strategies中策略的更多信息,请参见Descheduler

    策略 描述
    RemoveDuplicates 删除重复的Pod,确保只有一个Pod与同一节点上运行的ReplicaSet、Replication Controller、StatefulSet或者Job关联。
    RemovePodsViolatingInterPodAntiAffinity 此策略可确保从节点中删除违反Pod间反亲和性的Pod。
    LowNodeUtilization 此策略会找到未充分利用的节点,并尽可能从其他节点上驱逐Pod,以便ack-descheduler重新将这些被驱逐的Pod调度到未充分利用的节点上。该策略的参数可以通过nodeResourceUtilizationThresholds字段进行配置。
    RemovePodsHavingTooManyRestarts 此策略可确保从节点中删除重启次数过多的Pod。
  2. 查看调度策略修改前的调度效果。
    1. 部署测试Deployment。
      nginx.yaml的命令示例如下所示。
      apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
      kind: Deployment
      metadata:
        name: nginx-deployment-basic
        labels:
          app: nginx
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx:1.7.9 #替换为实际的容器镜像,格式为:<image_name:tags>。
              ports:
              - containerPort: 80

      执行以下命令,部署Deployment nginx.yaml

      kubectl apply -f nginx.yaml

      预期输出:

      deployment.apps/nginx-deployment-basic created
    2. 等待两分钟后,执行以下命令,查看Pod分布节点。
      kubectl get pod -o wide | grep nginx

      预期输出:

      NAME                          READY   STATUS     RESTARTS   AGE    IP               NODE                         NOMINATED NODE   READINESS GATES
      nginx-deployment-basic-**1    1/1     Running    0          36s    172.25.XXX.XX1   cn-hangzhou.172.16.XXX.XX2   <none>           <none>
      nginx-deployment-basic-**2    1/1     Running    0          11s    172.25.XXX.XX2   cn-hangzhou.172.16.XXX.XX3   <none>           <none>
      nginx-deployment-basic-**3    1/1     Running    0          36s    172.25.XXX.XX3   cn-hangzhou.172.16.XXX.XX3   <none>           <none>

      从以上预期输出可以得出,nginx-deployment-basic-**2nginx-deployment-basic-**3都被调度到cn-hangzhou.172.16.XXX.XX3节点。

      说明 默认ConfigMap配置下的调度结果取决于实际的集群环境,此处的结果为多种情况之一,仅作示例。
  3. 修改调度策略。
    为了防止多个调度策略影响调度效果,修改步骤1中的ConfigMap,只保留RemoveDuplicates策略。
    说明 RemoveDuplicates策略是指尽可能保障有副本控制器的Pod,可以水平分布到不同的节点上。
    修改后的ConfigMap文件命名为newPolicy.yaml,内容示例如下所示。
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: descheduler
      namespace: kube-system
      labels:
        app.kubernetes.io/instance: descheduler
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: descheduler
        app.kubernetes.io/version: 0.20.0
        helm.sh/chart: descheduler-0.20.0  
      annotations:
        meta.helm.sh/release-name: descheduler
        meta.helm.sh/release-namespace: kube-system
    data: 
      policy.yaml: |-
        apiVersion: "descheduler/v1alpha1"
        kind: "DeschedulerPolicy"
        strategies:
          "RemoveDuplicates": #仅保留removeDuplicates策略。
             enabled: true
  4. 查看调度策略修改后的调度效果。
    1. 执行以下命令,部署新的调度策略。
      kubectl apply -f newPolicy.yaml

      预期输出:

      configmap/descheduler created
    2. 等待两分钟后,执行以下命令,查看Pod分布节点。
      kubectl get pod -o wide | grep nginx

      预期输出:

      NAME                          READY   STATUS     RESTARTS   AGE      IP               NODE                         NOMINATED NODE   READINESS GATES
      nginx-deployment-basic-**1    1/1     Running    0          8m26s    172.25.XXX.XX1   cn-hangzhou.172.16.XXX.XX2   <none>           <none>
      nginx-deployment-basic-**2    1/1     Running    0          8m1s     172.25.XXX.XX2   cn-hangzhou.172.16.XXX.XX1   <none>           <none>
      nginx-deployment-basic-**3    1/1     Running    0          8m26s    172.25.XXX.XX3   cn-hangzhou.172.16.XXX.XX3   <none>           <none>

      从以上预期输出可以得出,nginx-deployment-basic-**2被Descheduler重新调度到cn-hangzhou.172.16.XXX.XX1节点,三个Pod被分散到三个不同的Node节点,实现了副本之间在不同节点的均衡分布。