任务

任务
管理集群
管理集群
Debug DNS 方案
Enabling Service Topology (EN)
IP Masquerade Agent 用户指南
Kubernetes 云管理控制器
Safely Drain a Node while Respecting the PodDisruptionBudget (EN)
为 Kubernetes 运行 etcd 集群
为系统守护进程预留计算资源
为节点发布扩展资源
使用 CoreDNS 进行服务发现
使用 KMS 提供商进行数据加密
使用 Kubernetes API 访问集群
关键插件 Pod 的调度保证
启用端点切片
命名空间演练
在 Kubernetes 集群中使用 NodeLocal DNSCache
在 Kubernetes 集群中使用 sysctl
在实时集群上重新配置节点的 Kubelet
声明网络策略
开发云控制器管理器
控制节点上的 CPU 管理策略
控制节点上的拓扑管理策略
搭建高可用的 Kubernetes Masters
改变默认 StorageClass
更改 PersistentVolume 的回收策略
自定义 DNS 服务
访问集群上运行的服务
通过命名空间共享集群
通过配置文件设置 Kubelet 参数
配置 API 对象配额
配置多个调度器
配置资源不足时的处理方式
限制存储消耗
集群 DNS 服务自动伸缩
集群安全
集群管理
静态加密 Secret 数据
用插件扩展 kubectl
管理巨页(HugePages)
调度 GPUs

Edit This Page

配置多个调度器

Kubernetes 自带了一个默认调度器,其详细描述请查阅这里。 如果默认调度器不适合您的需求,您可以实现自己的调度器。 不仅如此,您甚至可以伴随着默认调度器同时运行多个调度器,并告诉 Kubernetes 为每个 pod 使用什么调度器。 让我们通过一个例子讲述如何在 Kubernetes 中运行多个调度器。

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

准备开始

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

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

打包调度器

将调度器二进制文件打包到容器镜像中。出于示例目的,我们就使用默认调度器(kube-scheduler)作为我们的第二个调度器。 从 Github 克隆 Kubernetes 源代码,并编译构建源代码。

git clone https://github.com/kubernetes/kubernetes.git
cd kubernetes
make

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

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

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

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

为调度器定义 Kubernetes Deployment

现在我们将调度器放在容器镜像中,我们可以为它创建一个 pod 配置,并在我们的 Kubernetes 集群中运行它。 但是与其在集群中直接创建一个 pod,不如使用 DeploymentDeployment 管理一个 Replica Set,Replica Set 再管理 pod,从而使调度器能够适应故障。 以下是 Deployment 配置,被保存为 my-scheduler.yaml

admin/sched/my-scheduler.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-scheduler
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRoleBinding
metadata:
  name: my-scheduler-as-kube-scheduler
subjects:
- kind: ServiceAccount
  name: my-scheduler
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: system:kube-scheduler
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1

kind: Deployment
metadata:
  labels:
    component: scheduler
    tier: control-plane
  name: my-scheduler
  namespace: kube-system
spec:
  selector:
    matchLabels:
      component: scheduler
      tier: control-plane
  replicas: 1
  template:
    metadata:
      labels:
        component: scheduler
        tier: control-plane
        version: second
    spec:
      serviceAccountName: my-scheduler
      containers:
      - command:
        - /usr/local/bin/kube-scheduler
        - --address=0.0.0.0
        - --leader-elect=false
        - --scheduler-name=my-scheduler
        image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 10251
          initialDelaySeconds: 15
        name: kube-second-scheduler
        readinessProbe:
          httpGet:
            path: /healthz
            port: 10251
        resources:
          requests:
            cpu: '0.1'
        securityContext:
          privileged: false
        volumeMounts: []
      hostNetwork: false
      hostPID: false
      volumes: []

这里需要注意的是,在该部署文件中 Container 的 spec 配置的调度器启动命令参数(–scheduler-name)指定的调度器名称应该是惟一的。 这个名称应该与 pods 上的可选参数 spec.schedulerName 的值相匹配,也就是说调度器名称的匹配关系决定了 pods 的调度任务由哪个调度器负责。

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

请参阅 kube-scheduler 文档以获取其他命令行参数的详细说明。

在集群中运行第二个调度器

为了在 Kubernetes 集群中运行我们的第二个调度器,只需在 Kubernetes 集群中创建上面配置中指定的 Deployment:

kubectl create -f my-scheduler.yaml

验证调度器 pod 正在运行:

$ kubectl get pods --namespace=kube-system
NAME                                           READY     STATUS    RESTARTS   AGE
....
my-scheduler-lnf4s-4744f                       1/1       Running   0          2m
...

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

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

首先,更新上述 Deployment YAML(my-scheduler.yaml)文件中的以下字段:

  • --leader-elect=true
  • --lock-object-namespace=lock-object-namespace
  • --lock-object-name=lock-object-name

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

$ kubectl edit clusterrole system:kube-scheduler
- apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRole
  metadata:
    annotations:
      rbac.authorization.kubernetes.io/autoupdate: "true"
    labels:
      kubernetes.io/bootstrapping: rbac-defaults
    name: system:kube-scheduler
  rules:
  - apiGroups:
    - ""
    resourceNames:
    - kube-scheduler
    - my-scheduler
    resources:
    - endpoints
    verbs:
    - delete
    - get
    - patch
    - update

指定 pod 的调度器

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

  • Pod spec 没有任何调度器名称
admin/sched/pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: no-annotation
  labels:
    name: multischeduler-example
spec:
  containers:
  - name: pod-with-no-annotation-container
    image: k8s.gcr.io/pause:2.0

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

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

kubectl create -f pod1.yaml
  • Pod spec 设置为 default-scheduler
admin/sched/pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: annotation-default-scheduler
  labels:
    name: multischeduler-example
spec:
  schedulerName: default-scheduler
  containers:
  - name: pod-with-default-annotation-container
    image: k8s.gcr.io/pause:2.0

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

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

kubectl create -f pod2.yaml
  • Pod spec 设置为 my-scheduler
admin/sched/pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: annotation-second-scheduler
  labels:
    name: multischeduler-example
spec:
  schedulerName: my-scheduler
  containers:
  - name: pod-with-second-annotation-container
    image: k8s.gcr.io/pause:2.0

在这种情况下,我们指定此 pod 使用我们部署的 my-scheduler 来调度。 请注意,spec.schedulerName 参数的值应该与 Deployment 中配置的提供给 scheduler 命令的参数名称匹配。

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

kubectl create -f pod3.yaml

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

kubectl get pods

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

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

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

kubectl get events

反馈