API Server源碼分析之入口點(diǎn)解析
Kubernetes(K8s)集群中最關(guān)鍵的組件之一是 API Server,它是所有集群管理活動的入口點(diǎn)。從本文開始,我們將對 K8s API Server 的代碼進(jìn)行詳細(xì)分析,并探討其應(yīng)用入口點(diǎn)、框架以及與 etcd 的通信。
應(yīng)用入口點(diǎn)
K8s API Server 的主要入口點(diǎn)位于 cmd/kube-apiserver/apiserver.go 文件的。
其中的 app.NewAPIServerCommand() 是構(gòu)建的一個 cobra 的命令對象,cli.Run 然后執(zhí)行該命令即可,所以我們直接查看 NewAPIServerCommand 函數(shù)是如果構(gòu)造 cobra.Command 對象的:
該函數(shù)最核心的功能就是使用 Complete(s) 函數(shù)來生成 apiserver 啟動需要的默認(rèn)參數(shù),然后將默認(rèn)參數(shù)傳遞給 Run 函數(shù)進(jìn)行啟動。
在 Run 函數(shù)中首先會通過 CreateServerChain 函數(shù)通過委托創(chuàng)建連接的 APIServer 對象。
上面的函數(shù)中可以看到 CreateServerChain 會創(chuàng)建3個 server:APIExtensionServer、KubeAPIServer、AggregratorServer,APIServer 就是依靠這3個組件來對不同類型的請求進(jìn)行處理的:
- APIExtensionServer: 主要負(fù)責(zé)處理 CustomResourceDefinition(CRD)方面的請求。
- KubeAPIServer: 主要負(fù)責(zé)處理 K8s 內(nèi)置資源的請求,此外還會包括通用處理、認(rèn)證、鑒權(quán)等。
- AggregratorServer: 主要負(fù)責(zé)聚合器方面的處理,它充當(dāng)一個代理服務(wù)器,將請求轉(zhuǎn)發(fā)到聚合進(jìn)來的 K8s service 中。
創(chuàng)建每個 server 都有對應(yīng)的 config,可以看出上面函數(shù)中的 apiExtensionServer 和 aggregatorServer 的 Config 需要依賴 kubeAPIServerConfig,而這幾個 ServerConfig 都需要依賴 GenericConfig,CreateKubeAPIServerConfig 函數(shù)創(chuàng)建 kubeAPIServerConfig ,在該函數(shù)中通過調(diào)用 buildGenericConfig 來創(chuàng)建 GenericConfig 對象,如下代碼所示。
然后我們再來分別看看這3個 Server 是如何構(gòu)建的。
go-restful框架
這里我們就不得不先了解下 go-restful 這個框架了,因?yàn)?APIServer 就使用的這個框架。下面的代碼是 go-restful 官方的一個示例,這個 demo 了解后基本上就知道 go-restful 框架是如何使用的了:
這個示例代碼,就是使用 go-restful 的核心功能實(shí)現(xiàn)了一個簡單的 RESTful 的 API,實(shí)現(xiàn)了對 User 的增刪查改,其中有這么幾個核心概念:Container、WebService、Route。
- Container:服務(wù)器容器,包含多個 WebService 和一個 http.ServerMux。
- WebService:服務(wù),由多個 Route 組成,一個 WebService 其實(shí)代表某一個對象相關(guān)的服務(wù),如上例中的 /users,針對該 /users 要實(shí)現(xiàn)RESTful API,那么需要向其添加增刪查改的路由,即 Route,它是 Route 的集合。
- Route:路由,包含了 url,http 方法,接收和響應(yīng)的媒體類型以及處理函數(shù)。每一個 Route,根據(jù) Method 和 Path,映射到對應(yīng)的方法中,即是 Method/Path 到 Function 映射關(guān)系的抽象,如上例中的 ws.Route(ws.GET("/{user-id}").To(u.findUser)),就是針對 /users/{user-id}該路徑的GET請求,則被路由到 findUser 方法中進(jìn)行處理。
- Container 是 WebService 的集合,可以向 Container 中添加多個 WebService,而 Container 因?yàn)閷?shí)現(xiàn)了 ServeHTTP() 方法,其本質(zhì)上還是一個http Handler,可以直接用在 http Server 中。
Kubernetes 中對 go-restful 的使用比較基礎(chǔ),就使用到了其最基礎(chǔ)的路由功能,由于 K8s 有很多內(nèi)置的資源對象,也包括 CRD 這種自定義資源對象,所以一開始并不是直接將這些資源對應(yīng)對應(yīng)的接口硬編碼的,而是通過一系列代碼動態(tài)注冊的,所以接下來我們分析的其實(shí)就是想辦法讓 APIServer 能夠提供如下所示的路由處理出來:
對 go-restful 有一個基礎(chǔ)了解后,后面就可以去了解下這3個 Server 具體是如何實(shí)例化的了。