歡迎來(lái)到深入學(xué)習(xí)Kubernetes API?Server的系列文章渊胸,在本系列文章中我們將深入的探究Kubernetes API?Server的相關(guān)實(shí)現(xiàn)。如果你對(duì)Kubernetes的內(nèi)部實(shí)現(xiàn)機(jī)制比較感興趣或者正在進(jìn)行Kubernetes項(xiàng)目的相關(guān)開(kāi)發(fā)工作,那么本系列文章能夠?yàn)槟闾峁┮恍椭ぶ亍A私鈱W(xué)習(xí)過(guò)go語(yǔ)言惯殊,會(huì)在某些方面幫助你更好的理解本系列文章携御。
在本期文章中诱咏,我們首先會(huì)對(duì)Kubernetes API Server進(jìn)行一個(gè)總體的大致說(shuō)明,然后對(duì)API的技術(shù)術(shù)語(yǔ)及請(qǐng)求流作說(shuō)明缴挖。在下幾期的文章中則主要對(duì)API Server與etcd存儲(chǔ)的交互以及對(duì)API Server進(jìn)行相關(guān)擴(kuò)展進(jìn)行探討袋狞,說(shuō)明。
API Server的總體說(shuō)明
從理論上來(lái)說(shuō)映屋,Kubernetes?是由一些具有不同角色的節(jié)點(diǎn)組成的苟鸯。作為控制面的主節(jié)點(diǎn)主要部署有API Server, Controller Manager 和?Scheduler(s)等組件。API Server作為Kubernetes?中的管理中心棚点,是唯一能夠與存儲(chǔ)etcd交互通信的組件早处。它主要能夠提供如下服務(wù):
1.作為Kubernetes API的服務(wù)端,為集群內(nèi)的節(jié)點(diǎn)以及kubectl工具提供API服務(wù)瘫析。
2.作為集群組件的代理砌梆,例如Kubernetes UI
3.通過(guò)API Server能夠?qū)ubernetes的API對(duì)象比如pods,services進(jìn)行增刪查改等操作贬循。
4.保證在分布式存儲(chǔ)系統(tǒng)(etcd)中的Kubernetes API對(duì)象的狀態(tài)一致咸包。
Kubernetes API是一個(gè)HTTP形式的API,JSON格式是它主要的序列化架構(gòu)杖虾。同時(shí)它也支持協(xié)議緩沖區(qū)(Protocol Buffers)的形式烂瘫,這種形式主要是用在集群內(nèi)通信中。出于可擴(kuò)展性原因考慮奇适,Kubernetes可支持多個(gè)API版本坟比,通過(guò)不同的API路徑的方式區(qū)分。比如/api/v1?和?/apis/extensions/v1beta1嚷往,不同的API版本代表了這個(gè)API處于不同的版本穩(wěn)定性階段葛账。
1.Alpha 階段,比如v1alpha1皮仁,在默認(rèn)狀態(tài)下為關(guān)閉狀態(tài)注竿。只在某個(gè)分支中支持使用,在將來(lái)可能會(huì)2.Beta階段魂贬,比如v2beta3巩割,在默認(rèn)狀態(tài)下為開(kāi)啟狀態(tài)。表示這部分代碼已經(jīng)經(jīng)過(guò)測(cè)試付燥,基本功能已經(jīng)通過(guò)驗(yàn)證宣谈。但是這個(gè)狀態(tài)的API對(duì)象將來(lái)還是有可能發(fā)生不可兼容的改動(dòng)以過(guò)度到stable穩(wěn)定階段。
3.Stable階段键科,比如v1闻丑,是一個(gè)穩(wěn)定的軟件發(fā)布階段漩怎,API對(duì)象一般之后不會(huì)有太大改動(dòng)。
接下去嗦嗡,我們介紹一下HTTP API主要結(jié)構(gòu)勋锤。首先我們需要區(qū)分三種不同的API形式:core group?API(在/api/v1路徑下,由于某些歷史原因而并沒(méi)有在/apis/core/v1路徑下)和named groups API(在對(duì)應(yīng)的/apis/$NAME/$VERSION路徑下)及system-wide?API(比如/metrics,/healthz)侥祭。
一個(gè)HTTP API的主要結(jié)構(gòu)如下所示:
接下去我們主要列舉batch group下的兩個(gè)API例子來(lái)講解說(shuō)明叁执。在Kubernetes?1.5版本中,batch群組下有/apis/batch/v1?和?/apis/batch/v2alpha1兩個(gè)API版本來(lái)供開(kāi)發(fā)者使用矮冬。我們來(lái)看一下API的整體實(shí)現(xiàn)(下面列舉的API例子我們是通過(guò)proxy?命令kubectl proxy --port=8080直接訪問(wèn)API獲得)谈宛。
$ curl http://127.0.0.1:8080/apis/batch/v1?
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "batch/v1",
"resources": [
{
"name": "jobs",
"namespaced": true,
"kind": "Job"
},
{
"name": "jobs/status",
"namespaced": true,
"kind": "Job"
}
]
}
在將來(lái),將會(huì)使用更新的alpha版本:
$ curl http://127.0.0.1:8080/apis/batch/v2alpha1?
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "batch/v2alpha1",
"resources": [
{
"name": "cronjobs",
"namespaced": true,
"kind": "CronJob"
},
{
"name": "cronjobs/status",
"namespaced": true,
"kind": "CronJob"
},
{
"name": "jobs",
"namespaced": true,
"kind": "Job"
},
{
"name": "jobs/status",
"namespaced": true,
"kind": "Job"
},
{
"name": "scheduledjobs",
"namespaced": true,
"kind": "ScheduledJob"
},
{
"name": "scheduledjobs/status",
"namespaced": true,
"kind": "ScheduledJob"
}
]
}
總體上來(lái)說(shuō)Kubernetes API支持對(duì)API對(duì)象的增刪查改(?create, update, delete, retrieve)通過(guò)使用JSON作為默認(rèn)格式的HTTP (POST,?PUT,?DELETE,?GET)方式來(lái)實(shí)現(xiàn)胎署。
大多數(shù)API對(duì)象會(huì)區(qū)分對(duì)象想要達(dá)到的預(yù)期狀態(tài)以及當(dāng)前對(duì)象所處的實(shí)際狀態(tài)吆录。所以一個(gè)規(guī)范的API描述應(yīng)該對(duì)于這兩種狀態(tài)都有完整的描述說(shuō)明并在儲(chǔ)存(etcd)中記錄。
API Server的術(shù)語(yǔ)說(shuō)明
在對(duì)API Server以及HTTP API結(jié)構(gòu)進(jìn)行總體說(shuō)明后琼牧,接下去我們對(duì)一些術(shù)語(yǔ)來(lái)進(jìn)行說(shuō)明解釋恢筝。Kubernetes?的主要API對(duì)象主要有pods, services, endpoints, deployment等。一個(gè)API對(duì)象主要由以下條目
Kind:是一個(gè)API對(duì)象的類型巨坊。它告訴了client(比如kubectl)這種API對(duì)象所代表的實(shí)體類型滋恬。比如一個(gè)pod
apiVersion: v1
kind: Pod
metadata:
name: webserver
spec:
containers:
- name: nginx
image: nginx:1.9
ports:
- containerPort: 80
目前API中有三種Kinds類型:
1.Object對(duì)象代表了系統(tǒng)中持久存在的實(shí)體,一個(gè)object對(duì)象可能具有多個(gè)resources資源能讓客戶端來(lái)執(zhí)行一些特定的操作抱究。比如Pod和namespace.
2.Lists?代表了一些resources資源或者object實(shí)體對(duì)象的集合恢氯。比如PodLists和?NodeLists.
3.代表了一個(gè)對(duì)實(shí)體對(duì)象的操作或一個(gè)非實(shí)體存在的狀態(tài)過(guò)程。比如binding或者status等鼓寺。
API Group?:是一組相關(guān)的Kind的集合勋拟。比如在Kind:Job以及Kind:ScheduleJob都屬于batch的API Group.
Version:每個(gè)API Group下面都能存在有多個(gè)version版本。比如在一個(gè)group群組中最早有第一個(gè)v1alpha1版本妈候,后來(lái)中間發(fā)展到了v1beta1版本敢靡,最終發(fā)展到v1的穩(wěn)定版本。如果在系統(tǒng)創(chuàng)建了一個(gè)v1beta1?版本的對(duì)象苦银,那么它能過(guò)被Group任一支持的版本(比如v1)檢索到啸胧。這是由于API server能夠支持不同版本對(duì)象之間的無(wú)損耗轉(zhuǎn)換。
Resource?:代表以JSON格式通過(guò)HTTP發(fā)送或檢索的資源實(shí)體幔虏。它既可以使一個(gè)單獨(dú)的resource資源(比如.../namespaces/default)也可以是一組resource?資源(比如.../jobs)
一個(gè)API Group群組纺念,一個(gè)Version版本,一個(gè)Resource(GVR)資源就能過(guò)定義一個(gè)唯一的HTTP路徑想括。
實(shí)際上陷谱,一個(gè)job對(duì)象的API路徑為/apis/batch/v1/namespaces/$NAMESPACE/jobs,因?yàn)閖obs并不是cluster側(cè)的資源,所以需要有namespace字段烟逊。與之相對(duì)node作為cluster側(cè)的資源渣窜,它的API路徑就沒(méi)有$NAMESPACE的部分。
值得注意的是Kinds不一定只在同一個(gè)Group群組下存在不同的Version版本宪躯,它在不同的Group群組也有可能存在不同的Version版本乔宿。比如Deployment?一開(kāi)始在extensions group群組中作為alpha版本存在,但最后它發(fā)展成GA version版本時(shí)擁有了一個(gè)新的獨(dú)立的Group群組apps.k8s.io访雪。因此详瑞,如果想要區(qū)分唯一的Kinds,必須要有API Group,Version以及Kind(GVK)三部分冬阳。
API請(qǐng)求流過(guò)程
在對(duì)Kubernetes API中的術(shù)語(yǔ)有了了解之后,接下去我們將討論API請(qǐng)求的處理流程党饮。相關(guān)API主要在k8s.io/pkg/api可以看到肝陪,它既處理來(lái)自集群內(nèi)的API請(qǐng)求也處理來(lái)自集群外的API請(qǐng)求。
當(dāng)API Server接收到一個(gè)HTTP的Kubernetes API請(qǐng)求時(shí)刑顺,它主要處理流程如下所示:
1.HTTP?請(qǐng)求通過(guò)一組定義在DefaultBuildHandlerChain()(config.go)函數(shù)中的過(guò)濾處理函數(shù)處理氯窍,并進(jìn)行相關(guān)操作(相關(guān)過(guò)濾處理函數(shù)如下圖所示)。這些過(guò)濾處理函數(shù)將HTTP請(qǐng)求處理后存到中ctx.RequestInfo蹲堂,比如用戶的相關(guān)認(rèn)證信息狼讨,或者相應(yīng)的HTTP請(qǐng)求返回碼。
2.接著multiplexer?(container.go)基于HTTP路徑會(huì)將HTTP請(qǐng)求發(fā)給對(duì)應(yīng)的各自的處理handlers柒竞。
3.routes?(在routes/*定義)路由將HTTP路徑與handlers處理器關(guān)聯(lián)政供。
4.根據(jù)每個(gè)API Group注冊(cè)的處理程序獲取HTTP請(qǐng)求相關(guān)內(nèi)容對(duì)象(比如用戶,權(quán)限等)朽基,并將請(qǐng)求的內(nèi)容對(duì)象存入存儲(chǔ)中布隔。
完整的處理流程如下圖所示
再次提醒,為簡(jiǎn)潔起見(jiàn)稼虎,我們省略了上圖中HTTP路徑的$NAMESPACE字段衅檀。
下面我們來(lái)仔細(xì)看一下定義在DefaultBuildHandlerChain()(config.go)函數(shù)中的相關(guān)filters過(guò)濾處理函數(shù):
1.定義在requestinfo.go中的WithRequestInfo()函數(shù)主要獲取HTTP請(qǐng)求的RequestInfo內(nèi)容。
2.定義在maxinflight.go的中的WithMaxInFlightLimit()函數(shù)限制請(qǐng)求的in-flight數(shù)量霎俩。
3.定義在timeout.go的中的WithTimeoutForNonLongRunningRequests()函數(shù)主要定義了類似GET,?PUT,?POST,?DELETE等non-long-running請(qǐng)求的超時(shí)時(shí)間哀军。
4.定義在wrap.go?中的WithPanicRecovery()函數(shù)主要定義了當(dāng)發(fā)生panic之后的相關(guān)處理。
5.定義在cors.go中的WithCORS()函數(shù)主要提供了CORS實(shí)現(xiàn)打却。CORS代表跨源資源共享杉适,它是一種機(jī)制,允許能夠處理嵌入在HTML頁(yè)面中的JavaScript的XMLHttpRequests請(qǐng)求柳击。
6.定義在authentication.go?中的WithAuthentication()函數(shù)主要對(duì)請(qǐng)求中的用戶信息進(jìn)行驗(yàn)證淘衙,并將用戶信息存到相應(yīng)的context中。如果認(rèn)證成功腻暮,那么Authorization?HTTP頭將會(huì)在request請(qǐng)求體中移除彤守。
7.定義在audit.go?中的WithAudit()函數(shù)主要將request的用戶信息進(jìn)行相關(guān)處理毯侦。然后將Request請(qǐng)求的源IP,用戶名具垫,用戶操作及namespace等信息記入到相關(guān)審計(jì)日志中侈离。
8.定義在impersonation.go中的WithImpersonation()函數(shù)主要處理用戶模擬,通過(guò)嘗試修改請(qǐng)求的用戶(比如sudo)的方式筝蚕。
9.定義在authorization.go中的WithAuthorization()函數(shù)主要請(qǐng)求中的用戶權(quán)限就行驗(yàn)證卦碾,如果驗(yàn)證通過(guò)則發(fā)送給相應(yīng)的handler進(jìn)行處理,如果權(quán)限驗(yàn)證不通過(guò)則拒絕此次請(qǐng)求起宽,返回相應(yīng)錯(cuò)誤洲胖。
本部分文章主要對(duì)API Server進(jìn)行了一個(gè)總體介紹。下一部分坯沪,我們將對(duì)API資源的序列化以及如何存入到相關(guān)分布式存儲(chǔ)中進(jìn)行探究绿映。