Kubernetes學習之路(二十)之K8S組件運行原理詳解總結

轉自:https://www.cnblogs.com/linuxk/p/10291178.html

一、看圖說K8S

先從一張大圖來觀看一下K8S是如何運作的,再具體去細化K8S的概念、組件以及網絡模型。

從上圖,我們可以看到K8S組件和邏輯及其複雜,但是這並不可怕,我們從宏觀上先了解K8S是怎麼用的,再進行庖丁解牛。從上圖我們可以看出:

  • Kubernetes集羣主要由Master和Node兩類節點組成
  • Master的組件包括:apiserver、controller-manager、scheduler和etcd等幾個組件,其中apiserver是整個集羣的網關。
  • Node主要由kubelet、kube-proxy、docker引擎等組件組成。kubelet是K8S集羣的工作與節點上的代理組件。
  • 一個完整的K8S集羣,還包括CoreDNS、Prometheus(或HeapSter)、Dashboard、Ingress Controller等幾個附加組件。其中cAdivsor組件作用於各個節點(master和node節點)之上,用於收集及收集容器及節點的CPU、內存以及磁盤資源的利用率指標數據,這些統計數據由Heapster聚合後,可以通過apiserver訪問。

要了解K8S的所有組件,沒去走一遍,永遠不知道它是怎麼跑起來的,那麼下面就帶着幾個新手疑問來看K8S

  • 1、K8S是如何對容器編排?

在K8S集羣中,容器並非最小的單位,K8S集羣中最小的調度單位是Pod,容器則被封裝在Pod之中。由此可知,一個容器或多個容器可以同屬於在一個Pod之中。

  • 2、Pod是怎麼創建出來的?

Pod並不是無緣無故跑出來的,它是一個抽象的l邏輯概念,那麼Pod是如何創建的呢?Pod是由Pod控制器進行管理控制,其代表性的Pod控制器有Deployment、StatefulSet等。這裏我們先有這樣的一個概念,後面再詳細解刨。

  • 3、Pod資源組成的應用如何提供外部訪問的?

Pod組成的應用是通過Service這類抽象資源提供內部和外部訪問的,但是service的外部訪問需要端口的映射,帶來的是端口映射的麻煩和操作的繁瑣。爲此還有一種提供外部訪問的資源叫做Ingress。

  • 4、Service又是怎麼關聯到Pod呢?

在上面說的Pod是由Pod控制器進行管理控制,對Pod資源對象的期望狀態進行自動管理。而在Pod控制器是通過一個YAML的文件進行定義Pod資源對象的。在該文件中,還會對Pod資源對象進行打標籤,用於Pod的辨識,而Servcie就是通過標籤選擇器,關聯至同一標籤類型的Pod資源對象。這樣就實現了從service-->pod-->container的一個過程。

  • 5、Pod的怎麼創建邏輯流程是怎樣的?
  • (1)客戶端提交創建請求,可以通過API Server的Restful API,也可以使用kubectl命令行工具。支持的數據類型包括JSON和YAML。
  • (2)API Server處理用戶請求,存儲Pod數據到etcd。
  • (3)調度器通過API Server查看未綁定的Pod。嘗試爲Pod分配主機。
  • (4)過濾主機 (調度預選):調度器用一組規則過濾掉不符合要求的主機。比如Pod指定了所需要的資源量,那麼可用資源比Pod需要的資源量少的主機會被過濾掉。
  • (5)主機打分(調度優選):對第一步篩選出的符合要求的主機進行打分,在主機打分階段,調度器會考慮一些整體優化策略,比如把容一個Replication Controller的副本分佈到不同的主機上,使用最低負載的主機等。
  • (6)選擇主機:選擇打分最高的主機,進行binding操作,結果存儲到etcd中。
  • (7)kubelet根據調度結果執行Pod創建操作: 綁定成功後,scheduler會調用APIServer的API在etcd中創建一個boundpod對象,描述在一個工作節點上綁定運行的所有pod信息。運行在每個工作節點上的kubelet也會定期與etcd同步boundpod信息,一旦發現應該在該工作節點上運行的boundpod對象沒有更新,則調用Docker API創建並啓動pod內的容器。

