深度剖析Kubernetes API Server三部曲 - part 1

PaaS小魔仙發表於2018-08-30

歡迎來到深入學習 Kubernetes API Server 的系列文章, 在本系列文章中我們將深入的探究 Kubernetes API Server 的相關實現 。如果你對 Kubernetes  的內部實現機制比較感興趣或者正在進行 Kubernetes  專案的相關開發工作,那麼本系列文章能夠為你提供一些幫助。瞭解學習過 go 語言,會在某些方面幫助你更好的理解本系列文章。

在本期文章中,我們首先會對 Kubernetes API Server 進行一個總體的大致說明,然後對 API 的技術術語及請求流作說明。在下幾期的文章中則主要對 API Server etcd 儲存的互動以及對 API Server 進行相關擴充套件進行探討,說明。

API Server 的總體說明

從理論上來說, Kubernetes  是由一些具有不同角色的節點組成的。作為控制面的主節點主要部署有 API Server, Controller Manager Scheduler(s) 等元件。 API Server 作為 Kubernetes  中的管理中心,是唯一能夠與儲存 etcd 互動通訊的元件。它主要能夠提供如下服務:

1.     作為   的服務端,為叢集內的節點以及 kubectl 工具提供 API 服務。

2.     作為叢集元件的代理,例如 Kubernetes UI

3.     透過 API Server 能夠對 Kubernetes API 物件比如 pods services 進行增刪查改等操作。

4.     保證在分散式儲存系統 (etcd) 中的 Kubernetes API 物件的狀態一致。

Kubernetes API 是一個 HTTP 形式的 API JSON 格式是它主要的序列化架構。同時它也支援協議緩衝區( Protocol Buffers )的形式,這種形式主要是用在叢集內通訊中。出於可擴充套件性原因考慮, Kubernetes 可支援多個 API 版本,透過不同的 API 路徑的方式區分。比如 /api/v1     /apis/extensions/v1beta1 ,不同的 API 版本代表了這個 API 處於不同的版本穩定性階段。

1.        Alpha 階段,比如 v1alpha1 ,在預設狀態下為關閉狀態。只在某個分支中支援使用,在將來可能會被廢棄。一般只支援在測試環境中短期使用。

2.        Beta 階段,比如 v2beta3 ,在預設狀態下為開啟狀態。表示這部分程式碼已經經過測試,基本功能已經透過驗證。但是這個狀態的 API 物件將來還是有可能發生不可相容的改動以過度到 stable  穩定階段。

3.        Stable 階段,比如 v1 ,是一個穩定的軟體釋出階段, API 物件一般之後不會有太大改動。

接下去,我們介紹一下 HTTP API 主要結構。首先我們需要區分三種不同的 API 形式: core group API (在 /api/v1 路徑下,由於某些歷史原因而並沒有在 /apis/core/v1 路徑下)和 named groups API (在對應的 /apis/$NAME/$VERSION 路徑下)及 system-wide API (比如 /metrics,/healthz )。

一個 HTTP API 的主要結構如下所示:

接下去我們主要列舉 batch group 下的兩個 API 例子來講解說明。在 Kubernetes 1.5 版本中, batch  群組下有 /apis/batch/v1     /apis/batch/v2alpha1 兩個 API 版本來供開發者使用。我們來看一下 API 的整體實現(下面列舉的 API 例子我們是 透過 proxy  命令 kubectl proxy --port=8080 直接訪問 API 獲得)。

$ curl

{

"kind": "APIResourceList",

"apiVersion": "v1",

"groupVersion": "batch/v1",

"resources": [

{

"name": "jobs",

"namespaced": true,

"kind": "Job"

},

{

"name": "jobs/status",

"namespaced": true,

"kind": "Job"

}

]

}

在將來,將會使用更新的 alpha  版本:

$ curl

{

"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"

}

]

}

總體上來說  Kubernetes API  支援對 API 物件的增刪查改(  create, update, delete, retrieve )透過使用 JSON 作為預設格式的 HTTP ( POST PUT DELETE GET) 方式來實現。

大多數 API 物件會區分物件想要達到的預期狀態以及當前物件所處的實際狀態。所以一個規範的 API 描述應該對於這兩種狀態都有完整的描述說明並在儲存( etcd )中記錄。

API Server 的術語說明

在對 API Server 以及 HTTP API 結構進行總體說明後,接下去我們對一些術語來進行說明解釋。 Kubernetes  的主要 API 物件主要有 pods, services, endpoints, deployment 等。一個 API 物件主要由以下條目

Kind: 是一個 API 物件的型別。它告訴了 client( 比如 kubectl) 這種 API 物件所代表的實體型別。比如一個 pod

apiVersion: v1

kind: Pod

metadata:

name: webserver

spec:

containers:

- name: nginx

image: nginx:1.9

ports:

- containerPort: 80

目前 API 中有三種 Kinds 型別:

1.     Object 物件代表了系統中持久存在的實體,一個 object 物件可能具有多個 resources 資源能讓客戶端來執行一些特定的操作。比如 Pod namespace.

2.     Lists  代表了一些 resources 資源或者 object 實體物件的集合。比如 PodLists  NodeLists.

