一篇文章學會什么是Kubernetes
什么是Kubernetes?
Borg系統是谷歌內部使用很多的容器管理系統,在早期是采用Chroot Jail實現安全隔離,后期采用Namespace,資源隔離是采用CGroup實現。
為什么谷歌要推出Kubernetes開源版本呢?我個人的理解是:
- 使用開源社區的力量來解決谷歌未解決的問題
- 在云原生領域分一杯羹
- 推動云原生的發展,畢竟谷歌在容器領域已經玩了許多年了
Kubernetes具有以下特點:
- ?便攜性: 無論公有云、私有云、混合云還是多云架構都全面支持
- 可擴展: 它是模塊化、可插拔、可掛載、可組合的,支持各種形式的擴展
- 自修復: 它可以自保持應用狀態、可自重啟、自復制、自縮放的,通過聲明式語法提供了強大的自修復能力
使用 Kubernetes, 您可以快速高效地響應客戶需求:
- 快速、可預測地部署您的應用程序
- 擁有即時擴展應用程序的能力
- 不影響現有業務的情況下,無縫地發布新功能
- 優化硬件資源,降低成本
Kubernetes是一個聲明式系統,聲明式系統和命令式系統?是有本質的區別。所謂聲明式系統?關注點是做什么,即告訴你將要達成什么樣的期望,至于怎么達到是你系統的事情。而命令式系統則是必須按照相應的規定或者步驟達到某個目標或者完成某個任務,其關注點是在怎么做。
命令式強調的是How,它需要你通過step-by-step的方式告訴計算機如何完成一個任務,在這種場景下,計算機是不具備“智能”,智能很機械的完成任務,至于完成的結果如何,需要看編程者的水平了。
而聲明式強調的是What,你只需要告訴計算機你想要什么,然后由計算機自己去執行,這時候的計算機是具備一定的“智能”。當然,聲明式不一定會滿足你所有的需要。
在日常工作中,命令式編程比較普遍,這種編程實現比較方便,只需要按照一定的步驟開發即可,但是在一些特定的場合,聲明式要比命令式方便,其實大多數聲明式語言都是針對特定任務的領域專用語言,即DSL。
最常見的聲明式語言就是SQL,只需要告訴計算機你想要的結果集,數據庫就會幫你設計獲取這個結果集的執行路徑,并返回結果。
Kubernetes就是一個聲明式系統,在使用Kubernetes的時候,用戶不需要去定義A->B->C這種Workflow,而是直接去描述一個期望狀態,然后Kubernetes就會幫助用戶達到這個狀態,至于如何達到這個狀態,用戶不需要關心。這種設計使得Kubernetes更加易用和健壯,也更具彈性和擴展性。
Kubernetes的架構
Kubernetes整體是Master-Slave架構,如下:
其中:
- etcd 保存了整個集群的狀態,就是一個數據庫,只有API Server能與其通信;
- apiserver 提供了資源操作的唯一入口,并提供認證、授權、訪問控制、API 注冊和發現等機制;
- controller manager 負責維護集群的狀態,比如故障檢測、自動擴展、滾動更新等;
- scheduler 負責資源的調度,按照預定的調度策略將 Pod 調度到相應的機器上;
- kubelet 負責維護容器的生命周期,同時也負責 Volume(CSI)和網絡(CNI)的管理;
- container runtime 負責鏡像管理以及 Pod 和容器的真正運行(CRI);
- kube-proxy 負責為 Service 提供 cluster 內部的服務發現和負載均衡;
- registry是鏡像倉庫,負責存儲容器鏡像
- kubectl和dashboard都是客戶端工具
上面的架構是邏輯架構,在實際的生產運用中,為了達到高可用,會對架構做對應的調整,調整對象就是主節點,如下:
主要做了以下改變:
(1)將Master節點從單節點變成了多節點,在kube-apiserver前增加了load balancer用來負載,其他組件通信都是通過LB進行
(2)將etcd和master節點獨立開,避免由于某個master節點故障導致ectd受影響
Kubernetes架構的設計原則是:
- 只有APIServer可以直接訪問Etcd存儲,其他服務必須通過Kubernetes API來訪問集群的狀態
- 單節點故障原則上不應該影響集群的狀態
- 在沒有新請求的情況下,所有組件應該在故障恢復后繼續執行上次最后收到的請求
- 所有組件應該在內存中保持所需要的狀態,APIServer將狀態寫入Etcd存儲,而其他組件則通過APIServer更新并監聽所有的變化,最終由Controller Manager去協調
- 優先使用事件監聽而不是輪詢
Kubernetes的重要組件
上面介紹了Kubernetes的整體架構以及簡單介紹了各個組件的作用,但是它們之間的關系具體如何并沒有做過多的介紹,我們現在來看看各個組件以及它們之間是怎么協作的。
(1)kubectl 客戶端首先將CLI命令轉化為RESTful的API調用,然后發送到kube-apiserver。
(2)kube-apiserver 在認證、授權、準入驗證過后,將任務元信息并存儲到etcd,然后kube-scheduler會對任務進行調度,并將調度結果返回給kube-apiserver。
(3)一旦 kube-scheduler 返回一個適合調度的目標節點后,kube-apiserver 就把任務的節點信息存入etcd,并創建任務。
(4)此時目標節點中的 kubelet正監聽apiserver,當監聽到有新任務需要調度到本節點后,kubelet通過本地runtime創建任務容器,執行作業。
(5)接著kubelet將任務狀態等信息返回給apiserver存儲到etcd。
(6)kube-proxy也會監聽apiserver,如果有網絡策略相關的操作,就會在本機上創建對應的iptables或者ipvs規則。
(7)這樣我們的任務已經在運行了,此時control-manager發揮作用保證任務一直是我們期望的狀態。
其主要組件如下:
- Etcd
- API Server
- Controller Manager
- Scheduler
- Kubelet
- Kube-proxy
Etcd
Etcd 是兼具一致性和高可用性的鍵值存儲,可用于服務發現、共享配置以及一致性保障,在Kubernetes中,Etcd是作為唯一的存儲,保存Kubernetes的所有API對象。
在生產級Kubernetes中etcd通常會以集群的方式存在,安全原因,它只能從 API 服務器訪問。
API Server
API Server是Kubernetes最重要的核心組件之一,主要提供以下功能:
- 提供集群管理的REST API接口,包括:
- 認證
- 授權
- 準入
- 為其他模塊提供數據交互和通信的樞紐
- API Server提供Etcd的數據緩存,減少集群對Etcd的訪問
Controller Manager
Kubernetes在后臺運行許多不同的控制器進程,當服務配置發生更改時(例如,替換運行 pod 的鏡像,或更改配置 yaml 文件中的參數),控制器會發現更改并開始朝著新的期望狀態工作。
從邏輯上講,每個控制器都是一個單獨的進程, 但是為了降低復雜性,它們都被編譯到同一個可執行文件,并在一個進程中運行。控制器包括:
- 節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應
- 任務控制器(Job controller): 監測代表一次性任務的 Job 對象,然后創建 Pods 來運行這些任務直至完成
- 端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)
- 服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創建默認帳戶和 API 訪問令牌
下面就是Deployment Controller和ReplicaSet Controller兩個控制器的工作流程。
Scheduler
kube-scheduler 負責監視新創建、未指定運行Node的 Pods,決策出一個讓pod運行的節點。例如,如果應用程序需要 1GB 內存和 2 個 CPU 內核,那么該應用程序的 pod 將被安排在至少具有這些資源的節點上。每次需要調度 pod 時,調度程序都會運行。調度程序必須知道可用的總資源以及分配給每個節點上現有工作負載的資源。調度決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬件/軟件/策略約束、親和性和反親和性規范、數據位置、工作負載間的干擾和最后時限。
調度總共分為三個階段:
- Predict:預選階段,過濾不能滿足業務需求的節點
- Priority:優選階段,選擇最優的節點
- Bind:綁定階段,將最優節點和Pod進行綁定,完成調度
Kubelet
Kubelet是每個節點上的核心組件之一,負責管理節點的資源對象。
- 從不同源獲取Pod清單,并按需啟停Pod
Pod清單可以來自本地文件目錄、給定的Http Server、API Server等
Kubelet將Container Runtime、Network、Stroage抽象成CRI、CNI、CSI
- 負責匯報節點的健康狀態以及資源信息
- 負責Pod的健康檢查和狀態匯報
Kube-proxy
kube-proxy 是集群中每個節點上運行的網絡代理, 實現 Kubernetes 服務(Service) 概念的一部分。用于處理單個主機子網劃分并向外部世界公開服務。它跨集群中的各種隔離網絡將請求轉發到正確的 pod/容器。kube-proxy 維護節點上的網絡規則。這些網絡規則允許從集群內部或外部的網絡會話與 Pod 進行網絡通信。如果操作系統提供了數據包過濾層并可用的話,kube-proxy 會通過它來實現網絡規則。否則, kube-proxy 僅轉發流量本身。
其他組件
上面介紹的這些組件是集群的架子,光有架子還不夠,還需要第三方的組件讓其更強大:
- kube-dns:負責為整個集群提供DNS服務,常用的是CoreDNS
- Ingress Controller:為集群提供外網訪問入口
- Metrics-Server:為集群提供監控資源
- DashBoard:提供GUI,方便運維
- Prometheus:收集并監控集群資源
- Grafana:圖形化展示監控數據
- ELK:收集、存儲、查詢集群日志