從上面的幾個疑問,大致瞭解了K8S怎麼工作的,那麼現在再從三個面去了解Kubernetes,分別是Kubernetes概念和術語、集羣組件、網絡模型。

二、K8S的概念和術語

​ Kubernetes是利用共享網絡將多個物理機或者虛擬機組成一個集羣,在各個服務器之間進行通信,該集羣是配置Kubernetes的所有租金啊啊、功能和負載的物理平臺。

​ 一個Kubernetes集羣由master和node組成。如下圖:

  • Master:是集羣的網關和中樞樞紐,主要作用:暴露API接口,跟蹤其他服務器的健康狀態、以最優方式調度負載,以及編排其他組件之間的通信。單個的Master節點可以完成所有的功能,但是考慮單點故障的痛點,生產環境中通常要部署多個Master節點,組成Cluster。
  • Node:是Kubernetes的工作節點,負責接收來自Master的工作指令,並根據指令相應地創建和銷燬Pod對象,以及調整網絡規則進行合理路由和流量轉發。生產環境中,Node節點可以有N個。

img

Kubernetes從宏觀上看分爲2個角色:Master和Node,但是在Master節點和Node節點上都存在着多個組件來支持內部的業務邏輯,其包括:運行應用、應用編排、服務暴露、應用恢復等等,在Kubernetes中這些概念被抽象爲Pod、Service、Controller等資源類型。先來了解一下這些常用概念和術語:

  • (1)Pod

    從上圖,我們可以看到K8S並不直接地運行容器,而是被一個抽象的資源對象--Pod所封裝,它是K8S最小的調度單位。這裏要注意的是,Pod可以封裝一個活多個容器!同一個Pod中共享網絡名稱空間和存儲資源,而容器之間可以通過本地迴環接口:lo 直接通信,但是彼此之間又在Mount、User和Pid等名稱空間上保持了隔離。

  • (2)資源標籤(Label)

    標籤(Label)是將資源進行分類的標識符,就好像超市的商品分類一般。資源標籤具體化的就是一個鍵值型(key/values)數據,相信瞭解redis的友友應該知道什麼是鍵值數據。使用標籤是爲了對指定對象進行辨識,比如Pod對象。標籤可以在對象創建時進行附加,也可以創建後進行添加或修改。要知道的是一個對象可以有多個標籤,一個標籤頁可以附加到多個對象。如圖:

  • (3)標籤選擇器(Selector)

    有標籤,當然就有標籤選擇器,它是根據Label進行過濾符合條件的資源對象的一種 機制。比如將含有標籤role: backend的所有Pod對象挑選出來歸併爲一組。通常在使用過程中,會通過標籤對資源對象進行分類,然後再通過標籤選擇器進行篩選,最常見的應用就是講一組這樣的Pod資源對象創建爲某個Service的端點。如圖:

  • (4)Pod控制器(Controller)

    雖然Pod是K8S的最小調度單位,但是K8S並不會直接地部署和管理Pod對象,而是要藉助於另外一個抽象資源--Controller進行管理。其實一種管理Pod生命週期的資源抽象,並且它是一類對象,並非單個的資源對象,其中包括:ReplicationController、ReplicaSet、Deployment、StatefulSet、Job等。

    以Deployment爲例,它負責確保定義的Pod對象的副本數量符合預期的設置,這樣用戶只需要聲明應用的期望狀態,控制器就會自動地對其進行管理。如圖:

  • (5)服務資源(Service)

