Как изменить 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.

  1. Замените образ докера kube-scheduler своим изображением в /etc/kubernetes/manifests/kube-scheduler.yaml или же
  2. Отредактируйте развертывание планировщика 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 по умолчанию на собственный. Вот как я это сделал.

Я думаю, что это основная часть ответа. Я переместил (или удалил) файл . Это отключает (или удаляет) планировщик 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
Другие вопросы по тегам