Как изменить kube-scheduler по умолчанию в Kubernetes
Этот документ рассказывает о том, как запустить несколько планировщиков. Но я не могу понять, как определяется планировщик по умолчанию? Это основано на
--leader-elect
вариант?
Могу ли я сказать Kubernetes использовать my-custom-scheduler в качестве планировщика по умолчанию вместо kube-scheduler? Есть ли другой способ указать планировщик, кроме
schedulerName
в спецификации Pod/Deployment.
4 ответа
Как определяется планировщик по умолчанию? Это основано на опции --leader-elect?
Нет, это не основано на
--leader-elect
который должен запускать несколько реплицированных копий одного и того же планировщика с включенным выбором лидера, чтобы только одна реплика действовала как лидер в любой заданный момент времени.
Могу ли я сказать Kubernetes использовать my-custom-scheduler в качестве планировщика по умолчанию вместо kube-scheduler?
Вам не нужно менять планировщик по умолчанию на уровне кластера kubernetes, потому что вы можете указать Kubernetes использовать ваш настраиваемый планировщик в спецификации модуля. Пример ниже с использованием
my-scheduler
вместо
default-scheduler
apiVersion: v1
kind: Pod
metadata:
name: pod-with-custom-scheduler
spec:
schedulerName: my-scheduler
containers:
- name: pod-with-custom-scheduler
image: k8s.gcr.io/pause:2.0
Вышеуказанный пакет будет запланирован
my-scheduler
вместо стандартного планировщика куба. Если вы опустите
schedulerName
тогда это будет запланировано по умолчанию kube-scheduler
Из документа
По умолчанию создается один профиль с именем планировщика default-scheduler. Этот профиль включает плагины по умолчанию, описанные выше. При объявлении более одного профиля требуется уникальное имя планировщика для каждого из них.
Если для Pod не указано имя планировщика, kube-apiserver установит для него значение default-scheduler. Следовательно, должен существовать профиль с таким именем планировщика, чтобы эти модули были запланированы.
Таким образом, вы можете просто заменить существующий планировщик kube своим планировщиком с именем
default-scheduler
.
- Замените образ докера kube-scheduler своим изображением в
/etc/kubernetes/manifests/kube-scheduler.yaml
или же - Отредактируйте развертывание планировщика kube и измените образ
Если вы не можете удалить/заменить планировщик по умолчанию в плоскости управления (например, если вы используете управляемую платформу k8s), вы можете использовать GateKeeper — замену OPA — или другой агент политики для записи мутаций, которые применяются к некоторым или все модули в вашем кластере.
Например:
apiVersion: mutations.gatekeeper.sh/v1beta1
kind: Assign
metadata:
name: pod-scheduler-name
spec:
applyTo:
- groups: ""
kinds: ["Pod"]
versions: ["v1"]
match:
kinds:
- apiGroups: ["*"]
kinds: ["Pod"]
# Adjust this to a label that is present on the pods of your custom scheduler.
# It's important that you leave your custom scheduler to be itself scheduled by the
# default scheduler, as otherwise if all pods of your custom scheduler somehow get
# terminated, they won't be able to start up again due to not being scheduled.
labelSelector:
matchExpressions:
- key: app
operator: NotIn
values: ["my-scheduler"]
location: "spec.schedulerName"
# Adjust this to match the desired profile name from your scheduler's configuration.
parameters:
assign:
value: my-scheduler
Мне также нужно было заменить планировщик Kubernetes по умолчанию на собственный. Вот как я это сделал.
Я думаю, что это основная часть ответа. Я переместил (или удалил) файл
Теперь, когда планировщик по умолчанию отключен, у меня есть собственный планировщик (скрипт Python), который выполняет планирование. Я просто запускаю его. Вот скрипт ниже. Это не очень чисто, но должно работать. Вы можете настроить его по своему желанию. Обратите внимание, что я не пытался запускать скрипт после его очистки. Возможны незначительные ошибки.
#!/usr/bin/env python
import time
import random
import json
from kubernetes import client, config, watch
config.load_kube_config()
v1 = client.CoreV1Api()
def get_request_time(hostname):
# You can do some magic here.
print("returning 1.2")
return 1.2
def best_request_time(nodes):
if not nodes:
return []
node_times = [get_request_time(hostname) for hostname in nodes]
best_node = nodes[node_times.index(min(node_times)) + 1]
print("Best node: " + best_node)
return best_node
def nodes_available():
ready_nodes = []
for n in v1.list_node().items:
# This loops over the nodes available. n is the node. We are trying to schedule the pod on one of those nodes.
for status in n.status.conditions:
if status.status == "True" and status.type == "Ready":
ready_nodes.append(n.metadata.name)
return ready_nodes
def scheduler(name, node, namespace="<YOUR-NAMESPACE-HERE"): # You can use "default" as a namespace.
target=client.V1ObjectReference()
target.kind="Node"
target.apiVersion="v1"
target.name= node
meta=client.V1ObjectMeta()
meta.name=name
body=client.V1Binding(target=target)
body.metadata=meta
return v1.create_namespaced_binding(namespace, body, _preload_content=False)
def main():
w = watch.Watch()
for event in w.stream(v1.list_namespaced_pod, "<YOUR-NAMESPACE-HERE>"):
# We get an "event" whenever a pod needs to be scheduled
if event['object'].status.phase == "Pending": # and event['object'].spec.scheduler_name == scheduler_name:
try:
arg2 = best_request_time(nodes_available())
print("Scheduling " + event['object'].metadata.name)
res = scheduler(event['object'].metadata.name, arg2)
except client.rest.ApiException as e:
print("exception")
print(json.loads(e.body)['message'])
if __name__ == '__main__':
main()
Сначала убедитесь, что вы настроили настраиваемый планировщик и отключили
--leader-elect=false
. и вы можете использовать его в модуле в разделе спецификации, например
spec:
containers:
- image: nginx
name: nginx
schedulerName: your-scheduler-name