配置多个调度器
Kubernetes 附带一个默认调度器,其描述 在此。如果默认调度器不符合您的需求,您可以实现自己的调度器。此外,您甚至可以在默认调度器旁边同时运行多个调度器,并指示 Kubernetes 对每个 Pod 使用哪个调度器。让我们学习如何使用示例在 Kubernetes 中运行多个调度器。
有关如何实现调度器的详细描述超出了本文档的范围。请参阅 Kubernetes 源代码目录中的 pkg/scheduler 中的 kube-scheduler 实现,以获取规范示例。
开始之前
您需要一个 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/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler
将文件另存为 Dockerfile
,构建镜像并将其推送到注册表。本示例将镜像推送到 Google Container Registry (GCR)。有关更多详细信息,请阅读 GCR 文档。或者,您也可以使用 docker hub。有关更多详细信息,请参阅 docker hub 文档。
docker build -t gcr.io/my-gcp-project/my-kube-scheduler:1.0 . # The image name and the repository
gcloud docker -- push gcr.io/my-gcp-project/my-kube-scheduler:1.0 # used in here is just an example
为调度器定义 Kubernetes 部署
现在您已将调度器置于容器镜像中,请为其创建一个 Pod 配置,并在您的 Kubernetes 集群中运行它。但是,在本示例中,您无需直接在集群中创建 Pod,而是可以使用 部署。一个 部署 管理一个 副本集,副本集进而管理 Pod,从而使调度器能够抵御故障。以下为部署配置。将其另存为 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: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-scheduler-as-volume-scheduler
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
roleRef:
kind: ClusterRole
name: system:volume-scheduler
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-scheduler-extension-apiserver-authentication-reader
namespace: kube-system
roleRef:
kind: Role
name: extension-apiserver-authentication-reader
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-scheduler-config
namespace: kube-system
data:
my-scheduler-config.yaml: |
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-scheduler
leaderElection:
leaderElect: false
---
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
- --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
livenessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
initialDelaySeconds: 15
name: kube-second-scheduler
readinessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
resources:
requests:
cpu: '0.1'
securityContext:
privileged: false
volumeMounts:
- name: config-volume
mountPath: /etc/kubernetes/my-scheduler
hostNetwork: false
hostPID: false
volumes:
- name: config-volume
configMap:
name: my-scheduler-config
在以上清单中,您使用 KubeSchedulerConfiguration 自定义调度器实现的行为。此配置已在初始化期间使用 --config
选项传递给 kube-scheduler
。my-scheduler-config
ConfigMap 存储配置文件。my-scheduler
部署的 Pod 将 my-scheduler-config
ConfigMap 作为卷挂载。
在上述调度器配置中,您的调度器实现通过 KubeSchedulerProfile 表示。
注意
要确定调度器是否负责调度特定 Pod,PodTemplate 或 Pod 清单中的spec.schedulerName
字段必须与 KubeSchedulerProfile
的 schedulerName
字段匹配。集群中运行的所有调度器必须具有唯一名称。此外,请注意,您创建了一个专用的服务帐户 my-scheduler
,并将 ClusterRole system:kube-scheduler
绑定到它,以便它可以获取与 kube-scheduler
相同的权限。
请参阅 kube-scheduler 文档,了解其他命令行参数的详细说明,以及 调度器配置参考,了解其他可定制 kube-scheduler
配置的详细说明。
在集群中运行第二个调度器
为了在 Kubernetes 集群中运行您的调度器,请在 Kubernetes 集群中创建上面配置中指定的部署
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 之外,您还应该看到一个“运行中”的 my-scheduler Pod。
启用领导者选举
要运行多个调度器并启用领导者选举,您必须执行以下操作
更新 YAML 文件中 my-scheduler-config
ConfigMap 中的 KubeSchedulerConfiguration 的以下字段
leaderElection.leaderElect
为true
leaderElection.resourceNamespace
为<lock-object-namespace>
leaderElection.resourceName
为<lock-object-name>
注意
控制平面会为您创建锁定对象,但命名空间必须已存在。您可以使用kube-system
命名空间。如果您的集群上启用了 RBAC,则必须更新 system:kube-scheduler
集群角色。将您的调度器名称添加到应用于 endpoints
和 leases
资源的规则的 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:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- apiGroups:
- coordination.k8s.io
resourceNames:
- kube-scheduler
- my-scheduler
resources:
- leases
verbs:
- get
- update
- apiGroups:
- ""
resourceNames:
- kube-scheduler
- my-scheduler
resources:
- endpoints
verbs:
- delete
- get
- patch
- update
为 Pod 指定调度器
现在您的第二个调度器已在运行,请创建一些 Pod,并将它们引导到由默认调度器或您部署的调度器进行调度。为了使用特定调度器调度给定的 Pod,请在该 Pod 规范中指定调度器的名称。让我们看三个例子。
没有调度器名称的 Pod 规范
apiVersion: v1 kind: Pod metadata: name: no-annotation labels: name: multischeduler-example spec: containers: - name: pod-with-no-annotation-container image: registry.k8s.io/pause:2.0
当没有提供调度器名称时,Pod 会自动使用 default-scheduler 进行调度。
将此文件另存为
pod1.yaml
并将其提交到 Kubernetes 集群。kubectl create -f pod1.yaml
带有
default-scheduler
的 Pod 规范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: registry.k8s.io/pause:2.0
调度器是通过将调度器名称作为值提供给
spec.schedulerName
来指定的。在本例中,我们提供了默认调度器的名称,即default-scheduler
。将此文件另存为
pod2.yaml
并将其提交到 Kubernetes 集群。kubectl create -f pod2.yaml
带有
my-scheduler
的 Pod 规范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: registry.k8s.io/pause:2.0
在本例中,我们指定此 Pod 应该使用我们部署的调度器
my-scheduler
进行调度。请注意,spec.schedulerName
的值应与在KubeSchedulerProfile
的schedulerName
字段中为调度器提供的名称匹配。将此文件另存为
pod3.yaml
并将其提交到 Kubernetes 集群。kubectl create -f pod3.yaml
验证所有三个 Pod 是否正在运行。
kubectl get pods
验证 Pod 是否使用所需的调度器进行调度
为了更轻松地完成这些示例,我们没有验证 Pod 是否确实使用所需的调度器进行调度。我们可以通过更改以上 Pod 和部署配置提交的顺序来验证这一点。如果我们在提交调度器部署配置之前将所有 Pod 配置提交到 Kubernetes 集群,我们会看到 annotation-second-scheduler
Pod 永远处于“挂起”状态,而其他两个 Pod 则被调度。一旦我们提交调度器部署配置并且我们的新调度器开始运行,annotation-second-scheduler
Pod 也会被调度。
或者,您可以查看事件日志中的“已调度”条目,以验证 Pod 是否使用所需的调度器进行调度。
kubectl get events
您也可以使用 自定义调度器配置 或集群主调度器的自定义容器镜像,方法是修改相关控制平面节点上的静态 Pod 清单。