Service是建立在一組Pod對象之上的資源對象,在前面提過,它是通過標籤選擇器選擇一組Pod對象,併爲這組Pod對象定義一個統一的固定訪問入口(通常是一個IP地址),如果K8S存在DNS附件(如coredns)它就會在Service創建時爲它自動配置一個DNS名稱,用於客戶端進行服務發現。

通常我們直接請求Service IP,該請求就會被負載均衡到後端的端點,即各個Pod對象,從這點上,是不是有點像負載均衡器呢,因此Service本質上是一個4層的代理服務,另外Service還可以將集羣外部流量引入至集羣,這就需要節點對Service的端口進行映射了。

  • (6)存儲卷(Volume)

在使用容器時,我們知道,當數據存放於容器之中,容器銷燬後,數據也會隨之丟失。這就是需要一個外部存儲,以保證數據的持久化存儲。而存儲卷就是這樣的一個東西。

存儲卷(Volume)是獨立於容器文件系統之外的存儲空間,常用於擴展容器的存儲空間併爲其提供持久存儲能力。存儲卷在K8S中的分類爲:臨時卷、本地卷和網絡卷。臨時卷和本地卷都位於Node本地,一旦Pod被調度至其他Node節點,此類型的存儲卷將無法被訪問,因爲臨時卷和本地卷通常用於數據緩存,持久化的數據通常放置於持久卷(persistent volume)之中。

  • (7)Name和Namespace

名稱(Name)是K8S集羣中資源對象的標識符,通常作用於名稱空間(Namespace),因此名稱空間是名稱的額外的限定機制。在同一個名稱空間中,同一類型資源對象的名稱必須具有唯一性。

名稱空間通常用於實現租戶或項目的資源隔離,從而形成邏輯分組。關於此概念可以參考:https://www.jb51.net/article/136411.htm

如圖:創建的Pod和Service等資源對象都屬於名稱空間級別,未指定時,都屬於默認的名稱空間default

  • (8)註解(Annotation)

Annotation是另一種附加在對象上的一種鍵值類型的數據,常用於將各種非標識型元數據(metadata)附加到對象上,但它並不能用於標識和選擇對象。其作用是方便工具或用戶閱讀及查找。

  • (9)Ingress

K8S將Pod對象和外部的網絡環境進行了隔離,Pod和Service等對象之間的通信需要通過內部的專用地址進行,如果需要將某些Pod對象提供給外部用戶訪問,則需要給這些Pod對象打開一個端口進行引入外部流量,除了Service以外,Ingress也是實現提供外部訪問的一種方式。

三、K8S集羣組件

1、Master組件

  • 1、API Server

K8S對外的唯一接口,提供HTTP/HTTPS RESTful API,即kubernetes API。所有的請求都需要經過這個接口進行通信。主要負責接收、校驗並響應所有的REST請求,結果狀態被持久存儲在etcd當中,所有資源增刪改查的唯一入口。

  • 2、etcd

負責保存k8s 集羣的配置信息和各種資源的狀態信息,當數據發生變化時,etcd會快速地通知k8s相關組件。etcd是一個獨立的服務組件,並不隸屬於K8S集羣。生產環境當中etcd應該以集羣方式運行,以確保服務的可用性。

etcd不僅僅用於提供鍵值數據存儲,而且還爲其提供了監聽(watch)機制,用於監聽和推送變更。在K8S集羣系統中,etcd的鍵值發生變化會通知倒API Server,並由其通過watch API向客戶端輸出。

  • 3、Controller Manager

負責管理集羣各種資源,保證資源處於預期的狀態。Controller Manager由多種controller組成,包括replication controller、endpoints controller、namespace controller、serviceaccounts controller等 。由控制器完成的主要功能主要包括生命週期功能和API業務邏輯,具體如下:

  • 生命週期功能:包括Namespace創建和生命週期、Event垃圾回收、Pod終止相關的垃圾回收、級聯垃圾回收及Node垃圾回收等。
  • API業務邏輯:例如,由ReplicaSet執行的Pod擴展等。
  • 4、調度器(Schedule)

