Kubernetes API源碼學習筆記


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來進行處理。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM