In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)05/31 Report--
这篇文章主要介绍了kubernetes代码阅读apiserver的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
apiserver是整个kubernetes的核心模块,做的事情多,代码量也较大。市面上已经有不少apiserver代码解读的文章了,但问题在于,由于k8s的代码变化很快,想写一篇长久能用的未必能做到。所以,我参照了《Kubernetes权威指南》和浙大SEL实验室的一些文章,先把我看到的东西记下来,待后观是否有用。
kubernetes源代码版本1.2.0
代码阅读方法
先简单讲讲整个代码的目录结构
目录说明api输出接口文档用build构建脚本cluster适配不同I层的云,例如亚马逊AWS,微软Azure,谷歌GCE的集群启动脚本cmd所有的二进制可执行文件入口代码,例如apiserver/scheduler/kubeletcontrib项目贡献者docs文档,包括了用户文档、管理员文档、设计、新功能提议example使用案例Godeps项目中依赖使用的Go第三方包,例如docker客户端SDK,rest等hack工具箱,各种编译、构建、测试、校验的脚本都在这里面hooksgit提交前后触发的脚本pkg项目代码主目录,cmd的只是个入口,这里是所有的具体实现plugin插件,k8s认为调度器是插件的一部分,所以调度器的代码在这里release应该是Google发版本用的?test测试相关的工具third_party一些第三方工具,应该不是强依赖的?wwwUI,不过已经被移动到新项目了
可以看到,关键实现代码都放在pkg这个目录下。对于apiserver这种跨度很广的组件而言,唯一有效的阅读方式估计就是
遍历pkg下所有的目录,概览大概知道这个目录是干啥的
从cmd这个入口来看apiserver的代码,然后一点点由浅入深,看apiserver的大致实现
分特性,看具体某个大的特性是怎么实现的,例如安全,例如和etcd存储对接
在上面这几步的过程中可以看看别人的代码阅读文档,能有效的节省时间
0. apiserver主要实现了什么?
apiserver是k8s系统中所有对象的增删查改盯的http/restful式服务端,其中盯是指watch操作。数据最终存储在分布式一致的etcd存储内,apiserver本身是无状态的,提供了这些数据访问的认证鉴权、缓存、api版本适配转换等一系列的功能。
restful服务入门
对于http服务和使用go语言实现方式,可以看go-restful的文档和例子,对这个有基本的了解,这个文档对入门者和一知半解者极为有效!
1. 对象的数据结构
古人有言,程序就是算法+数据结构,搞懂了数据结构,整个程序的处理过程就明白了一半。对于apiserver的任何一个api请求来说,上图说明了所有的数据结构关系。
k8s放在etcd内的存储对象是api.Pod对象(无版本),从不同版本的请求路径标识来操作,例如api/v1,最后获取到的是不同版本,例如v1.Pod的json文本。这里就经历了几个过程,包括
http client访问/api/v1/pod/xyz,想要获取这个Pod的数据
从etcd获取到api.Pod对象
api.Pod对象转换为v1.Pod对象
v1.Pod对象序列化为json或yaml文本
文本通过http的response体,返回给http client
其中用于处理业务数据的关键数据结构是APIGroupVersion,里面的几个成员变量的作用是:
成员作用GroupVersion包含 api/v1这样的string,用于标识这个实例Serializer对象序列化和反序列化器Converter这是一个强大的数据结构,这里放的是个接口,本体在/pkg/conversion/conversion.go,几乎可以转换任意一种对象到另一种,只要你事先注入了相应的转换函数Storage这个map的key,用于对象的url,value是一个rest.Storage结构,用于对接etcd存储,在初始化注册时,会把这个map化开,化为真正的rest服务到存储的一条龙服务2. 入口和启动文件主要数据结构/函数用途kubernetes/cmd/kube-apiserver/apiserver.go
入口kubernetes/cmd/kube-apiserver/app/options/options.gostruct APIServer启动选项kubernetes/cmd/kube-apiserver/apiserver.gofunc Run初始化一些客户端、启动master对象kubernetes/pkg/genericapiserver/genericapiserver.gofunc Run启动安全和非安全的http服务3. API分组、多版本的初始化注册(Rest)
k8s采用ApiGroup来管理所有的api分组和版本升级,目前有的API分组包括
核心组,REST路径在 /api/v1 ,但这个路径不是固定的,v1是当前的版本。与之相对应的代码里面的apiVersion 字段的值是 v1。
扩展组,REST路径在 /apis/extensions/$VERSION,相对应的代码里面的 apiVersion: extensions/$VERSION (例如当前的apiVersion: extensions/v1beta1)。这里提供的API对象今后有可能会被移动到别的组内。
"componentconfig"和 "metrics"这这些组。
在这个文档里面讲述了实现ApiGroup的几个目标,包括api分组演化,对旧版API的向后兼容(Backwards compatibility),包括用户可以自定义自己的api等。接下来我们看看他么是怎么初始化注册的,这里都是缩减版代码,去掉了其他部分。
kubernetes/pkg/master/master.go
api注册入口
func New(c *Config) (*Master, error) { m.InstallAPIs(c)}
根据Config往APIGroupsInfo内增加组信息,然后通过InstallAPIGroups进行注册
func (m *Master) InstallAPIs(c *Config) { if err := m.InstallAPIGroups(apiGroupsInfo); err != nil { glog.Fatalf("Error in registering group versions: %v", err) }}
转换为APIGroupVersion这个关键数据结构,然后进行注册
func (s *GenericAPIServer) installAPIGroup(apiGroupInfo *APIGroupInfo) error { apiGroupVersion, err := s.getAPIGroupVersion(apiGroupInfo, groupVersion, apiPrefix) if err := apiGroupVersion.InstallREST(s.HandlerContainer); err != nil { return fmt.Errorf("Unable to setup API %v: %v", apiGroupInfo, err) }}
关键数据结构
kubernetes/pkg/apiserver/apiserver.gotype APIGroupVersion struct { Storage map[string]rest.Storage Root string // GroupVersion is the external group version GroupVersion unversioned.GroupVersion}
实际注册的Storage的map如下:
kubernetes/pkg/master/master.go m.v1ResourcesStorage = map[string]rest.Storage{ "pods": podStorage.Pod, "pods/attach": podStorage.Attach, "pods/status": podStorage.Status, "pods/log": podStorage.Log, "pods/exec": podStorage.Exec, "pods/portforward": podStorage.PortForward, "pods/proxy": podStorage.Proxy, "pods/binding": podStorage.Binding, "bindings": podStorage.Binding,
那么,这里的map[string]rest.Storage最后是怎么变成一个具体的API来提供服务的呢?例如这么一个URL:
GET /api/v1/namespaces/{namespace}/pods/{name}
restful服务的实现
k8s使用的一个第三方库github.com/emicklei/go-restful,里面提供了一组核心的对象,看例子
数据结构功能在k8s内的位置restful.Container代表一个http rest服务对象,包括一组restful.WebServicegenericapiserver.go - GenericAPIServer.HandlerContainerrestful.WebService由多个restful.Route组成,处理这些路径下所有的特殊的MIME类型等api_installer.go - NewWebService()restful.Route路径--处理函数映射mapapi_installer.go - registerResourceHandlers()
实际注册过程
kubernetes/pkg/apiserver/api_installer.gofunc (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storage, ws *restful.WebService, proxyHandler http.Handler) (*unversioned.APIResource, error) {}
最终的API注册过程是在这个函数中完成的,把一个rest.Storage对象转换为实际的getter, lister等处理函数,并和实际的url关联起来。
4.etcd存储的操作(ORM)
上面已经基本厘清了从http请求 -> restful.Route -> rest.Storage这条线路,那rest.Storage仅仅是一个接口,有何德何能,可以真正的操作etcd呢?
这段也是牵涉到多个文件,但还比较清晰,首先,所有的对象都有增删改查这些操作,如果为Pod单独搞一套,Controller单独搞一套,那代码会非常重复,不可复用,所以存储的关键目录是在这里:
kubernetes/pkg/registry/generic/etcd/etcd.go
这个文件定义了所有的对etcd对象的操作,get,list,create等,但具体的对象是啥,这个文件不关心;etcd客户端地址,这个文件也不关心。这些信息都是在具体的PodStorage对象创建的时候注入的。以Pod为例子,文件在:
kubernetes/pkg/registry/pod/etcd/etcd.go
这里的NewStorage方法,把上述的信息注入了etcd里面去,生成了PodStorage这个对象。
// REST implements a RESTStorage for pods against etcdtype REST struct { *etcdgeneric.Etcd proxyTransport http.RoundTripper}
由于PodStorage.Pod是一个REST类型,而REST类型采用了Go语言的struct匿名内部成员,天然就拥有Get, List等方法。
kubernetes/pkg/apiserver/api_installer.go
最后在这里把PodStorage转换成了Getter对象,并最终注册到ApiGroup里面去。
感谢你能够认真阅读完这篇文章,希望小编分享的"kubernetes代码阅读apiserver的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.