資源調度,負責決定將Pod放到哪個Node上運行。Scheduler在調度時會對集羣的結構進行分析,當前各個節點的負載,以及應用對高可用、性能等方面的需求。

2、Node組件

Node主要負責提供容器的各種依賴環境,並接受Master管理。每個Node有以下幾個組件構成。

  • 1、Kubelet

kubelet是node的agent,當Scheduler確定在某個Node上運行Pod後,會將Pod的具體配置信息(image、volume等)發送給該節點的kubelet,kubelet會根據這些信息創建和運行容器,並向master報告運行狀態。

  • 2、Container Runtime

每個Node都需要提供一個容器運行時(Container Runtime)環境,它負責下載鏡像並運行容器。目前K8S支持的容器運行環境至少包括Docker、RKT、cri-o、Fraki等。

  • 3、Kube-proxy

service在邏輯上代表了後端的多個Pod,外借通過service訪問Pod。service接收到請求就需要kube-proxy完成轉發到Pod的。每個Node都會運行kube-proxy服務,負責將訪問的service的TCP/UDP數據流轉發到後端的容器,如果有多個副本,kube-proxy會實現負載均衡,有2種方式:LVS或者Iptables

3、核心附件

K8S集羣還依賴一組附件組件,通常是由第三方提供的特定應用程序。如下圖:

  • 1、KubeDNS

在K8S集羣中調度並運行提供DNS服務的Pod,同一集羣內的其他Pod可以使用該DNS服務來解決主機名。K8S自1.11版本開始默認使用CoreDNS項目來爲集羣提供服務註冊和服務發現的動態名稱解析服務。

  • 2、Dashboard

K8S集羣的全部功能都要基於Web的UI,來管理集羣中的應用和集羣自身。

  • 3、Heapster

容器和節點的性能監控與分析系統,它收集並解析多種指標數據,如資源利用率、生命週期時間,在最新的版本當中,其主要功能逐漸由Prometheus結合其他的組件進行代替。

  • 4、Ingress Controller

Service是一種工作於4層的負載均衡器,而Ingress是在應用層實現的HTTP(S)的負載均衡。不過,Ingress資源自身並不能進行流量的穿透,,它僅僅是一組路由規則的集合,這些規則需要通過Ingress控制器(Ingress Controller)發揮作用。目前該功能項目大概有:Nginx-ingress、Traefik、Envoy和HAproxy等。如下圖就是Nginx-ingress的應用,具體可以查看博文:https://www.cnblogs.com/linuxk/p/9706720.html

img

四、K8S的網絡模型

K8S的網絡中主要存在4種類型的通信:

  • ①同一Pod內的容器間通信
  • ②各個Pod彼此間的通信
  • ③Pod和Service間的通信
  • ④集羣外部流量和Service之間的通信

K8S爲Pod和Service資源對象分別使用了各自的專有網絡,Pod網絡由K8S的網絡插件配置實現,而Service網絡則由K8S集羣進行指定。如下圖:

K8S使用的網絡插件需要爲每個Pod配置至少一個特定的地址,即Pod IP。Pod IP地址實際存在於某個網卡(可以是虛擬機設備)上。

而Service的地址卻是一個虛擬IP地址,沒有任何網絡接口配置在此地址上,它由Kube-proxy藉助iptables規則或ipvs規則重定向到本地端口,再將其調度到後端的Pod對象。Service的IP地址是集羣提供服務的接口,也稱爲Cluster IP。

Pod網絡和IP由K8S的網絡插件負責配置和管理,具體使用的網絡地址可以在管理配置網絡插件時進行指定,如10.244.0.0/16網絡。而Cluster網絡和IP是由K8S集羣負責配置和管理,如10.96.0.0/12網絡。

