专栏名称: 分布式实验室
最专业的Docker文章,最权威的Docker新闻。关注容器生态圈的发展。
目录
相关文章推荐
51好读  ›  专栏  ›  分布式实验室

如何扩展Kubernetes管理的资源对象?

分布式实验室  · 公众号  · 后端  · 2017-06-07 07:45

正文


Kubernetes是一套容器化解决方案,也是一套资源管理的架构和标准;本次分享是基于我在饿了么现阶段容器化经验和理念的总结,探讨深化Kubernetes在企业内部的应用的方法,介绍如何利用开源的API Server框架在企业内部打造和扩展Kubernetes管理的资源对象。


Kubernetes逐渐成熟,也成为许多公司容器化平台的首选,然而在落地当中,每个企业面对的问题场景多少也有些不一样的,总是希望对Kubernetes做改造,来更好的满足企业目前的需求。


然而fork一个Kubernetes分支出来并不是一个好的选择,那么有其他方案吗?


接下来,我们先了解下Kubernetes的API Server。


  1. API Server作为整个Kubernetes集群的核心组件,让所有资源可被描述和配置;这里的资源包括了类似网络、存储、Pod这样的基础资源也包括了replication controller、deployment这样的管理对象


  2. API Server某种程度上来说更像是包含了一定逻辑的对象数据库;接口上更加丰富、自带GC、支持对象 间的复杂逻辑;当然API Server本身是无状态的 数据都在etcd当中;


  3. API Server提供基于RESTful的管理接口,支持增删改查和patch、监听的操作,其他组件通过和API Server的接口获取资源配置和状态,以实现各种资源处理逻辑。


在Kubernetes集群外打造另一个API Server来扩展Kubernetes的资源,与原生Kubernetes组成“联邦”;一来解除和社区版本的耦合,二来可以最大化定制需求,在一些场景下,这个方案更具灵活性和可操作性。


我们也部署了Kubernetes集群,但是也遇到了一些挑战。一是Kubernetes并不能解决所有容器化带来的问题,二来我们也看到了Kubernetes这套框架在扩展性、灵活性等方面优点,所以我们已经在积极尝试实践Kubernetes框架来延伸Kubernetes方案。


那么好实现吗?有没有现成的开源框架方便实现这个方案呢,而不需要大海捞针,在Kubernetes源码里去抽丝剥茧呢?


令人兴奋的是答案是肯定的,Kubernetes单独开源了API Server的开发框架。


项目地址:https://github.com/kubernetes/apiserver.git,需要说明的是这个项目本身和Kubernetes的代码保持同步的。


那么我们接下来就看下如何利用Kubernetes开源的框架构建特定资源的API Server。


由于已经有很多文章介绍API Server的架构这里不再赘述,我主要讲下如何使用框架,从添加一个资源的过程来了解这个框架。


先上架构图


这里有几个概念要先介绍:


  • Scheme :定义了资源序列化和反序列化的方法以及资源类型和版本的对应关系;这里我们可以理解成一张纪录表。

  • Storage :是对资源的完整封装,实现了资源创建、删除、watch等所有操作。

  • APIGroupInfo :是在同一个Group下的所有资源的集合。


还需要 注意 的是:一个资源对应着两个版本;一个版本是用户访问的接口对象(yaml或者json通过接口传递的格式),另一个版本则是核心对象,实现了资源创建和删除等,并且直接参与持久化,对应了在etcd中存储,这两个版本的资源是需要相互转化的,并且转换方法需要事先注册在Scheme中。


接下来我们具体描述下API Server框架下资源的构建过程。


定义一个资源先要定义好核心对象:


type TestObjList struct {

    Items []TestObj 
}

type TestObj struct {} 


资源的核心对象是该类型资源的主体,参与操作资源的相关方法和持久化,另外除了定义对象本身,还需要定义其对应的list以便支持list接口。


然后定义该资源的"对外"版本-接口对象,可以和核心对象一样也可以不一样,例如,我们可以这样定义接口对象:


type TestObjList struct {

    Items []TestObj 
}

type TestObj struct {
    Number int
}

但是Number值并不会被保存下来,因为核心对象中并没有这个值。


接下来实现资源向Scheme注册的接口函数 SchemeFunc---AddToScheme


func addKnownTypes(scheme *runtime.Scheme) error {
    scheme.AddKnownTypes(SchemeGroupVersion,
        &TestObj{},
        &TestObjList{},
    )
    metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
    return nil
}
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme


那么我们就可以使用AddToScheme,把该对象类型(包括deepcopy和coversion方法)注册到Scheme。


资源要能被RESTful接口访问到,是需要构建实现rest.Storage接口的对象;我们可以借助Registry.Store(实现了标准的存储对象接口)实现:


type REST struct {
    *registry.Store
}

func NewREST() *REST {

    store := ®istry.Store{}

    return &REST{store}
}  


然后组装出APIGroupInfo(APIGroupInfo是包含了一组资源类型的集合):


apiGroupInfo := apiserver.NewDefaultAPIGroupInfo(... Scheme)
v1alpha1storage := map[string]rest.Storage{}
v1alpha1storage["testobj"] = NewREST()
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage   

最后调用GenericAPIServer运行apiserver:


GenericAPIServer.InstallAPIGroup(&apiGroupInfo).Run()

OK,现在你就可以像访问Kubernetes原生资源一样访问这个新的资源了。


注意 :上文中代码为了更好的突出显示资源创建逻辑,一些细节被隐藏掉了。例如可能大家会有疑问,etcd、admissionControl怎么没配置,这其实是在GenericAPIServer中实现了。


最后总结一下, Kubernetes是一套容器化解决方案,也是一套资源管理的架构和标准


Q&A






请到「今天看啥」查看全文