本文收錄在容器技術學習系列文章總目錄node
一、Kubernetes設計架構
Kubernetes集羣包含有節點代理kubelet和Master組件(APIs, scheduler, etc),一切都基於分佈式的存儲系統。下面這張圖是Kubernetes的架構圖。git
二、Kubernetes節點
2.1 介紹
① 在這張系統架構圖中,咱們把服務分爲運行在工做節點上的服務和組成集羣級別控制板的服務。github
② Kubernetes節點有運行應用容器必備的服務,而這些都是受Master的控制。算法
③ 每次個節點上固然都要運行Docker。Docker來負責全部具體的映像下載和容器運行。數據庫
④ Kubernetes主要由如下幾個核心組件組成:後端
- etcd 保存了整個集羣的狀態;
- apiserver 提供了資源操做的惟一入口,並提供認證、受權、訪問控制、API註冊和發現等機制;
- controller manager 負責維護集羣的狀態,好比故障檢測、自動擴展、滾動更新等;
- scheduler 負責資源的調度,按照預約的調度策略將Pod調度到相應的機器上;
- kubelet 負責維護容器的生命週期,同時也負責Volume(CVI)和網絡(CNI)的管理;
- Container runtime 負責鏡像管理以及Pod和容器的真正運行(CRI);
- kube-proxy 負責爲Service提供cluster內部的服務發現和負載均衡;
⑤ 除了核心組件,還有一些推薦的Add-ons:api
- kube-dns 負責爲整個集羣提供DNS服務
- Ingress Controller 爲服務提供外網入口
- Heapster提供資源監控
- Dashboard提供GUI
- Federation提供跨可用區的集羣
- Fluentd-elasticsearch提供集羣日誌採集、存儲與查詢
2.2 示意圖
(1)kubernetes master安全
(2)kubernetes node服務器
三、分層架構
Kubernetes設計理念和功能其實就是一個相似Linux的分層架構,以下圖所示
- 核心層:Kubernetes最核心的功能,對外提供API構建高層的應用,對內提供插件式應用執行環境
- 應用層:部署(無狀態應用、有狀態應用、批處理任務、集羣應用等)和路由(服務發現、DNS解析等)
- 管理層:系統度量(如基礎設施、容器和網絡的度量),自動化(如自動擴展、動態Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
- 接口層:kubectl命令行工具、客戶端SDK以及集羣聯邦
- 生態系統:在接口層之上的龐大容器集羣管理調度的生態系統,能夠劃分爲兩個範疇
- Kubernetes外部:日誌、監控、配置管理、CI、CD、Workflow、FaaS、OTS應用、ChatOps等
- Kubernetes內部:CRI、CNI、CVI、鏡像倉庫、Cloud Provider、集羣自身的配置和管理等
四、K8S相關名字解釋
(1)kubelet
kubelet負責管理pods和它們上面的容器,images鏡像、volumes、etc。
(2)kube-proxy
每個節點也運行一個簡單的網絡代理和負載均衡(詳見services FAQ )(PS:官方 英文)。 正如Kubernetes API裏面定義的這些服務(詳見the services doc)(PS:官方 英文)也能夠在各類終端中以輪詢的方式作一些簡單的TCP和UDP傳輸。
服務端點目前是經過DNS或者環境變量( Docker-links-compatible 和 Kubernetes{FOO}_SERVICE_HOST 及 {FOO}_SERVICE_PORT 變量都支持)。這些變量由服務代理所管理的端口來解析。
(3)Kubernetes控制面板
Kubernetes控制面板能夠分爲多個部分。目前它們都運行在一個master 節點,然而爲了達到高可用性,這須要改變。不一樣部分一塊兒協做提供一個統一的關於集羣的視圖。
(4)etcd
全部master的持續狀態都存在etcd的一個實例中。這能夠很好地存儲配置數據。由於有watch(觀察者)的支持,各部件協調中的改變能夠很快被察覺。
(5)Kubernetes API Server
API服務提供Kubernetes API (PS:官方 英文)的服務。這個服務試圖經過把全部或者大部分的業務邏輯放到不兩隻的部件中從而使其具備CRUD特性。它主要處理REST操做,在etcd中驗證更新這些對象(並最終存儲)。
(6)Scheduler
調度器把未調度的pod經過binding api綁定到節點上。調度器是可插拔的,而且咱們期待支持多集羣的調度,將來甚至但願能夠支持用戶自定義的調度器。
(7)Kubernetes控制管理服務器
全部其它的集羣級別的功能目前都是由控制管理器所負責。例如,端點對象是被端點控制器來建立和更新。這些最終能夠被分隔成不一樣的部件來讓它們獨自的可插拔。
replicationcontroller(PS:官方 英文)是一種創建於簡單的 pod API之上的一種機制。一旦實現,咱們最終計劃把這變成一種通用的插件機制。
五、kubernetes設計理念
5.1 Kubernetes設計理念與分佈式系統
分析和理解Kubernetes的設計理念可使咱們更深刻地瞭解Kubernetes系統,更好地利用它管理分佈式部署的雲原生應用,另外一方面也可讓咱們借鑑其在分佈式系統設計方面的經驗。
(1)API設計原則
對於雲計算系統,系統API實際上處於系統設計的統領地位,正如本文前面所說,K8s集羣系統每支持一項新功能,引入一項新技術,必定會新引入對應的API對象,支持對該功能的管理操做,理解掌握的API,就比如抓住了K8s系統的牛鼻子。K8s系統API的設計有如下幾條原則:
- 全部API應該是聲明式的。正如前文所說,聲明式的操做,相對於命令式操做,對於重複操做的效果是穩定的,這對於容易出現數據丟失或重複的分佈式環境來講是很重要的。另外,聲明式操做更容易被用戶使用,可使系統向用戶隱藏實現的細節,隱藏實現的細節的同時,也就保留了系統將來持續優化的可能性。此外,聲明式的API,同時隱含了全部的API對象都是名詞性質的,例如Service、Volume這些API都是名詞,這些名詞描述了用戶所指望獲得的一個目標分佈式對象。
- API對象是彼此互補並且可組合的。這裏面實際是鼓勵API對象儘可能實現面向對象設計時的要求,即「高內聚,鬆耦合」,對業務相關的概念有一個合適的分解,提升分解出來的對象的可重用性。事實上,K8s這種分佈式系統管理平臺,也是一種業務系統,只不過它的業務就是調度和管理容器服務。
- 高層API以操做意圖爲基礎設計。如何可以設計好API,跟如何能用面向對象的方法設計好應用系統有相通的地方,高層設計必定是從業務出發,而不是過早的從技術實現出發。所以,針對K8s的高層API設計,必定是以K8s的業務爲基礎出發,也就是以系統調度管理容器的操做意圖爲基礎設計。
- 低層API根據高層API的控制須要設計。設計實現低層API的目的,是爲了被高層API使用,考慮減小冗餘、提升重用性的目的,低層API的設計也要以需求爲基礎,要儘可能抵抗受技術實現影響的誘惑。
- 儘可能避免簡單封裝,不要有在外部API沒法顯式知道的內部隱藏的機制。簡單的封裝,實際沒有提供新的功能,反而增長了對所封裝API的依賴性。內部隱藏的機制也是很是不利於系統維護的設計方式,例如PetSet和ReplicaSet,原本就是兩種Pod集合,那麼K8s就用不一樣API對象來定義它們,而不會說只用同一個ReplicaSet,內部經過特殊的算法再來區分這個ReplicaSet是有狀態的仍是無狀態。
- API操做複雜度與對象數量成正比。這一條主要是從系統性能角度考慮,要保證整個系統隨着系統規模的擴大,性能不會迅速變慢到沒法使用,那麼最低的限定就是API的操做複雜度不能超過O(N),N是對象的數量,不然系統就不具有水平伸縮性了。
- API對象狀態不能依賴於網絡鏈接狀態。因爲衆所周知,在分佈式環境下,網絡鏈接斷開是常常發生的事情,所以要保證API對象狀態能應對網絡的不穩定,API對象的狀態就不能依賴於網絡鏈接狀態。
- 儘可能避免讓操做機制依賴於全局狀態,由於在分佈式系統中要保證全局狀態的同步是很是困難的。
(2)控制機制設計原則
- 控制邏輯應該只依賴於當前狀態。這是爲了保證分佈式系統的穩定可靠,對於常常出現局部錯誤的分佈式系統,若是控制邏輯只依賴當前狀態,那麼就很是容易將一個暫時出現故障的系統恢復到正常狀態,由於你只要將該系統重置到某個穩定狀態,就能夠自信的知道系統的全部控制邏輯會開始按照正常方式運行。
- 假設任何錯誤的可能,並作容錯處理。在一個分佈式系統中出現局部和臨時錯誤是大機率事件。錯誤可能來自於物理系統故障,外部系統故障也可能來自於系統自身的代碼錯誤,依靠本身實現的代碼不會出錯來保證系統穩定其實也是難以實現的,所以要設計對任何可能錯誤的容錯處理。
- 儘可能避免複雜狀態機,控制邏輯不要依賴沒法監控的內部狀態。由於分佈式系統各個子系統都是不能嚴格經過程序內部保持同步的,因此若是兩個子系統的控制邏輯若是互相有影響,那麼子系統就必定要能互相訪問到影響控制邏輯的狀態,不然,就等同於系統裏存在不肯定的控制邏輯。
- 假設任何操做均可能被任何操做對象拒絕,甚至被錯誤解析。因爲分佈式系統的複雜性以及各子系統的相對獨立性,不一樣子系統常常來自不一樣的開發團隊,因此不能奢望任何操做被另外一個子系統以正確的方式處理,要保證出現錯誤的時候,操做級別的錯誤不會影響到系統穩定性。
- 每一個模塊均可以在出錯後自動恢復。因爲分佈式系統中沒法保證系統各個模塊是始終鏈接的,所以每一個模塊要有自我修復的能力,保證不會由於鏈接不到其餘模塊而自我崩潰。
- 每一個模塊均可以在必要時優雅地降級服務。所謂優雅地降級服務,是對系統魯棒性的要求,即要求在設計實現模塊時劃分清楚基本功能和高級功能,保證基本功能不會依賴高級功能,這樣同時就保證了不會由於高級功能出現故障而致使整個模塊崩潰。根據這種理念實現的系統,也更容易快速地增長新的高級功能,覺得沒必要擔憂引入高級功能影響原有的基本功能。
5.2 Kubernetes的核心技術概念和API對象
API對象是K8s集羣中的管理操做單元。K8s集羣系統每支持一項新功能,引入一項新技術,必定會新引入對應的API對象,支持對該功能的管理操做。例如副本集Replica Set對應的API對象是RS。
每一個API對象都有3大類屬性:元數據metadata、規範spec和狀態status。元數據是用來標識API對象的,每一個對象都至少有3個元數據:namespace,name和uid;除此之外還有各類各樣的標籤labels用來標識和匹配不一樣的對象,例如用戶能夠用標籤env來標識區分不一樣的服務部署環境,分別用env=dev、env=testing、env=production來標識開發、測試、生產的不一樣服務。規範描述了用戶指望K8s集羣中的分佈式系統達到的理想狀態(Desired State),例如用戶能夠經過複製控制器Replication Controller設置指望的Pod副本數爲3;status描述了系統實際當前達到的狀態(Status),例如系統當前實際的Pod副本數爲2;那麼複製控制器當前的程序邏輯就是自動啓動新的Pod,爭取達到副本數爲3。
K8s中全部的配置都是經過API對象的spec去設置的,也就是用戶經過配置系統的理想狀態來改變系統,這是k8s重要設計理念之一,即全部的操做都是聲明式(Declarative)的而不是命令式(Imperative)的。聲明式操做在分佈式系統中的好處是穩定,不怕丟操做或運行屢次,例如設置副本數爲3的操做運行屢次也仍是一個結果,而給副本數加1的操做就不是聲明式的,運行屢次結果就錯了。
(1)Pod
K8s有不少技術概念,同時對應不少API對象,最重要的也是最基礎的是微服務Pod。Pod是在K8s集羣中運行部署應用或服務的最小單元,它是能夠支持多容器的。Pod的設計理念是支持多個容器在一個Pod中共享網絡地址和文件系統,能夠經過進程間通訊和文件共享這種簡單高效的方式組合完成服務。Pod對多容器的支持是K8s最基礎的設計理念。好比你運行一個操做系統發行版的軟件倉庫,一個Nginx容器用來發布軟件,另外一個容器專門用來從源倉庫作同步,這兩個容器的鏡像不太多是一個團隊開發的,可是他們一起工做才能提供一個微服務;這種狀況下,不一樣的團隊各自開發構建本身的容器鏡像,在部署的時候組合成一個微服務對外提供服務。
Pod是K8s集羣中全部業務類型的基礎,能夠看做運行在K8s集羣中的小機器人,不一樣類型的業務就須要不一樣類型的小機器人去執行。目前K8s中的業務主要能夠分爲長期伺服型(long-running)、批處理型(batch)、節點後臺支撐型(node-daemon)和有狀態應用型(stateful application);分別對應的小機器人控制器爲Deployment、Job、DaemonSet和PetSet,本文後面會一一介紹。
(2)複製控制器(Replication Controller,RC)
RC是K8s集羣中最先的保證Pod高可用的API對象。經過監控運行中的Pod來保證集羣中運行指定數目的Pod副本。指定的數目能夠是多個也能夠是1個;少於指定數目,RC就會啓動運行新的Pod副本;多於指定數目,RC就會殺死多餘的Pod副本。即便在指定數目爲1的狀況下,經過RC運行Pod也比直接運行Pod更明智,由於RC也能夠發揮它高可用的能力,保證永遠有1個Pod在運行。RC是K8s較早期的技術概念,只適用於長期伺服型的業務類型,好比控制小機器人提供高可用的Web服務。
(3)副本集(Replica Set,RS)
RS是新一代RC,提供一樣的高可用能力,區別主要在於RS後來居上,能支持更多種類的匹配模式。副本集對象通常不單獨使用,而是做爲Deployment的理想狀態參數使用。
(4)部署(Deployment)
部署表示用戶對K8s集羣的一次更新操做。部署是一個比RS應用模式更廣的API對象,能夠是建立一個新的服務,更新一個新的服務,也能夠是滾動升級一個服務。滾動升級一個服務,實際是建立一個新的RS,而後逐漸將新RS中副本數增長到理想狀態,將舊RS中的副本數減少到0的複合操做;這樣一個複合操做用一個RS是不太好描述的,因此用一個更通用的Deployment來描述。以K8s的發展方向,將來對全部長期伺服型的的業務的管理,都會經過Deployment來管理。
(5)服務(Service)
RC、RS和Deployment只是保證了支撐服務的微服務Pod的數量,可是沒有解決如何訪問這些服務的問題。一個Pod只是一個運行服務的實例,隨時可能在一個節點上中止,在另外一個節點以一個新的IP啓動一個新的Pod,所以不能以肯定的IP和端口號提供服務。要穩定地提供服務須要服務發現和負載均衡能力。服務發現完成的工做,是針對客戶端訪問的服務,找到對應的的後端服務實例。在K8s集羣中,客戶端須要訪問的服務就是Service對象。每一個Service會對應一個集羣內部有效的虛擬IP,集羣內部經過虛擬IP訪問一個服務。在K8s集羣中微服務的負載均衡是由Kube-proxy實現的。Kube-proxy是K8s集羣內部的負載均衡器。它是一個分佈式代理服務器,在K8s的每一個節點上都有一個;這一設計體現了它的伸縮性優點,須要訪問服務的節點越多,提供負載均衡能力的Kube-proxy就越多,高可用節點也隨之增多。與之相比,咱們平時在服務器端作個反向代理作負載均衡,還要進一步解決反向代理的負載均衡和高可用問題。
(6)任務(Job)
Job是K8s用來控制批處理型任務的API對象。批處理業務與長期伺服業務的主要區別是批處理業務的運行有頭有尾,而長期伺服業務在用戶不中止的狀況下永遠運行。Job管理的Pod根據用戶的設置把任務成功完成就自動退出了。成功完成的標誌根據不一樣的spec.completions策略而不一樣:單Pod型任務有一個Pod成功就標誌完成;定數成功型任務保證有N個任務所有成功;工做隊列型任務根據應用確認的全局成功而標誌成功。
(7)後臺支撐服務集(DaemonSet)
長期伺服型和批處理型服務的核心在業務應用,可能有些節點運行多個同類業務的Pod,有些節點上又沒有這類Pod運行;然後臺支撐型服務的核心關注點在K8s集羣中的節點(物理機或虛擬機),要保證每一個節點上都有一個此類Pod運行。節點多是全部集羣節點也多是經過nodeSelector選定的一些特定節點。典型的後臺支撐型服務包括,存儲,日誌和監控等在每一個節點上支持K8s集羣運行的服務。
(8)有狀態服務集(PetSet)
K8s在1.3版本里發佈了Alpha版的PetSet功能。在雲原生應用的體系裏,有下面兩組近義詞;第一組是無狀態(stateless)、牲畜(cattle)、無名(nameless)、可丟棄(disposable);第二組是有狀態(stateful)、寵物(pet)、有名(having name)、不可丟棄(non-disposable)。RC和RS主要是控制提供無狀態服務的,其所控制的Pod的名字是隨機設置的,一個Pod出故障了就被丟棄掉,在另外一個地方重啓一個新的Pod,名字變了、名字和啓動在哪兒都不重要,重要的只是Pod總數;而PetSet是用來控制有狀態服務,PetSet中的每一個Pod的名字都是事先肯定的,不能更改。PetSet中Pod的名字的做用,並非《千與千尋》的人性緣由,而是關聯與該Pod對應的狀態。
對於RC和RS中的Pod,通常不掛載存儲或者掛載共享存儲,保存的是全部Pod共享的狀態,Pod像牲畜同樣沒有分別(這彷佛也確實意味着失去了人性特徵);對於PetSet中的Pod,每一個Pod掛載本身獨立的存儲,若是一個Pod出現故障,從其餘節點啓動一個一樣名字的Pod,要掛載上原來Pod的存儲繼續以它的狀態提供服務。
適合於PetSet的業務包括數據庫服務MySQL和PostgreSQL,集羣化管理服務Zookeeper、etcd等有狀態服務。PetSet的另外一種典型應用場景是做爲一種比普通容器更穩定可靠的模擬虛擬機的機制。傳統的虛擬機正是一種有狀態的寵物,運維人員須要不斷地維護它,容器剛開始流行時,咱們用容器來模擬虛擬機使用,全部狀態都保存在容器裏,而這已被證實是很是不安全、不可靠的。使用PetSet,Pod仍然能夠經過漂移到不一樣節點提供高可用,而存儲也能夠經過外掛的存儲來提供高可靠性,PetSet作的只是將肯定的Pod與肯定的存儲關聯起來保證狀態的連續性。PetSet還只在Alpha階段,後面的設計如何演變,咱們還要繼續觀察。
(9)集羣聯邦(Federation)
K8s在1.3版本里發佈了beta版的Federation功能。在雲計算環境中,服務的做用距離範圍從近到遠通常能夠有:同主機(Host,Node)、跨主機同可用區(Available Zone)、跨可用區同地區(Region)、跨地區同服務商(Cloud Service Provider)、跨雲平臺。K8s的設計定位是單一集羣在同一個地域內,由於同一個地區的網絡性能才能知足K8s的調度和計算存儲鏈接要求。而聯合集羣服務就是爲提供跨Region跨服務商K8s集羣服務而設計的。
每一個K8s Federation有本身的分佈式存儲、API Server和Controller Manager。用戶能夠經過Federation的API Server註冊該Federation的成員K8s Cluster。當用戶經過Federation的API Server建立、更改API對象時,Federation API Server會在本身全部註冊的子K8s Cluster都建立一份對應的API對象。在提供業務請求服務時,K8s Federation會先在本身的各個子Cluster之間作負載均衡,而對於發送到某個具體K8s Cluster的業務請求,會依照這個K8s Cluster獨立提供服務時同樣的調度模式去作K8s Cluster內部的負載均衡。而Cluster之間的負載均衡是經過域名服務的負載均衡來實現的。
全部的設計都儘可能不影響K8s Cluster現有的工做機制,這樣對於每一個子K8s集羣來講,並不須要更外層的有一個K8s Federation,也就是意味着全部現有的K8s代碼和機制不須要由於Federation功能有任何變化。
(10)存儲卷(Volume)
K8s集羣中的存儲卷跟Docker的存儲卷有些相似,只不過Docker的存儲卷做用範圍爲一個容器,而K8s的存儲卷的生命週期和做用範圍是一個Pod。每一個Pod中聲明的存儲卷由Pod中的全部容器共享。K8s支持很是多的存儲卷類型,特別的,支持多種公有云平臺的存儲,包括AWS,Google和Azure雲;支持多種分佈式存儲包括GlusterFS和Ceph;也支持較容易使用的主機本地目錄hostPath和NFS。K8s還支持使用Persistent Volume Claim即PVC這種邏輯存儲,使用這種存儲,使得存儲的使用者能夠忽略後臺的實際存儲技術(例如AWS,Google或GlusterFS和Ceph),而將有關存儲實際技術的配置交給存儲管理員經過Persistent Volume來配置。
(11)持久存儲卷(Persistent Volume,PV)和持久存儲卷聲明(Persistent Volume Claim,PVC)
PV和PVC使得K8s集羣具有了存儲的邏輯抽象能力,使得在配置Pod的邏輯裏能夠忽略對實際後臺存儲技術的配置,而把這項配置的工做交給PV的配置者,即集羣的管理者。存儲的PV和PVC的這種關係,跟計算的Node和Pod的關係是很是相似的;PV和Node是資源的提供者,根據集羣的基礎設施變化而變化,由K8s集羣管理員配置;而PVC和Pod是資源的使用者,根據業務服務的需求變化而變化,有K8s集羣的使用者即服務的管理員來配置。
(12)節點(Node)
K8s集羣中的計算能力由Node提供,最初Node稱爲服務節點Minion,後來更名爲Node。K8s集羣中的Node也就等同於Mesos集羣中的Slave節點,是全部Pod運行所在的工做主機,能夠是物理機也能夠是虛擬機。不管是物理機仍是虛擬機,工做主機的統一特徵是上面要運行kubelet管理節點上運行的容器。
(13)密鑰對象(Secret)
Secret是用來保存和傳遞密碼、密鑰、認證憑證這些敏感信息的對象。使用Secret的好處是能夠避免把敏感信息明文寫在配置文件裏。在K8s集羣中配置和使用服務不可避免的要用到各類敏感信息實現登陸、認證等功能,例如訪問AWS存儲的用戶名密碼。爲了不將相似的敏感信息明文寫在全部須要使用的配置文件中,能夠將這些信息存入一個Secret對象,而在配置文件中經過Secret對象引用這些敏感信息。這種方式的好處包括:意圖明確,避免重複,減小暴漏機會。
(14)用戶賬戶(User Account)和服務賬戶(Service Account)
顧名思義,用戶賬戶爲人提供帳戶標識,而服務帳戶爲計算機進程和K8s集羣中運行的Pod提供帳戶標識。用戶賬戶和服務賬戶的一個區別是做用範圍;用戶賬戶對應的是人的身份,人的身份與服務的namespace無關,因此用戶帳戶是跨namespace的;而服務賬戶對應的是一個運行中程序的身份,與特定namespace是相關的。
(15)名稱空間(Namespace)
名稱空間爲K8s集羣提供虛擬的隔離做用,K8s集羣初始有兩個名字空間,分別是默認名稱空間default和系統名稱空間kube-system,除此之外,管理員能夠能夠建立新的名字空間知足須要。
(16)RBAC訪問受權
K8s在1.3版本中發佈了alpha版的基於角色的訪問控制(Role-based Access Control,RBAC)的受權模式。相對於基於屬性的訪問控制(Attribute-based Access Control,ABAC),RBAC主要是引入了角色(Role)和角色綁定(RoleBinding)的抽象概念。在ABAC中,K8s集羣中的訪問策略只能跟用戶直接關聯;而在RBAC中,訪問策略能夠跟某個角色關聯,具體的用戶在跟一個或多個角色相關聯。顯然,RBAC像其餘新功能同樣,每次引入新功能,都會引入新的API對象,從而引入新的概念抽象,而這一新的概念抽象必定會使集羣服務管理和使用更容易擴展和重用。
5.3 總結
從K8s的系統架構、技術概念和設計理念,咱們能夠看到K8s系統最核心的兩個設計理念:一個是容錯性,一個是易擴展性。容錯性實際是保證K8s系統穩定性和安全性的基礎,易擴展性是保證K8s對變動友好,能夠快速迭代增長新功能的基礎。