2023年6月30日发(作者:)
kubernetes之kube-ApiServer代码分析⼀、概述: kube-ApiServer相当于是k8集群的⼀个⼊⼝,不论通过kubectl还是使⽤remote api 直接控制,都要经过apiserver。apiserver说⽩了就是⼀个server负责监听指定的端⼝(http/https协议),之后处理不同的请求,只不过加上的很多控制;apiserver是k8s系统中所有对象的增删查改盯的http/restful式服务端,其中盯是指watch操作【watch是apiserver中的重要操作之⼀】。数据最终存储在分布式⼀致的etcd存储内,apiserver本⾝是⽆状态的,提供了这些数据访问的认证鉴权、缓存、api版本适配转换等⼀系列的功能。⼆、restful基础 对于http服务和使⽤go语⾔实现⽅式,可以看go-restful的和 k8s存放在etcd内的存储对象是对象(⽆版本),从不同版本的请求路径标⽰来操作,例如api/v1,最后获取到的是不同版本,例如的json⽂本。这⾥就经历了⼏个过程,包括: 1、http client访问/api/v1/pod/xyz, 想要获取到这个Pod的数据 2、从etcd获取到对象 3、对象转换为对象 4、对象序列化为json或yaml⽂本 5、⽂本通过http的response体,返回给http client 其中⽤于处理业务数据的关键数据结构是APIGroupVersion: 1 // APIGroupVersion is a helper for exposing e objects as rs via go-restful 2 // It handles URLs of the form: 3 // /${storage_key}[/${object_name}] 4 // Where 'storage_key' points to a e object stored in storage. 5 // This object should contain all parameterization necessary for running a particular API version 6 //重点数据结构 7 type APIGroupVersion struct { 8 //最重要的数据结构,该map的key是⽤于对,value是e结构,⽤于对接etcd存储, 9 //在初始化注册时,会把这个map化开,化为真正的rest服务到存储的⼀条龙服务10 Storage map[string]e11
12 Root string13
14 // GroupVersion is the external group version15 // 包含api/v1这样的string,⽤于标⽰这个实例16 GroupVersion ersion17
18 // RequestInfoResolver is used to parse URLs for the legacy proxy handler. Don't use this for anything else19 // TODO: refactor proxy handler to use sub resources20 RequestInfoResolver *RequestInfoResolver21
22 // OptionsExternalVersion controls the Kubernetes APIVersion used for common objects in the apiserver23 // schema like , Options, and tions. Other implementors may24 // define a version "v1beta1" but want to use the Kubernetes "v1" internal objects. If25 // empty, defaults to GroupVersion.26 OptionsExternalVersion *ersion27
28 Mapper pper29
30 // Serializer is used to determine how to convert responses from API methods into bytes to send over31 // the wire.32 //对象序列化和反序列化器33 Serializer atedSerializer34 ParameterCodec terCodec35
36 Typer Typer37 Creater Creater38 //可以转换任意⼀种对象到另⼀种,只要你事先注⼊了相应的转换函数39 HandleFunc(pattern string, handler func(seWriter, *t))40 Convertor Convertor41 Copier Copier42 Linker nker43
44 Admit ace45 Context tContextMapper46
47 MinRequestTimeout on48
49 // SubresourceGroupVersionKind contains the GroupVersionKind overrides for each subresource that is50 // accessible from this API group version. The GroupVersionKind is that of the external version of51 // the subresource. The key of this map should be the path of the subresource. The keys here should52 // match the keys in the Storage map above for subresources.53 SubresourceGroupVersionKind map[string]ersionKind54 }三、API分组、多版本的初始化注册(Rest) k8s采⽤ApiGroup来管理所有的api分组和版本升级,⽬前的API分组包括: 1、核⼼组,REST路径在/api/v1,但这个路径不是固定的,v1是当前的版本。与之相对应的代码⾥⾯的apiVersion字段的值为v1. 2、扩展组,REST路径在/apis/extensions/$version, 相应的代码⾥⾯的apiversion:extensions/$VERSION(eg:apiVersion:extensions/v1beta1),这⾥的API对象可能会被重新分组; 3、"componentconfig" 和 "metrics"这些组 在⾥⾯讲述了实现ApiGroup的⼏个⽬标,包括api分组演化,对旧版API的向后兼容(Backwards compatibility),包括⽤户可以⾃定义⾃⼰的api等。接下来我们看看他么是怎么初始化注册的,这⾥都是缩减版代码,去掉了其他部分。1. api注册⼊⼝:kubernets/pkg/master/
func New(c *Config)(*Master, error) { lAPIs(c)
} 2.根据Config往APIGroupsInfo内增加组信息,然后通过InstallAPIGroups进⾏注册1 func (m *Master) InstallAPIs(c *Config) {2 if err := lAPIGroups(apiGroupsInfo); err != nil {3 ("Error in registering group versions:%v", err)4 }5 } 3.转换为APIGroupVersion这个关键数据结构,然后进⾏注册func (s *GenericAPIServer) installAPIGroup(apiGroupInfo *APIGroupInfo) error { apiGroupVersion, err := GroupVersion(apiGroupInfo, groupVersion, apiPrefix) if err := lREST(rContainer); err != nil { return ("Unable to setup API %v: %v", apiGroupInfo, err) }
} upVersion 关键数据结构kubernetes/pkg/apiserver/
type APIGroupVersion struct { Storage map[string]e
Root string //GroupVersion is the external group version
GroupVersion ersion} 5.实际注册的Storage的map如下:kubernetes/pkg/master/ m.v1ResourcesStorage = map[string]e{ "pods": , "pods/attach": , "pods/status": , "pods/log": , "pods/exec": , "pods/portforward": rward, "pods/proxy": , "pods/binding": g, "bindings": g, 那么,这⾥的map[string]e最后是怎么变成⼀个具体的API来提供服务的呢?例如这么⼀个URL: GET /api/v1/namespaces/{namespace}/pods/{name} k8s使⽤的⼀个第三⽅库/emicklei/go-restful,⾥⾯提供了⼀组核⼼的对象,看数据结构实际注册过程kubernetes/pkg/apiserver/api_功能代表⼀个http rest服务对象,包括⼀组vice由多个组成,处理这些路径下所有的特殊的MIME类型等路径——处理函数映射map在k8s内的位置 - rContainerapi_ - NewWebService()api_ - registerResourceHandlersfunc (a *APIInstaller) registerResourceHandlers(path string, storage e, ws *vice, proxyHandler r) (*ource, error) {}最终的API注册过程是在这个函数中完成的,把⼀个e对象转换为实际的getter, lister等处理函数,并和实际的url关联起来。存储的操作(ORM) 上⾯已经基本厘清了从http请求 -> -> e这条线路,那e仅仅是⼀个接⼝,有何德何能,可以真正的操作etcd呢? 这段也是牵涉到多个⽂件,但还⽐较清晰,⾸先,所有的对象都有增删改查这些操作,如果为Pod单独搞⼀套,Controller单独搞⼀套,那代码会⾮常重复,不可复⽤,所以存储的关键⽬录是在这⾥: kubernetes/pkg/registry/generic/etcd/ 这个⽂件定义了所有的对etcd对象的操作,get,list,create等,但具体的对象是啥,这个⽂件不关⼼;etcd客户端地址,这个⽂件也不关⼼。这些信息都是在具体的PodStorage对象创建的时候注⼊的。以Pod为例⼦,⽂件在: kubernetes/pkg/registry/pod/etcd/ 这⾥的NewStorage⽅法,把上述的信息注⼊了etcd⾥⾯去,⽣成了PodStorage这个对象。 // REST implements a RESTStorage for pods against etcd type REST struct { * proxyTransport ripper } 由于是⼀个REST类型,⽽REST类型采⽤了Go语⾔的struct匿名内部成员,天然就拥有Get, List等⽅法。 kubernetes/pkg/apiserver/api_ 最后在这⾥把PodStorage转换成了Getter对象,并最终注册到ApiGroup⾥⾯去。
发布者:admin,转转请注明出处:http://www.yc00.com/web/1688056417a72262.html
评论列表(0条)