美文网首页
动手写kube-scheduler(1)

动手写kube-scheduler(1)

作者: 大雄good | 来源:发表于2019-08-24 21:41 被阅读0次

    不知道各位小伙伴是不是和我一样都有看过蛮多关于kubernetes的文档和各种源码解读(说实话我是看不下去的),所以还是觉得自己飘在外面。

    我觉得基本的k8s的使用,如果有业务驱动花上几个月时间是能够熟悉主要的功能,其他比较偏的知识可以在用到的时候查看。网上关于k8s的原理和源码解读的文章有一大堆,但是研究k8s自身的源码,说实话如果没有业务驱动或者debug的需求,真的蛮难啃下去的。所以我以另外的一条学习之路,就是通过增量的实现和完善一个kube-scheduler来完成对kube-scheduler的学习。

    为什么首先选择scheduler呢?一是scheduler是k8s的核心组件,可以了解k8s组件之间的交互;二是scheduler比较简单,项目上也有潜在的定制scheduler的需求,我先花点业余时间写一个试试水。另外在网上我也搜到一篇英文的blog可以参考,不至于完全没头绪。

    scheduler调度过程

    写scheduler之前,还是需要简单回顾和介绍k8s创建一个pod的过程。下图是从Kubernetes in Action截取的k8s部署一个deployment的过程:

    Creating a deployemnt

    从step 6,7可以看到scheduler主要任务就是:

    1. 通过API Server来watch未标记nodeName的pod;
    2. 经过计算将pod调度到合适的node。

    Scheduler初始版本实现

    OK,根据上面的分析,可以看到Scheduler的任务还是比较简单的,这里我们根据sheduler的原理,先实现一个最简易的Scheduler。这里的代码主要还是fork的BanzaiCloud的code,简单修改了一下。

    首先,我们需要通过APIServer来watchspec.schedulerNamecustom-scheduler(我们创建的scheduler name)且nodeName为空字符串的pod。(这里注意一下,如果没有指定schedulerName,所有scheduler都会尝试去为该pod绑定node)。
    然后,我们可以开始监听符合条件的pod的ADDED事件(意味着新创建的pod)。

        // start to watch pod
        watch, err := s.clientSet.CoreV1().Pods("").Watch(metav1.ListOptions{
            FieldSelector: fmt.Sprintf("spec.schedulerName=%s,spec.nodeName=", name),
        })
    ...
        // handle add pod event
        for event := range watch.ResultChan() {
            if event.Type != "ADDED" {
                continue
            }
            p, ok := event.Object.(*v1.Pod)
            if !ok {
                fmt.Println("unexpected type")
                continue
            }
    

    对新创建的pod,我们需要绑定到合适的node上,这里我们list了集群所有的node,每次选择第一个node进行绑定(实际k8s的scheduler会对node的资源进行过滤并且对node打分,这里只是为了验证功能所以每次都选择第一个node):

        nodes, err := s.clientSet.CoreV1().Nodes().List(metav1.ListOptions{})
    ...
        //always use the first node
        log.Println("Available node list:")
        for _, node := range nodes.Items {
            log.Println("available node name:", node.GetName())
        }
        return &nodes.Items[0], nil
    ...
        // binding the pod to selected node
        return s.clientSet.CoreV1().Pods(p.Namespace).Bind(&v1.Binding{
            ObjectMeta: metav1.ObjectMeta{
                Name:      p.Name,
                Namespace: p.Namespace,
            },
            Target: v1.ObjectReference{
                APIVersion: "v1",
                Kind:       "Node",
                Name:       node.Name,
            },
        })
    

    完成了pod和node的绑定,再触发一个Scheduled的event:

        _, err := s.clientSet.CoreV1().Events(p.Namespace).Create(&v1.Event{
            Count:          1,
            Message:        message,
            Reason:         "Scheduled",
            LastTimestamp:  metav1.NewTime(timestamp),
            FirstTimestamp: metav1.NewTime(timestamp),
            Type:           "Normal",
            Source: v1.EventSource{
                Component: name,
            },
            InvolvedObject: v1.ObjectReference{
                Kind:      "Pod",
                Name:      p.Name,
                Namespace: p.Namespace,
                UID:       p.UID,
            },
            ObjectMeta: metav1.ObjectMeta{
                GenerateName: p.Name + "-",
            },
        })
    

    这样调度完之后可以看到“Scheduled”的event:

     kubectl get pod -o wide |grep sleep
    sleep-5d4cc94556-g4ggq              1/1     Running   0          46s    10.244.0.215   master   <none>           <none>
    sleep-5d4cc94556-zhrb5              1/1     Running   0          6m8s   10.244.0.214   master   <none>           <none>
    
    kubectl get event |grep sleep
    4m41s Normal   Scheduled  Pod  Placed pod [default/sleep-5d4cc94556-zhrb5] on master
    0s    Normal   Scheduled  Pod  Placed pod [default/sleep-5d4cc94556-g4ggq] on master
    

    本文中的代码在这里,下载下来,执行步骤(我是在mac下编译的,所以可以根据自己的环境修改一下Makefile):

    make
    kubectl create -f deployment
    

    小结

    本文根据banzaicloud的blog总结和实现了一个简易的scheduler,总的代码也只有一百多行,比较容易理解和练习。当然这个scheduler还有许多问题,比如没leader-election,并发效率不高,没有处理delete pod等功能(必须使用--force删除pod)。不过没关系,先迈开脚步开干,这些功能我们慢慢增量地完善,这样更有动力继续学习。

    相关文章

      网友评论

          本文标题:动手写kube-scheduler(1)

          本文链接:https://www.haomeiwen.com/subject/dpccectx.html