针对kubernetes v1.1.8-beta.0版本,从数据结构定义和使用的角度对kubernetes源代码进行分析,分析scheduler模块和api-server模块。

1、scheduler模块

对于调度,一般分成两个部分,第一部分是调度算法部分,第二部分是调度执行部分,但是在kubernetes的调度模块中,只有调度算法部分,也就是根据POD请求在所有Node中找到一个适合的Node,第二部分并不在kubernetes调度模块中。
在kubernetes调度算法部分有个核心的结构体,叫做genericScheduler。下面我们先详细的分析下这个结构体,在分析这个结构体的过程中我们就可以发现调度算法。

type genericScheduler struct {
    predicates   map[string]algorithm.FitPredicate
    prioritizers []algorithm.PriorityConfig
    pods         algorithm.PodLister
    random       *rand.Rand
    randomLock   sync.Mutex
}

genericScheduler是负责调度的结构体,里面用到了algorithm包中的FitPredicate函数、PriorityConfig结构体和PodLister接口,还用到了rand包的Rand结构体、sync包的Mutex结构体。FitPredicate函数用来在Node中判断POD请求的资源是否满足需要,PriorityConfig结构体包括Function函数和Weight整型变量,Function函数用来表示优先级算法,Weight变量用来表示优先级算法权重。PodLister接口用来表示满足调度算法的所有POD信息。Rand结构体用来表示均匀分布的伪随机数,随机数范围从0到9223372036854775807,Mutex结构体用来表示互斥锁,如果Mutex结构体中sema变量的值为0,那么表示没有被锁。
Schedule是负责调度的函数,里面用到了findNodesThatFit和PrioritizeNodes两个函数。findNodesThatFit函数会在所有Node中查找满足genericScheduler结构体中变量predicates所指定函数算法要求的所有Node。PrioritizeNodes函数对满足条件的Node按照genericScheduler结构体中变量prioritizers进行优先级计算,prioritizers结构体代表一个优先级计算函数数组,对每个Node会顺序的对每个优先级计算函数进行计算,然后将每个优先级计算函数计算结果相加,最后得出每个Node优先级,对于一个优先级计算函数的计算方法是按照prioritizers结构体中Function函数计算出优先级,优先级从0到10,0是最低的优先级,10是最高的优先级,然后将得到的优先级乘以prioritizers结构体中权重变量Weight,最后得出这个算法优先级。
Schedule函数最后通过selectHost函数从已经计算好优先级的Node列表中按照优先级最大值随机选取一个Node。
kubernetes调度通过结构体genericScheduler最后选取出了一个Node,用来在这个Node上面创建POD,但是整个调度的工作还没有完成,到目前为止只是选出了一个Node,但是在这个Node上面创建POD的工作并没有做,下面我们看看kubernetes是如何创建POD的。
前面调度算法执行结束后,调度模块将调度结果发送出去,并没有在调度模块中执行。在kubernetes发送调度结果部分有个核心的结构体,叫做Binding,这个结构体的作用是建立将一个对象绑定到另一个对象的关系,比如在调度过程中将POD绑定到一个Node上,在这个结构体中就是将ObjectMeta(POD)绑定到ObjectReference(Node)上。

type Binding struct {
    unversioned.TypeMeta `json:",inline"`
    ObjectMeta `json:"metadata,omitempty"`
    Target ObjectReference `json:"target"`
}

在建立好POD同Node的绑定关系后,将这个绑定关系向下执行,也就是真正的在Node上去创建POD,这里面使用到了GO语言的一个接口Binder。

type Binder interface {
    Bind(binding *api.Binding) error
}

这里提到了GO语言的接口,那我们来说说GO语言,GO语言不是一种典型的面向对象语言,它在语法上没有类和继承的概念,没有继承是否就无法拥有面向对象中的“多态”行为,但是GO语言引入了一种新类型“接口”,它在效果上实现了面向对象中“多态”的概念。
到此,我们分析了kuberneters调度模块中的调度算法和调度结果发送,其实kuberneters的算法还是很简单的,相比较Mesos的DRF机制简单了很多,还有很多优化扩展的空间,从kuberneters架构设计来看,kuberneters调度算法部分其实也是很容易进行扩展和替换的。

2、api-server模块

api-server模块中主要使用APIServer结构体,这个结构体存放api-server使用到的各种参数。在这个结构体中变量InsecurePort表示访问api-server的端口,默认是8080,变量SecurePort表示访问api-server的安全端口,默认是6443,变量EtcdPathPrefix表示etcd中所有资源前缀,默认是”/registry”,变量EnableLogsSupport表示是否启用日志,默认是启用,变量MasterServiceNamespace表示kubernetes master服务命名空间,默认是”default”,变量ClusterName表示集群中实例的前缀,默认是”kubernetes”,变量CertDirectory表示TLS认证目录,默认是”/var/run/kubernetes”,这个目录中会存放TLS证书文件和TLS私钥文件,TLS是 Transport Layer Security(传输层安全协议)的缩写,用于两个应用程序之间提供保密性和数据完整性。TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本,可以理解为SSL 3.1,它是写入了 RFC 的。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。
Api-server模块还是用到了Master结构体,这个结构体存放kubernetes master节点中api-server信息。Master结构体中用到了第三方组件etcd,将kubernetes中的POD、service等信息注册到etcd中,实现这些信息的数据持久化。
Api-server模块首先初始化APIServer结构体,接着初始化Master结构体,然后初始化访问安全认证,最后作为http server进行端口监听。

Logo

开源、云原生的融合云平台

更多推荐