配置多个调度器

    关于实现调度器的具体细节描述超出了本文范围。 请参考 kube-scheduler 的实现,规范示例代码位于 pkg/scheduler

    你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

    要获知版本信息,请输入 .

    将调度器可执行文件打包到容器镜像中。出于示例目的,可以使用默认调度器 (kube-scheduler)作为第二个调度器。 克隆 GitHub 上 Kubernetes 源代码, 并编译构建源代码。

    创建一个包含 kube-scheduler 二进制文件的容器镜像。用于构建镜像的 Dockerfile 内容如下:

    1. FROM busybox
    2. ADD ./_output/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler

    将文件保存为 Dockerfile,构建镜像并将其推送到镜像仓库。 此示例将镜像推送到 。 有关详细信息,请阅读 GCR 文档

    1. docker build -t gcr.io/my-gcp-project/my-kube-scheduler:1.0 .
    2. gcloud docker -- push gcr.io/my-gcp-project/my-kube-scheduler:1.0

    现在将调度器放在容器镜像中,为它创建一个 Pod 配置,并在 Kubernetes 集群中 运行它。但是与其在集群中直接创建一个 Pod,不如使用 。 Deployment 管理一个 ReplicaSet, ReplicaSet 再管理 Pod,从而使调度器能够免受一些故障的影响。 以下是 Deployment 配置,将其保存为 my-scheduler.yaml

    1. apiVersion: v1
    2. kind: ServiceAccount
    3. metadata:
    4. name: my-scheduler
    5. namespace: kube-system
    6. ---
    7. apiVersion: rbac.authorization.k8s.io/v1
    8. kind: ClusterRoleBinding
    9. metadata:
    10. name: my-scheduler-as-kube-scheduler
    11. subjects:
    12. - kind: ServiceAccount
    13. name: my-scheduler
    14. namespace: kube-system
    15. roleRef:
    16. kind: ClusterRole
    17. name: system:kube-scheduler
    18. apiGroup: rbac.authorization.k8s.io
    19. ---
    20. apiVersion: v1
    21. kind: ConfigMap
    22. metadata:
    23. name: my-scheduler-config
    24. namespace: kube-system
    25. data:
    26. my-scheduler-config.yaml: |
    27. apiVersion: kubescheduler.config.k8s.io/v1beta2
    28. kind: KubeSchedulerConfiguration
    29. profiles:
    30. - schedulerName: my-scheduler
    31. leaderElection:
    32. leaderElect: false
    33. ---
    34. apiVersion: rbac.authorization.k8s.io/v1
    35. kind: ClusterRoleBinding
    36. metadata:
    37. name: my-scheduler-as-volume-scheduler
    38. subjects:
    39. - kind: ServiceAccount
    40. name: my-scheduler
    41. namespace: kube-system
    42. roleRef:
    43. kind: ClusterRole
    44. name: system:volume-scheduler
    45. apiGroup: rbac.authorization.k8s.io
    46. ---
    47. apiVersion: apps/v1
    48. kind: Deployment
    49. metadata:
    50. labels:
    51. component: scheduler
    52. name: my-scheduler
    53. namespace: kube-system
    54. spec:
    55. selector:
    56. matchLabels:
    57. component: scheduler
    58. tier: control-plane
    59. replicas: 1
    60. template:
    61. metadata:
    62. labels:
    63. component: scheduler
    64. tier: control-plane
    65. version: second
    66. serviceAccountName: my-scheduler
    67. containers:
    68. - command:
    69. - /usr/local/bin/kube-scheduler
    70. - --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
    71. image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
    72. livenessProbe:
    73. httpGet:
    74. path: /healthz
    75. port: 10259
    76. scheme: HTTPS
    77. initialDelaySeconds: 15
    78. name: kube-second-scheduler
    79. readinessProbe:
    80. httpGet:
    81. path: /healthz
    82. port: 10259
    83. scheme: HTTPS
    84. resources:
    85. requests:
    86. cpu: '0.1'
    87. securityContext:
    88. privileged: false
    89. volumeMounts:
    90. - name: config-volume
    91. mountPath: /etc/kubernetes/my-scheduler
    92. hostNetwork: false
    93. hostPID: false
    94. volumes:
    95. - name: config-volume
    96. configMap:
    97. name: my-scheduler-config

    在以上的清单中,你使用 KubeSchedulerConfiguration 来自定义调度器实现的行为。当使用 --config 选项进行初始化时,该配置被传递到 kube-schedulermy-scheduler-config ConfigMap 存储配置数据。 my-scheduler Deployment 的 Pod 将 my-scheduler-config ConfigMap 挂载为一个卷。

    在前面提到的调度器配置中,你的调度器通过 进行实现。

    说明: 要确定一个调度器是否可以调度特定的 Pod,PodTemplate 或 Pod 清单中的 spec.schedulerName 字段必须匹配 KubeSchedulerProfile 中的 schedulerName 字段。 所有运行在集群中的调度器必须拥有唯一的名称。

    还要注意,我们创建了一个专用服务账号 my-scheduler 并将集群角色 system:kube-scheduler 绑定到它,以便它可以获得与 kube-scheduler 相同的权限。

    请参阅 kube-scheduler 文档 获取其他命令行参数以及 获取自定义 kube-scheduler 配置的详细说明。

    1. kubectl create -f my-scheduler.yaml

    验证调度器 Pod 正在运行:

    输出类似于:

    1. NAME READY STATUS RESTARTS AGE
    2. ....
    3. my-scheduler-lnf4s-4744f 1/1 Running 0 2m
    4. ...

    此列表中,除了默认的 kube-scheduler Pod 之外,你应该还能看到处于 “Running” 状态的 my-scheduler Pod。

    要在启用了 leader 选举的情况下运行多调度器,你必须执行以下操作:

    更新你的 YAML 文件中的 my-scheduler-config ConfigMap 里的 KubeSchedulerConfiguration 相关字段如下:

    • leaderElection.leaderElect to true
    • leaderElection.resourceNamespace to <lock-object-namespace>
    • leaderElection.resourceName to <lock-object-name>

    说明:

    控制平面会为你创建锁对象,但是命名空间必须已经存在。 你可以使用 kube-system 命名空间。

    如果在集群上启用了 RBAC,则必须更新 system:kube-scheduler 集群角色。 将调度器名称添加到应用了 endpointsleases 资源的规则的 resourceNames 中,如以下示例所示:

    1. kubectl edit clusterrole system:kube-scheduler

    admin/sched/clusterrole.yaml

    1. apiVersion: rbac.authorization.k8s.io/v1
    2. kind: ClusterRole
    3. metadata:
    4. annotations:
    5. rbac.authorization.kubernetes.io/autoupdate: "true"
    6. labels:
    7. kubernetes.io/bootstrapping: rbac-defaults
    8. name: system:kube-scheduler
    9. - apiGroups:
    10. resources:
    11. - leases
    12. verbs:
    13. - create
    14. - apiGroups:
    15. - coordination.k8s.io
    16. resourceNames:
    17. - kube-scheduler
    18. - my-scheduler
    19. resources:
    20. - leases
    21. verbs:
    22. - get
    23. - update
    24. - apiGroups:
    25. - ""
    26. resourceNames:
    27. - kube-scheduler
    28. - my-scheduler
    29. resources:
    30. - endpoints
    31. verbs:
    32. - delete
    33. - get
    34. - patch
    35. - update

    现在第二个调度器正在运行,创建一些 Pod,并指定它们由默认调度器或部署的调度器进行调度。 为了使用特定的调度器调度给定的 Pod,在那个 Pod 的 spec 中指定调度器的名称。让我们看看三个例子。

    • Pod spec 没有任何调度器名称

      1. apiVersion: v1
      2. kind: Pod
      3. metadata:
      4. name: no-annotation
      5. labels:
      6. name: multischeduler-example
      7. spec:
      8. containers:
      9. - name: pod-with-no-annotation-container
      10. image: k8s.gcr.io/pause:2.0

      如果未提供调度器名称,则会使用 default-scheduler 自动调度 pod。

    • Pod spec 设置为 default-scheduler

      admin/sched/pod2.yaml

      1. apiVersion: v1
      2. kind: Pod
      3. metadata:
      4. name: annotation-default-scheduler
      5. labels:
      6. name: multischeduler-example
      7. spec:
      8. schedulerName: default-scheduler
      9. containers:
      10. - name: pod-with-default-annotation-container
      11. image: k8s.gcr.io/pause:2.0

      通过将调度器名称作为 spec.schedulerName 参数的值来指定调度器。 在这种情况下,我们提供默认调度器的名称,即 default-scheduler

      将此文件另存为 pod2.yaml,并将其提交给 Kubernetes 集群。

      1. kubectl create -f pod2.yaml
    • Pod spec 设置为 my-scheduler

      1. apiVersion: v1
      2. kind: Pod
      3. metadata:
      4. name: annotation-second-scheduler
      5. labels:
      6. name: multischeduler-example
      7. spec:
      8. schedulerName: my-scheduler
      9. containers:
      10. - name: pod-with-second-annotation-container
      11. image: k8s.gcr.io/pause:2.0

      在这种情况下,我们指定此 Pod 使用我们部署的 my-scheduler 来调度。 请注意,spec.schedulerName 参数的值应该与调度器提供的 KubeSchedulerProfile 中的 schedulerName 字段相匹配。

      将此文件另存为 pod3.yaml,并将其提交给 Kubernetes 集群。

      确认所有三个 pod 都在运行。

      验证是否使用所需的调度器调度了 pod

      为了更容易地完成这些示例,我们没有验证 Pod 实际上是使用所需的调度程序调度的。 我们可以通过更改 Pod 的顺序和上面的部署配置提交来验证这一点。 如果我们在提交调度器部署配置之前将所有 Pod 配置提交给 Kubernetes 集群, 我们将看到注解了 annotation-second-scheduler 的 Pod 始终处于 “Pending” 状态, 而其他两个 Pod 被调度。 一旦我们提交调度器部署配置并且我们的新调度器开始运行,注解了 annotation-second-scheduler 的 pod 就能被调度。

      或者,可以查看事件日志中的 “Scheduled” 条目,以验证是否由所需的调度器调度了 Pod。

      你也可以使用 或自定义容器镜像,用于集群的主调度器,方法是在相关控制平面节点上修改其静态 pod 清单。