從上圖進行總結起來,一個K8S集羣包含是三個網絡。

  • (1)節點網絡:各主機(Master、Node、ETCD等)自身所屬的網絡,地址配置在主機的網絡接口,用於各主機之間的通信,又稱爲節點網絡。
  • (2)Pod網絡:專用於Pod資源對象的網絡,它是一個虛擬網絡,用於爲各Pod對象設定IP地址等網絡參數,其地址配置在Pod中容器的網絡接口上。Pod網絡需要藉助kubenet插件或CNI插件實現。
  • (3)Service網絡:專用於Service資源對象的網絡,它也是一個虛擬網絡,用於爲K8S集羣之中的Service配置IP地址,但是該地址不會配置在任何主機或容器的網絡接口上,而是通過Node上的kube-proxy配置爲iptables或ipvs規則,從而將發往該地址的所有流量調度到後端的各Pod對象之上。

五、Kubernetes的核心對象詳解

1、Pod資源對象

​ Pod資源對象是一種集合了一個或多個應用容器、存儲資源、專用ip、以及支撐運行的其他選項的邏輯組件。如下圖:Pod其實就是一個應用程序運行的單一實例,它通常由共享資源且關係緊密的一個或2多個應用容器組成。

​ Kubernetes的網絡模型要求每個Pod的IP地址同一IP網段,各個Pod之間可以使用IP地址進行通信,無論這些Pod運行在集羣內的哪個節點上,這些Pod對象都類似於運行在同一個局域網內的虛擬機一般。

​ 我們可以將每一個Pod對象類比爲一個物理主機或者是虛擬機,那麼運行在同一個Pod對象中的多個進程,也就類似於跑在物理主機上的獨立進程,而不同的是Pod對象中的各個進程都運行在彼此隔離的容器當中,而各個容器之間共享兩種關鍵性資源:網絡和存儲卷。

  • 網絡:每一個Pod對象都會分配到一個Pod IP地址,同一個Pod內部的所有容器共享Pod對象的Network和UTS名稱空間,其中包括主機名、IP地址和端口等。因此,這些容器可以通過本地的迴環接口lo進行通信,而在Pod之外的其他組件的通信,則需要使用Service資源對象的Cluster IP+端口完成。
  • 存儲卷:用戶可以給Pod對象配置一組存儲卷資源,這些資源可以共享給同一個Pod中的所有容器使用,從而完成容器間的數據共享。存儲卷還可以確保在容器終止後被重啓,或者是被刪除後也能確保數據的持久化存儲。

​ 一個Pod代表着某個應用程序的特定實例,如果我們需要去擴展這個應用程序,那麼就意味着需要爲該應用程序同時創建多個Pod實例,每個實例都代表着應用程序的一個運行副本。而這些副本化的Pod對象的創建和管理,都是由一組稱爲Controller的對象實現,比如Deployment控制器對象。

​ 當創建Pod時,我們還可以使用Pod Preset對象爲Pod注入特定的信息,比如Configmap、Secret、存儲卷、卷掛載、環境變量等。有了Pod Preset對象,Pod模板的創建就不需要爲每個模板顯示提供所有信息。

​ 基於預定的期望狀態和各個節點的資源可用性,Master會把Pod對象調度至選定的工作節點上運行,工作節點從指向的鏡像倉庫進行下載鏡像,並在本地的容器運行時環境中啓動容器。Master會將整個集羣的狀態保存在etcd中,並通過API Server共享給集羣的各個組件和客戶端。

2、Controller

​ 在K8S的集羣設計中,Pod是一個有生命週期的對象。那麼用戶通過手工創建或者通過Controller直接創建的Pod對象會被調度器(Scheduler)調度到集羣中的某個工作節點上運行,等到容器應用進程運行結束之後正常終止,隨後就會被刪除。而需要注意的是,當節點的資源耗盡或者故障,也會導致Pod對象的回收。