3.     代表了一個對實體物件的操作或一個非實體存在的狀態過程。比如 binding 或者 status 等。

API Group  : 是一組相關的 Kind 的集合。比如在 Kind:Job 以及 Kind:ScheduleJob 都屬於 batch API Group.

Version :每個 API Group 下面都能存在有多個 version 版本。比如在一個 group 群組中最早有第一個 v1alpha1 版本,後來中間發展到了 v1beta1   版本,最終發展到 v1 的穩定版本。如果在系統建立了一個 v1beta1   版本的物件,那麼它能過被 Group 任一支援的版本(比如 v1 )檢索到。這是由於 API server 能夠支援不同版本物件之間的無損耗轉換。

Resource   :代表以 JSON 格式透過 HTTP 傳送或檢索的資源實體。它既可以使一個單獨的 resource  資源(比如 .../namespaces/default )也可以是一組 resource  資源(比如 .../jobs

一個 API Group 群組,一個 Version 版本,一個 Resource GVR )資源就能過定義一個唯一的 HTTP 路徑。

實際上,一個 job 物件的 API 路徑為 /apis/batch/v1/namespaces/$NAMESPACE/jobs ,因為 jobs 並不是 cluster 側的資源,所以需要有 namespace 欄位。與之相對 node 作為 cluster 側的資源,它的 API 路徑就沒有 $NAMESPACE 的部分。

值得注意的是 Kinds 不一定只在同一個 Group 群組下存在不同的 Version 版本,它在不同的 Group 群組也有可能存在不同的 Version 版本。比如 Deployment   一開始在 extensions group 群組中作為 alpha  版本存在,但最後它發展成 GA version 版本時擁有了一個新的獨立的 Group 群組 apps.k8s.io 。因此,如果想要區分唯一的 Kinds, 必須要有 API Group Version 以及 Kind(GVK) 三部分。

API 請求流過程

在對 Kubernetes API 中的術語有了瞭解之後,接下去我們將討論 API 請求的處理流程。相關 API 主要在 可以看到,它既處理來自叢集內的 API 請求也處理來自叢集外的 API 請求。

API Server 接收到一個 HTTP Kubernetes API 請求時,它主要處理流程如下所示:

1.     HTTP  請求透過一組定義在 DefaultBuildHandlerChain() )函式中的過濾處理函式處理,並進行相關操作(相關過濾處理函式如下圖所示)。這些過濾處理函式將 HTTP  請求處理後存到中 ctx.RequestInfo ,比如使用者的相關認證資訊,或者相應的 HTTP 請求返回碼。

2.     接著 multiplexer  )基於 HTTP 路徑會將 HTTP  請求發給對應的各自的處理 handlers 

3.     routes  (在 routes/* 定義)路由將 HTTP 路徑與 handlers  處理器關聯。

4.     根據每個 API Group 註冊的處理程式獲取 HTTP 請求相關內容物件(比如使用者,許可權等),並將請求的內容物件存入儲存中。

完整的處理流程如下圖所示

再次提醒,為簡潔起見,我們省略了上圖中 HTTP 路徑的 $NAMESPACE 欄位。

下面我們來仔細看一下定義在 DefaultBuildHandlerChain() ( ) 函式中的相關 filters 過濾處理函式:

1.     定義在   中的 WithRequestInfo() 函式主要獲取 HTTP 請求的 RequestInfo 內容。

2.     定義在   的中的 WithMaxInFlightLimit() 函式限制請求的  in-flight 數量。

3.     定義在 的中的 WithTimeoutForNonLongRunningRequests() 函式主要定義了類似 GET PUT POST DELETE non-long-running 請求的超時時間。

4.     定義在   中的 WithPanicRecovery() 函式主要定義了當發生 panic 之後的相關處理。

5.     定義在 中的 WithCORS() 函式主要提供了 CORS  實現。 CORS 代表跨源資源共享,它是一種機制,允許能夠處理嵌入在 HTML 頁面中的 JavaScript XMLHttpRequests 請求。

6.     定義在   中的 WithAuthentication() 函式主要對請求中的使用者資訊進行驗證,並將使用者資訊存到相應的 context 中。如果認證成功,那麼 Authorization  HTTP 頭將會在 request 請求體中移除。

7.     定義在     中的 WithAudit() 函式主要將 request 的使用者資訊進行相關處理。然後將 Request 請求的源 IP ,使用者名稱,使用者操作及 namespace 等資訊記入到相關審計日誌中。

8.     定義在 中的 WithImpersonation() 函式主要處理使用者模擬,透過嘗試修改請求的使用者 ( 比如 sudo) 的方式。

9.     定義在 中的 WithAuthorization() 函式主要請求中的使用者許可權就行驗證,如果驗證透過則傳送給相應的 handler 進行處理,如果許可權驗證不透過則拒絕此次請求,返回相應錯誤。

本部分文章主要對 API Server 進行了一個總體介紹。下一部分,我們將對 API 資源的序列化以及如何存入到相關分散式儲存中進行探究。https://www.huaweicloud.com/product/cce.html


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31543630/viewspace-2213240/,如需轉載,請註明出處,否則將追究法律責任。

相關文章