開源容器叢集管理系統Kubernetes架構及元件介紹
Kubernetes 作為Docker生態圈中重要一員,是Google多年大規模容器管理技術的開源版本,是產線實踐經驗的最佳表現。如Urs Hölzle所說,無論是公有云還是私有云甚至混合雲,Kubernetes將作為一個為任何應用,任何環境的容器管理框架無處不在。正因為如此,目前受到各大巨頭及初創公司的青睞,如Microsoft、VMWare、Red Hat、CoreOS、Mesos等,紛紛加入給Kubernetes貢獻程式碼。隨著Kubernetes社群及各大廠商的不斷改進、發展,Kuberentes將成為容器管理領域的領導者。
接下來我們一起探索Kubernetes是什麼、能做什麼以及怎麼做。
1. 什麼是Kubernetes
Kubernetes是Google開源的容器叢集管理系統,使用Golang開發,其提供應用部署、維護、擴充套件機制等功能,利用Kubernetes能方便地管理跨機器執行容器化的應用,其主要功能如下:
- 使用Docker對應用程式包裝(package)、例項化(instantiate)、執行(run)。
- 以叢集的方式執行、管理跨機器的容器。
- 解決Docker跨機器容器之間的通訊問題。
- Kubernetes的自我修復機制使得容器叢集總是執行在使用者期望的狀態。
當前Kubernetes支援GCE、vShpere、CoreOS、OpenShift、Azure等平臺,除此之外,也可以直接執行在物理機上。
這個官方給出的完整的架構圖:(可放大看)
2. Kubernetes的主要概念
2.1 Pods
在Kubernetes系統中,排程的最小顆粒不是單純的容器,而是抽象成一個Pod,Pod是一個可以被建立、銷燬、排程、管理的最小的部署單元。把相關的一個或多個容器(Container)構成一個Pod,通常Pod裡的容器執行相同的應用。Pod包含的容器執行在同一個Minion(Host)上,看作一個統一管理單元,共享相同的volumes和network namespace/IP和Port空間。
2.2 Services
Services也是Kubernetes的基本操作單元,是真實應用服務的抽象,每一個服務後面都有很多對應的容器來支援,通過Proxy的port和服務selector決定服務請求傳遞給後端提供服務的容器,對外表現為一個單一訪問地址,外部不需要了解後端如何執行,這給擴充套件或維護後端帶來很大的好處。
這一點github上的官網文件services.md講的特別清楚。
2.3 Replication Controllers
Replication Controller,理解成更復雜形式的pods,它確保任何時候Kubernetes叢集中有指定數量的pod副本(replicas)在執行,如果少於指定數量的pod副本(replicas),Replication Controller會啟動新的Container,反之會殺死多餘的以保證數量不變。Replication Controller使用預先定義的pod模板建立pods,一旦建立成功,pod 模板和建立的pods沒有任何關聯,可以修改 pod 模板而不會對已建立pods有任何影響,也可以直接更新通過Replication Controller建立的pods。對於利用 pod 模板建立的pods,Replication Controller根據 label selector 來關聯,通過修改pods的label可以刪除對應的pods。Replication Controller主要有如下用法:
Rescheduling 如上所述,Replication Controller會確保Kubernetes叢集中指定的pod副本(replicas)在執行, 即使在節點出錯時。
Scaling 通過修改Replication Controller的副本(replicas)數量來水平擴充套件或者縮小執行的pods。
Rolling updates Replication Controller的設計原則使得可以一個一個地替換pods來滾動更新(rolling updates)服務。
Multiple release tracks 如果需要在系統中執行multiple release的服務,Replication Controller使用labels來區分multiple release tracks。
以上三個概念便是使用者可操作的REST物件。Kubernetes以RESTfull API形式開放的介面來處理。
2.4 Labels
service和replicationController只是建立在pod之上的抽象,最終是要作用於pod的,那麼它們如何跟pod聯絡起來呢?這就引入了label的概念:label其實很好理解,就是為pod加上可用於搜尋或關聯的一組key/value標籤,而service和replicationController正是通過label來與pod關聯的。為了將訪問Service的請求轉發給後端提供服務的多個容器,正是通過標識容器的labels來選擇正確的容器;Replication Controller也使用labels來管理通過 pod 模板建立的一組容器,這樣Replication Controller可以更加容易,方便地管理多個容器。
如下圖所示,有三個pod都有label為"app=backend",建立service和replicationController時可以指定同樣的label:"app=backend",再通過label selector機制,就將它們與這三個pod關聯起來了。例如,當有其他frontend pod訪問該service時,自動會轉發到其中的一個backend pod。
3. Kubernetes構件
Kubenetes整體框架如下圖,主要包括kubecfg、Master API Server、Kubelet、Minion(Host)以及Proxy。
3.1 Master
Master定義了Kubernetes 叢集Master/API Server的主要宣告,包括Pod Registry、Controller Registry、Service Registry、Endpoint Registry、Minion Registry、Binding Registry、RESTStorage以及Client, 是client(Kubecfg)呼叫Kubernetes API,管理Kubernetes主要構件Pods、Services、Minions、容器的入口。Master由API Server、Scheduler以及Registry等組成。從下圖可知Master的工作流主要分以下步驟:
- Kubecfg將特定的請求,比如建立Pod,傳送給Kubernetes Client。
- Kubernetes Client將請求傳送給API server。
- API Server根據請求的型別,比如建立Pod時storage型別是pods,然後依此選擇何種REST Storage API對請求作出處理。
- REST Storage API對的請求作相應的處理。
- 將處理的結果存入高可用鍵值儲存系統Etcd中。
- 在API Server響應Kubecfg的請求後,Scheduler會根據Kubernetes Client獲取叢集中執行Pod及Minion資訊。
- 依據從Kubernetes Client獲取的資訊,Scheduler將未分發的Pod分發到可用的Minion節點上。
下面是Master的主要構件的詳細介紹。
3.1.1 Minion Registry
Minion Registry負責跟蹤Kubernetes 叢集中有多少Minion(Host)。Kubernetes封裝Minion Registry成實現Kubernetes API Server的RESTful API介面REST,通過這些API,我們可以對Minion Registry做Create、Get、List、Delete操作,由於Minon只能被建立或刪除,所以不支援Update操作,並把Minion的相關配置資訊儲存到etcd。除此之外,Scheduler演算法根據Minion的資源容量來確定是否將新建Pod分發到該Minion節點。
可以通過curl http://{master-apiserver-ip}:4001/v2/keys/registry/minions/
來驗證etcd中儲存的內容。
3.1.2 Pod Registry
Pod Registry負責跟蹤Kubernetes叢集中有多少Pod在執行,以及這些Pod跟Minion是如何的對映關係。將Pod Registry和Cloud Provider資訊及其他相關資訊封裝成實現Kubernetes API Server的RESTful API介面REST。通過這些API,我們可以對Pod進行Create、Get、List、Update、Delete操作,並將Pod的資訊儲存到etcd中,而且可以通過Watch介面監視Pod的變化情況,比如一個Pod被新建、刪除或者更新。
3.1.3 Service Registry
Service Registry負責跟蹤Kubernetes叢集中執行的所有服務。根據提供的Cloud Provider及Minion Registry資訊把Service Registry封裝成實現Kubernetes API Server需要的RESTful API介面REST。利用這些介面,我們可以對Service進行Create、Get、List、Update、Delete操作,以及監視Service變化情況的watch操作,並把Service資訊儲存到etcd。
3.1.4 Controller Registry
Controller Registry負責跟蹤Kubernetes叢集中所有的Replication Controller,Replication Controller維護著指定數量的pod 副本(replicas)拷貝,如果其中的一個容器死掉,Replication Controller會自動啟動一個新的容器,如果死掉的容器恢復,其會殺死多出的容器以保證指定的拷貝不變。通過封裝Controller Registry為實現Kubernetes API Server的RESTful API介面REST, 利用這些介面,我們可以對Replication Controller進行Create、Get、List、Update、Delete操作,以及監視Replication Controller變化情況的watch操作,並把Replication Controller資訊儲存到etcd。
3.1.5 Endpoints Registry
Endpoints Registry負責收集Service的endpoint,比如Name:"mysql",Endpoints: ["10.10.1.1:1909","10.10.2.2:8834"],同Pod Registry,Controller Registry也實現了Kubernetes API Server的RESTful API介面,可以做Create、Get、List、Update、Delete以及watch操作。
3.1.6 Binding Registry
Binding包括一個需要繫結Pod的ID和Pod被繫結的Host,Scheduler寫Binding Registry後,需繫結的Pod被繫結到一個host。Binding Registry也實現了Kubernetes API Server的RESTful API介面,但Binding Registry是一個write-only物件,所有隻有Create操作可以使用, 否則會引起錯誤。
3.1.7 Scheduler
Scheduler收集和分析當前Kubernetes叢集中所有Minion節點的資源(記憶體、CPU)負載情況,然後依此分發新建的Pod到Kubernetes叢集中可用的節點。由於一旦Minion節點的資源被分配給Pod,那這些資源就不能再分配給其他Pod, 除非這些Pod被刪除或者退出, 因此,Kubernetes需要分析叢集中所有Minion的資源使用情況,保證分發的工作負載不會超出當前該Minion節點的可用資源範圍。具體來說,Scheduler做以下工作:
- 實時監測Kubernetes叢集中未分發的Pod。
- 實時監測Kubernetes叢集中所有執行的Pod,Scheduler需要根據這些Pod的資源狀況安全地將未分發的Pod分發到指定的Minion節點上。
- Scheduler也監測Minion節點資訊,由於會頻繁查詢Minion節點,Scheduler會快取一份最新的資訊在本地。
- 最後,Scheduler在分發Pod到指定的Minion節點後,會把Pod相關的資訊Binding寫回API Server。
3.2 Kubelet
根據上圖可知Kubelet是Kubernetes叢集中每個Minion和Master API Server的連線點,Kubelet執行在每個Minion上,是Master API Server和Minion之間的橋樑,接收Master API Server分配給它的commands和work,與永續性鍵值儲存etcd、file、server和http進行互動,讀取配置資訊。Kubelet的主要工作是管理Pod和容器的生命週期,其包括Docker Client、Root Directory、Pod Workers、Etcd Client、Cadvisor Client以及Health Checker元件,具體工作如下:
- 通過Worker給Pod非同步執行特定的Action
- 設定容器的環境變數
- 給容器繫結Volume
- 給容器繫結Port
- 根據指定的Pod執行一個單一容器
- 殺死容器
- 給指定的Pod建立network 容器
- 刪除Pod的所有容器
- 同步Pod的狀態
- 從cAdvisor獲取container info、 pod info、 root info、 machine info
- 檢測Pod的容器健康狀態資訊
- 在容器中執行命令。
3.3 Proxy
Proxy是為了解決外部網路能夠訪問跨機器叢集中容器提供的應用服務而設計的,執行在每個Minion上。Proxy提供TCP/UDP sockets的proxy,每建立一種Service,Proxy主要從etcd獲取Services和Endpoints的配置資訊(也可以從file獲取),然後根據配置資訊在Minion上啟動一個Proxy的程序並監聽相應的服務埠,當外部請求發生時,Proxy會根據Load Balancer將請求分發到後端正確的容器處理。
所以Proxy不但解決了同一主宿機相同服務埠衝突的問題,還提供了Service轉發服務埠對外提供服務的能力,Proxy後端使用了隨機、輪循負載均衡演算法。關於更多 kube-proxy 的內容 KUBERNETES程式碼走讀之MINION NODE 元件 KUBE-PROXY 。
4. etcd
etcd在上面架構圖上提到過幾次,但它並不是kubernetes的一部分,它是 CoreOS 團隊發起的一個管理配置資訊和服務發現(service discovery)專案,目標是構建一個高可用的分散式鍵值(key-value)資料庫。與kubernetes和docker一樣還是在快速迭代開發中的產品,沒有ZooKeeper那樣成熟。有機會再另外通過文章介紹。