​ 而K8S在這一設計上,使用了控制器實現對一次性的Pod對象進行管理操作。比如,要確保部署的應用程序的Pod副本數達到用戶預期的數目,以及基於Pod模板來重建Pod對象等,從而實現Pod對象的擴容、縮容、滾動更新和自愈能力。例如,在某個節點故障,相關的控制器會將運行在該節點上的Pod對象重新調度到其他節點上進行重建。

​ 控制器本身也是一種資源類型,其中包括Replication、Controller、Deployment、StatefulSet、DaemonSet、Jobs等等,它們都統稱爲Pod控制器。如下圖的Deployment就是這類控制器的代表實現,是目前用於管理無狀態應用的Pod控制器。

​ Pod控制器的定義通常由期望的副本數量、Pod模板、標籤選擇器組成。Pod控制器會根據標籤選擇器來對Pod對象的標籤進行匹配篩選,所有滿足選擇條件的Pod對象都會被當前控制器進行管理並計入副本總數,確保數目能夠達到預期的狀態副本數。

​ 需要注意的是,在實際的應用場景中,在接收到的請求流量負載低於或接近當前已有Pod副本的承載能力時,需要我們手動修改Pod控制器中的期望副本數量以實現應用規模的擴容和縮容。而在集羣中部署了HeapSet或者Prometheus的這一類資源監控組件時,用戶還可以通過HPA(HorizontalPodAutoscaler)來計算出合適的Pod副本數量,並自動地修改Pod控制器中期望的副本數,從而實現應用規模的動態伸縮,提高集羣資源的利用率。

​ K8S集羣中的每個節點上都運行着cAdvisor,用於收集容器和節點的CPU、內存以及磁盤資源的利用率直播數據,這些統計數據由Heapster聚合之後可以通過API server訪問。而HorizontalPodAutoscaler基於這些統計數據監控容器的健康狀態並作出擴展決策。

3、Service

​ 我們知道Pod對象有Pod IP地址,但是該地址無法確保Pod對象重啓或者重建之後保持不變,這會帶來集羣中Pod應用間依賴關係維護的麻煩。比如前段Pod應用無法基於固定的IP地址跟中後端的Pod應用。

​ 而Service資源就是在被訪問的Pod對象中添加一個有着固定IP地址的中間層,客戶端向該地址發起訪問請求後,由相關的Service資源進行調度並代理到後端的Pod對象。

​ Service並不是一個具體的組件,而是一個通過規則定義出由多個Pod對象組成而成的邏輯集合,並附帶着訪問這組Pod對象的策略。Service對象挑選和關聯Pod對象的方式和Pod控制器是一樣的,都是通過標籤選擇器進行定義。如下圖:

​ Service IP是一種虛擬IP,也稱爲Cluster IP,專用於集羣內通信,通常使用專有的地址段,如:10.96.0.0/12網絡,各Service對象的IP地址在該範圍內由系統動態分配。

​ 集羣內的Pod對象可直接請求這類Cluster IP,比如上圖中來自Pod client的訪問請求,可以通過Service的Cluster IP作爲目標地址進行訪問,但是在集羣網絡中是屬於私有的網絡地址,僅僅可以在集羣內部訪問。

​ 而需要將集羣外部的訪問引入集羣內部的常用方法是通過節點網絡進行,其實現方法如下:

  • 通過工作節點的IP地址+端口(Node Port)接入請求。
  • 將該請求代理到相應的Service對象的Cluster IP的服務端口上,通俗地說:就是工作節點上的端口映射了Service的端口。
  • 由Service對象將該請求轉發到後端的Pod對象的Pod IP和 應用程序的監聽端口。

​ 因此,類似於上圖來自Exxternal Client的集羣外部客戶端,是無法直接請求該Service的Cluster IP,而是需要實現經過某一工作節點(如 Node Y)的IP地址,着了請求需要2次轉發才能到目標Pod對象。這一類訪問的缺點就是在通信效率上有一定的延時。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章