配置多個排程器
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 Deployment
現在你已經將排程器放入容器映象中,為其建立 Pod 配置並在你的 Kubernetes 叢集中執行它。 但是,你無需直接在叢集中建立 Pod,而是可以使用 Deployment 作為本例。 Deployment 管理一個 Replica Set,而 Replica Set 又管理 Pod,從而使排程器對故障具有彈性。 這是 Deployment 配置。 將其儲存為 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/v1
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
Deployment 的 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 叢集中建立上述配置中指定的 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 之外,你應該會看到一個“執行中”的 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:3.8
當未提供排程器名稱時,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:3.8
透過將排程器名稱作為
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:3.8
在這種情況下,我們指定此 Pod 應該使用我們部署的排程器
my-scheduler
進行排程。 請注意,spec.schedulerName
的值應與KubeSchedulerProfile
對映中排程器schedulerName
欄位提供的名稱匹配。將此檔案儲存為
pod3.yaml
並提交到 Kubernetes 叢集。kubectl create -f pod3.yaml
驗證所有三個 Pod 正在執行。
kubectl get pods
驗證 Pod 是否使用所需排程器進行排程
為了更容易地完成這些示例,我們沒有驗證 Pod 是否確實使用所需排程器進行排程。 我們可以透過更改上述 Pod 和 Deployment 配置提交的順序來驗證這一點。 如果我們在提交排程器 Deployment 配置之前將所有 Pod 配置提交到 Kubernetes 叢集,我們會看到 Pod annotation-second-scheduler
永遠保持“待處理”狀態,而其他兩個 Pod 被排程。 一旦我們提交排程器 Deployment 配置並且我們的新排程器開始執行,annotation-second-scheduler
Pod 也會被排程。
或者,你可以檢視事件日誌中的“已排程”條目,以驗證 Pod 是否由所需的排程器進行排程。
kubectl get events
你還可以透過修改相關控制平面節點上的靜態 Pod 清單,為叢集的主排程器使用自定義排程器配置或自定義容器映象。