k8s基本概念
前期對springboot、springcloud的config、eruka、fein、hystrix以及docker都有了一定的瞭解,後邊想重點學習一下k8s,個人認為前邊這些最後再加上k8s才是微服務最好的實踐方案,這也是學習k8s的最初原因。對我來講學習一個新框架最重要的要知道這個東西,怎麼來的,是什麼,能幹什麼,核心有什麼,這篇部落格就是圍繞這這幾個點展開,幾乎全是概念性的東西,參考了很多人的部落格,在文末都有標註。
怎麼來的:
k8s是Kubernetes的縮寫,源自谷歌的Borg,Borg是谷歌公司的內部容器管理系統。Borg系統執行幾十萬個以上的任務,來自幾千個不同的應用,跨多個叢集,每個叢集(cell)有上萬個機器。它通過管理控制、高效的任務包裝、超售、和程序級別效能隔離實現了高利用率。它支援高可用性應用程式與執行時功能,最大限度地減少故障恢復時間,減少相關故障概率的排程策略。該專案的目的是實現資源管理的自動化以及跨多個資料中心的資源利用率最大化。Kubernetes專案的目的就是將Borg最精華的部分提取出來,使現在的開發者能夠更簡單、直接地應用。它以Borg為靈感,但又沒那麼複雜和功能全面,更強調了模組性和可理解性。
是什麼:
Kubernetes是谷歌的第三個容器管理系統(前兩個:Borg、Omega,這兩個是谷歌內部系統,k8s是開源的),Kubernetes在Docker技術之上,為容器化的應用提供了資源排程、部署執行、服務發現和擴容縮容等豐富多樣的功能。在專案公開後不久,微軟、IBM、VMware、Docker、CoreOS以及SaltStack等多家公司便紛紛加入了Kubernetes社群,為該專案發展作出貢獻。
能幹什麼:
自動化容器的部署和複製
隨時擴充套件或收縮容器規模
將容器組織成組,並且提供容器間的負載均衡
很容易地升級應用程式容器的新版本
提供容器彈性,如果容器失效就替換它
關於這一點可以參看
核心有什麼:
首先了解k8s的設計理念,這裡主要參考了k8s的中文社群的網站,k8s最核心的兩個設計理念是容錯性和易拓展性,容錯性實際是保證K8s系統穩定性和安全性的基礎,易擴充套件性是保證K8s對變更友好,可以快速迭代增加新功能的基礎。個人認為,為了達到上述的兩個設計理念,有了下邊6個控制機制的設計原則:
1、控制邏輯應該只依賴於當前狀態。這是為了保證分散式系統的穩定可靠,對於經常出現區域性錯誤的分散式系統,如果控制邏輯只依賴當前狀態,那麼就非常容易將一個暫時出現故障的系統恢復到正常狀態,因為你只要將該系統重置到某個穩定狀態,就可以自信的知道系統的所有控制邏輯會開始按照正常方式執行。
2、假設任何錯誤的可能,並做容錯處理。在一個分散式系統中出現區域性和臨時錯誤是大概率事件。錯誤可能來自於物理系統故障,外部系統故障也可能來自於系統自身的程式碼錯誤,依靠自己實現的程式碼不會出錯來保證系統穩定其實也是難以實現的,因此要設計對任何可能錯誤的容錯處理。
3、儘量避免複雜狀態機,控制邏輯不要依賴無法監控的內部狀態。因為分散式系統各個子系統都是不能嚴格通過程式內部保持同步的,所以如果兩個子系統的控制邏輯如果互相有影響,那麼子系統就一定要能互相訪問到影響控制邏輯的狀態,否則,就等同於系統裡存在不確定的控制邏輯。
4、假設任何操作都可能被任何操作物件拒絕,甚至被錯誤解析。由於分散式系統的複雜性以及各子系統的相對獨立性,不同子系統經常來自不同的開發團隊,所以不能奢望任何操作被另一個子系統以正確的方式處理,要保證出現錯誤的時候,操作級別的錯誤不會影響到系統穩定性。
5、每個模組都可以在出錯後自動恢復。由於分散式系統中無法保證系統各個模組是始終連線的,因此每個模組要有自我修復的能力,保證不會因為連線不到其他模組而自我崩潰。
6、每個模組都可以在必要時優雅地降級服務。所謂優雅地降級服務,是對系統魯棒性的要求,即要求在設計實現模組時劃分清楚基本功能和高階功能,保證基本功能不會依賴高階功能,這樣同時就保證了不會因為高階功能出現故障而導致整個模組崩潰。根據這種理念實現的系統,也更容易快速地增加新的高階功能,以為不必擔心引入高階功能影響原有的基本功能。
k8s這個容器管理系統根據以上的控制原則設計完成之後就要被使用,使用的話就是通過API的方式,這裡也列出8條API的設計原則:
1、所有API應該是宣告式的。正如前文所說,宣告式的操作,相對於命令式操作,對於重複操作的效果是穩定的,這對於容易出現數據丟失或重複的分散式環境來說是很重要的。另外,宣告式操作更容易被使用者使用,可以使系統向用戶隱藏實現的細節,隱藏實現的細節的同時,也就保留了系統未來持續優化的可能性。此外,宣告式的API,同時隱含了所有的API物件都是名詞性質的,例如Service、Volume這些API都是名詞,這些名詞描述了使用者所期望得到的一個目標分散式物件。
2、API物件是彼此互補而且可組合的。這裡面實際是鼓勵API物件儘量實現面向物件設計時的要求,即“高內聚,鬆耦合”,對業務相關的概念有一個合適的分解,提高分解出來的物件的可重用性。事實上,K8s這種分散式系統管理平臺,也是一種業務系統,只不過它的業務就是排程和管理容器服務。
3、高層API以操作意圖為基礎設計。如何能夠設計好API,跟如何能用面向物件的方法設計好應用系統有相通的地方,高層設計一定是從業務出發,而不是過早的從技術實現出發。因此,針對K8s的高層API設計,一定是以K8s的業務為基礎出發,也就是以系統排程管理容器的操作意圖為基礎設計。
4、低層API根據高層API的控制需要設計。設計實現低層API的目的,是為了被高層API使用,考慮減少冗餘、提高重用性的目的,低層API的設計也要以需求為基礎,要儘量抵抗受技術實現影響的誘惑。
5、儘量避免簡單封裝,不要有在外部API無法顯式知道的內部隱藏的機制。簡單的封裝,實際沒有提供新的功能,反而增加了對所封裝API的依賴性。內部隱藏的機制也是非常不利於系統維護的設計方式,例如PetSet和ReplicaSet,本來就是兩種Pod集合,那麼K8s就用不同API物件來定義它們,而不會說只用同一個ReplicaSet,內部通過特殊的演算法再來區分這個ReplicaSet是有狀態的還是無狀態。
6、API操作複雜度與物件數量成正比。這一條主要是從系統性能角度考慮,要保證整個系統隨著系統規模的擴大,效能不會迅速變慢到無法使用,那麼最低的限定就是API的操作複雜度不能超過O(N),N是物件的數量,否則系統就不具備水平伸縮性了。
7、API物件狀態不能依賴於網路連線狀態。由於眾所周知,在分散式環境下,網路連線斷開是經常發生的事情,因此要保證API物件狀態能應對網路的不穩定,API物件的狀態就不能依賴於網路連線狀態。
8、儘量避免讓操作機制依賴於全域性狀態,因為在分散式系統中要保證全域性狀態的同步是非常困難的。
根據k8s的設計理念、控制原則、API的設計原則,設計完之後的系統的樣子,可以通過下邊的架構圖瞭解。
或者可以看一個更高層次的抽象,會更容易理解一些
k8s的重要的東西就可以在上邊的架構圖中看出來了,首先從整體上對架構圖進行一個描述,Master和Node:Kubernetes將叢集中的機器劃分為一個Master節點和一群工作節點(Node)。其中,Master節點上執行著叢集管理相關的一組程序etcd、API Server、Controller Manager、Scheduler,後三個元件構成了Kubernetes的總控中心,這些程序實現了整個叢集的資源管理、Pod排程、彈性伸縮、安全控制、系統監控和糾錯等管理功能,並且全都是自動完成。在每個Node上執行Kubelet、Proxy、Docker daemon三個元件,負責對本節點上的Pod的生命週期進行管理,以及實現服務代理的功能。下邊對一些重要的概念進行敘述,k8s既然是容器管理系統,就先從容器相關的概念開始:
pod:從上邊的架構圖中,我們可以看到pod是執行在docker之上的,在 kubernetes 的設計中,最基本的管理單位是 pod,而不是 container。pod 是 kubernetes 在容器上的一層封裝,由一組執行在同一主機的一個或者多個容器組成。如果把容器比喻成傳統機器上的一個程序(它可以執行任務,對外提供某種功能),那麼 pod 可以類比為傳統的主機:它包含了多個容器,為它們提供共享的一些資源。Pod包含一個或者多個相關的容器,Pod可以認為是容器的一種延伸擴充套件,一個Pod也是一個隔離體,而Pod內部包含的一組容器又是共享的(包括PID、Network、IPC、UTS)。除此之外,Pod中的容器可以訪問共同的資料捲來實現檔案系統的共享。
通過下邊這個豆莢的圖我們可以看出來pod和container的關係
通過下邊這個圖可以看到pod的幾種形式,以及通過加捲的方式共享資料方式
Node:Node是Kubernetes中的工作節點,最開始被稱為minion。一個Node可以是VM或物理機。每個Node(節點)具有執行pod的一些必要服務,並由Master元件進行管理,Node節點上的服務包括Docker、kubelet和kube-proxy。目前Kubernetes支援docker和rkt兩種容器
通過下邊這個圖可以更清晰的看出來node和pod的關係
kubelet:在每個節點(node)上都要執行一個 worker 對容器進行生命週期的管理,這個 worker 程式就是kubelet。kubelet的主要功能就是定時從某個地方獲取節點上 pod/container 的期望狀態(執行什麼容器、執行的副本數量、網路或者儲存如何配置等等),並呼叫對應的容器平臺介面達到這個狀態。kubelet 還要檢視容器是否正常執行,如果容器執行出錯,就要根據設定的重啟策略進行處理。kubelet 還有一個重要的責任,就是監控所在節點的資源使用情況,並定時向 master 報告。知道整個叢集所有節點的資源情況,對於 pod 的排程和正常執行至關重要。
kube-proxy:每個節點(node)都有一個元件kube-proxy,實際上是為service服務的,通過kube-proxy,實現流量從service到pod的轉發,它負責TCP和UDP資料包的網路路由,kube-proxy也可以實現簡單的負載均衡功能。其實就是管理service的訪問入口,包括叢集內Pod到Service的訪問和叢集外訪問service。 kube-proxy管理sevice的Endpoints,該service對外暴露一個Virtual IP,也成為Cluster IP, 叢集內通過訪問這個Cluster IP:Port就能訪問到叢集內對應的serivce下的Pod。
Service:個人認為這是k8s重要性僅次於pod的概念,眾所周知,pod生命週期短,狀態不穩定,pod異常後新生成的pod ip會發生變化,之前pod的訪問方式均不可達。通過service對pod做代理,service有固定的ip和port,ip:port組合自動關聯後端pod,即使pod發生改變,kubernetes內部更新這組關聯關係,使得service能夠匹配到新的pod。這樣,通過service提供的固定ip,使用者再也不用關心需要訪問哪個pod,以及pod是否發生改變,大大提高了服務質量。如果pod使用rc建立了多個副本,那麼service就能代理多個相同的pod,所以service可以認為是一組pod的代理或者是更高層的抽象,其他的service通過本service提供的虛擬IP進行訪問,也可以在service中對代理的一組pod提供負載服務。
通過這個圖片可以看到Service和pod的關係
下邊這個圖從更整體的角度理解Service
下邊這個動圖展示了Service的執行過程,也解釋了kube-proxy時如何實現Service的負載的。
現在,假定有2個後臺Pod,並且定義後臺Service的名稱為‘backend-service’,lable選擇器為(tier=backend, app=myapp)。backend-service 的Service會完成如下兩件重要的事情:會為Service建立一個本地叢集的DNS入口,因此前端(frontend)Pod只需要DNS查詢主機名為 ‘backend-service’,就能夠解析出前端應用程式可用的IP地址。現在前端已經得到了後臺服務的IP地址,但是它應該訪問2個後臺Pod的哪一個呢?Service在這2個後臺Pod之間提供透明的負載均衡,會將請求分發給其中的任意一個(如下面的動畫所示)。通過每個Node上執行的代理(kube-proxy)完成。
Virtual IP:k8s分配給Service一個固定IP,這是一個虛擬IP(也稱為ClusterIP),並不是一個真實存在的IP,無法被ping,沒有實體網路物件來響應,是由k8s虛擬出來的。虛擬IP的範圍通過k8s API Server的啟動引數 --service-cluster-ip-range=19.254.0.0/16配置;虛擬IP屬於k8s內部的虛擬網路,外部是定址不到的。在k8s系統中,實際上是由k8s Proxy元件負責實現虛擬IP路由和轉發的,所以k8s Node中都必須運行了k8s Proxy,從而在容器覆蓋網路之上又實現了k8s層級的虛擬轉發網路
Endpoint:每個pod都提供了一個獨立的Endpoint( Pod ip + Container port )以被客戶端訪問
Endpoints:當有連線通過ClusterIP 到達Service的時候,service將根據endpoints提供的資訊進行路由請求pod,Endpoints的變化可以通過k8s中的selectors手動或自動的被發現
Label:Label機制是Kubernetes中的一個重要設計,通過Label進行物件的弱關聯,可以靈活地進行分類和選擇,Label是識別Kubernetes物件(Pod、Service、RC、Node)的標籤,以key/value的方式附加到物件上,Label不提供唯一性,比如可以關聯Service和Pod。Label定義好後其他物件可以使用Label Selector來選擇一組相同label的物件。
Advisor:Google的cAdvisor(Container Advisor)“為容器使用者提供了了解執行時容器資源使用和效能特徵的方法”。cAdvisor的容器抽象基於Google的lmctfy容器棧,因此原生支援Docker容器並能夠“開箱即用”地支援其他的容器型別。cAdvisor部署為一個執行中的daemon,它會收集、聚集、處理並匯出執行中容器的資訊。這些資訊能夠包含容器級別的資源隔離引數、資源的歷史使用狀況、反映資源使用和網路統計資料完整歷史狀況的柱狀圖。
以上是node相關的一些概念的解釋,從pod開始,根據關聯性順次解釋,下邊對master中的一些概念進行解讀:
master:master節點負責管理整個k8s叢集,這是所有管理任務的入口,master節點負責編排工作node。
Controller Manager作為叢集內部的管理控制中心,負責叢集內的Node、Pod副本、服務端點(Endpoint)、名稱空間(Namespace)、服務賬號(ServiceAccount)、資源定額(ResourceQuota)的管理,當某個Node意外宕機時,Controller Manager會及時發現並執行自動化修復流程,確保叢集始終處於預期的工作狀態。如果說APIServer做的是“前臺”的工作的話,那controller manager就是負責“後臺”的。每個資源一般都對應有一個控制器,而controller manager就是負責管理這些控制器的。比如我們通過APIServer建立一個pod,當這個pod建立成功後,APIServer的任務就算完成了。而後面保證Pod的狀態始終和我們預期的一樣的重任就由controller manager去保證了。
下圖有一個很好的概括
Replication Controller(RC):是Kubernetes中的另一個核心概念,它的職責是確保叢集中有且僅有N個Pod例項,N是RC中定義的Pod副本數量。通過調整RC中的spec.replicas屬性值來實現系統擴容或縮容。通過改變RC中的Pod模板來實現系統的滾動升級。
下邊是RC執行過程中一個常見的動圖:
Replication Controller確保任意時間都有指定數量的Pod“副本”在執行。如果為某個Pod建立了Replication Controller並且指定3個副本,它會建立3個Pod,並且持續監控它們。如果某個Pod不響應,那麼Replication Controller會替換它,保持總數為3.如果之前不響應的Pod恢復了,現在就有4個Pod了,那麼Replication Controller會將其中一個終止保持總數為3。如果在執行中將副本總數改為5,Replication Controller會立刻啟動2個新Pod,保證總數為5。
Node Controller:負責發現、管理和監控叢集中的各個Node節點。
Endpoint Controller:定期關聯service和pod(關聯資訊由endpoint物件維護),保證service到pod的對映總是最新的。
Scheduler:scheduler的職責很明確,就是負責排程pod到合適的Node上。如果把scheduler看成一個黑匣子,那麼它的輸入是pod和由多個Node組成的列表,輸出是Pod和一個Node的繫結,即將這個pod部署到這個Node上。Kubernetes目前提供了排程演算法,但是同樣也保留了介面,使用者可以根據自己的需求定義自己的排程演算法。
etcd:etcd是一個高可用的鍵值儲存系統,Kubernetes使用它來儲存各個資源的狀態,從而實現了Restful的API。
API Server:APIServer負責對外提供RESTful的Kubernetes API服務,它是系統管理指令的統一入口,任何對資源進行增刪改查的操作都要交給APIServer處理後再提交給etcd。如架構圖中所示,kubectl(Kubernetes提供的客戶端工具,該工具內部就是對Kubernetes API的呼叫)是直接和APIServer互動的。只有API Server與儲存通訊,其他模組通過API Server訪問叢集狀態。這樣第一,是為了保證叢集狀態訪問的安全。第二,是為了隔離叢集狀態訪問的方式和後端儲存實現的方式:API Server是狀態訪問的方式,不會因為後端儲存技術etcd的改變而改變。加入以後將etcd更換成其他的儲存方式,並不會影響依賴依賴API Server的其他K8s系統模組。
參考的文章的列表:
https://jimmysong.io/kubernetes-handbook/concepts/
http://blog.csdn.net/liyingke112/article/details/76022267
http://m635674608.iteye.com/blog/2360095
http://itindex.net/detail/57343-kube-proxy-%E5%A4%96%E9%83%A8
https://www.cnblogs.com/junneyang/p/6274689.html
https://www.cnblogs.com/zhenyuyaodidiao/p/6500720.html
https://www.cnblogs.com/menkeyi/p/7134460.html
https://www.jianshu.com/p/0a656b3d94b2
http://blog.csdn.net/qq_35254726/article/details/54233781
http://www.dockone.io/article/932
http://www.infoq.com/cn/news/2015/05/Kubernetes-Borg-Eurosys/
https://www.kubernetes.org.cn/1613.html
https://x-team.com/blog/introduction-kubernetes-architecture/
https://www.ctolib.com/docs/sfile/kubernetes-handbook/introduction/concepts.html
https://www.quora.com/What-is-an-endpoint-object-in-terms-of-Kubernetes
http://blog.csdn.net/huwh_/article/details/75675761
http://blog.csdn.net/horsefoot/article/details/52221706