I also needed to replace the default Kubernetes scheduler with a custom one. Here's how I did it.
I think this is the main piece of the answer. I moved (or removed) the file etc/kubernetes/manifests/kube-scheduler.yaml
. This disables (or removes) the default Kubernetes scheduler. Moreover, you can check that it gets removed by running kubectl get po -n kube-system | grep -i scheduler
before and after removing the file.
Now that the default scheduler is disabled, I have a custom scheduler (a python script) that does the scheduling. I just run it. Here's the script below. It's not very clean, but it should work. You can tweak it as you wish. Note that I didn't try running the script after I cleaned it. Minor errors may exist.
#!/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()