API Server简介
在 kubernetes 集群中,API Server 有着非常重要的角色。API Server 负责和 etcd 交互(其他组件不会直接操作 etcd,只有 API Server 这么做),是整个 kubernetes 集群的数据中心,所有的交互都是以 API Server 为核心的。简单来说,API Server 提供了以下的功能:
整个集群管理的 API 接口:所有对集群进行的查询和管理都要通过 API 来进行
集群内部各个模块之间通信的枢纽:所有模块之前并不会之间互相调用,而是通过和 API Server 打交道来完成自己那部分的工作
集群安全控制:API Server 提供的验证和授权保证了整个集群的安全
API Server源码分析
github地址:https://github.com/kubernetes/kubernetes(当前master对应版本1.8)
sourcegraph网站地址:https://sourcegraph.com/github.com/kubernetes/kubernetes@master
入口:kubernetes/kubernetes/cmd/kube-apiserver/apiserver.go
apiserver.go里面的main方法调用server.go里面的run方法来启动指定的API Server
--》kubernetes/kubernetes/cmd/kube-apiserver/app/server.go
server.go里面的run方法如下:
可以看到先是调用CreateServerChain方法去创建一些server然后去启动这些server
CreateServerChain方法里面主要创建了两个server,一个是kubeAPIServer,一个是apiExtensionsServer。kubeAPIServer是kubernetes独有的API Server,它负责的是kubernetes最主要的api,官方文档里面不建议在这个里面添加和修改api,如果我们有自己编写的api可以放在apiExtensionsServer里面,这个server是负责一些扩展的api。
创建kubeAPIServer用到了CreateKubeAPIServer方法,此方法里面的创建server的关键代码如下:
kubeAPIServerConfig是创建server所用到资源(resource)和配置,complete方法自动填充那些不能为空的字段值,new方法根据传入的config返回一个Server的实例。
--》kubernetes/kubernetes/pkg/master/master.go
new方法里面先根据配置创建一个名字为kube-apiserver的server
然后生成一个Master结构体,此结构体的API Server为刚刚创建的kube-apiserver
然后先注册核心api即LegacyAPI(此方法后面会注册其他的API,例如扩展API和验证所用的API,本文章这里记录注册核心API的过程)
InstallLegacyAPI方法里面先调用NewLegacyRESTStorage方法来新建核心api所需用到的Storage,比如nodeStorage,podStorage(rest.Storage结构是用于对接etcd存储的,每个Storage都有操作ETCD的增删改查方法,比如PodStorage,NodeStorage就是操作对应pod和node在ETCD里面数据的结构,利用它们来实现对ETCD里面数据的操作)。
--》kubernetes/kubernetes/pkg/registry/core/rest/storage_core.go
这里只截取了node和pod的storage创建代码
所有核心API所需用到的Storage新建好之后都添加到restStorageMap 里面去,此map相当于一个配置文件,里面列出了所有api路径和storage的对应关系,当然这里的path路径并不是完整的路径,后面还需加上 /api/v1 这样的前缀才能构成完整的api请求路径。
restStorageMap := 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,
"podTemplates": podTemplateStorage,
"replicationControllers": controllerStorage.Controller,"replicationControllers/status": controllerStorage.Status,
"services": serviceRest.Service,"services/proxy": serviceRest.Proxy,"services/status": serviceStatusStorage,
"endpoints": endpointsStorage,
"nodes": nodeStorage.Node,"nodes/status": nodeStorage.Status,"nodes/proxy": nodeStorage.Proxy,
"events": eventStorage,
"limitRanges": limitRangeStorage,"resourceQuotas": resourceQuotaStorage,"resourceQuotas/status": resourceQuotaStatusStorage,"namespaces": namespaceStorage,"namespaces/status": namespaceStatusStorage,"namespaces/finalize": namespaceFinalizeStorage,"secrets": secretStorage,"serviceAccounts": serviceAccountStorage,"persistentVolumes": persistentVolumeStorage,"persistentVolumes/status": persistentVolumeStatusStorage,"persistentVolumeClaims": persistentVolumeClaimStorage,"persistentVolumeClaims/status": persistentVolumeClaimStatusStorage,"configMaps": configMapStorage,
"componentStatuses": componentstatus.NewStorage(componentStatusStorage{c.StorageFactory}.serversToValidate), }
后面将此map放入到apiGroupInfo结构里面去并返回apiGroupInfo
--》kubernetes/kubernetes/pkg/master/master.go
InstallLegacyAPI方法得到NewLegacyRESTStorage方法返回的apiGroupInfo后调用InstallLegacyAPIGroup方法
--》kubernetes/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go
InstallLegacyAPIGroup方法先调用installAPIResources方法去注册所有前面拿到的storage
installAPIResources方法里面主要处理逻辑就是下面这段,apiGroupVersion结构里面包含了所有的storage
InstallREST方法注册所有的REST处理器handler(包括storage, watch, proxy和redirect)到restful Container
restful.Container代表一个http rest服务对象(restful.Container来自于一个第三方库github.com/emicklei/go-restful),包括一组restful.WebService(每个webserver处理一个对应路径下的所有请求。比如/api/v1/),restful.WebService由多个restful.Route组成,处理这些路径下所有的特殊的MIME类型等,restful.Route为路径(处理函数映射map)
第一段代码生成url前缀字符串,比如/api/vi/。然后新建一个APIInstaller结构并调用它的install方法
--》kubernetes/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go
install方法里面首先新建一个webService结构
然后将所有前面集合里面的api路径path放到一个数组里面并将数组排序,接着循环遍历path数组将path路径与对应的storage注册到handler里面,注册好之后放到前面新建的webService里
registerResourceHandlers这个方法比较大,首先里面会调用拿到的storage(比如传入的是podStorage)的动作方法,这些方法可以判断此storage是否支持此动词,比如
getter, isGetter := storage.(rest.Getter)
若此storage支持get方法则得到getter结构,其他例如create,update,delete这些动作若支持也会得到相应结构体。
然后新建一个action数组并往此数组里面添加所有的action,这些action即GET,PUT和DELETE这些REST请求对应的actionn
然后遍历数组actions,在循环每种动作action(例如get)的逻辑里面先创建一个此action对应的处理器handler,然后通过webService和此handler创建一个route结构,此route结构即为当前path对应到此action的一个路由
循环遍历actions数组之后将所有route添加到当前路径对应的webService中
--》kubernetes/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/groupversion.go
然后回到InstallREST方法中将此webService添加到RestfulContainer中
--》kubernetes/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go
前面的逻辑处理好之后回到InstallLegacyAPIGroup方法,之前调用installAPIResources安装了对应url前缀下的所有rest storage(例如 /api 路径下的所有rest storage),后面接着往RestfulContainer添加另一个控制版本的webService,这个webService枚举了所有支持的api版本(例如 /api/v1, /api/v1bete1),至此API的注册过程全部结束,后面apiServer接收到一个rest请求就会根据RestfulContainer里面的handler来进行处理。
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com