帶着問題學 Kubernetes 架構

帶着問題學 Kubernetes 架構

摘要:本文屬於原創,歡迎轉載,轉載請保留出處:https://github.com/jasonGeng88/blognode

打開這篇文章的同窗,想必對 docker 都不會陌生。docker 是一種虛擬容器技術,它上手比較簡單,只需在宿主機上起一個 docker engine,而後就能愉快的玩耍了,如:拉鏡像、起容器、掛載數據、映射端口等等。相對於 Kubernetes(K8S)的上手,可謂簡單不少。git

那麼 K8S 是什麼,又爲何上手難度大?K8S 是一個基於容器技術的分佈式集羣管理系統,是谷歌幾十年來大規模應用容器技術的經驗積累和昇華的一個重要成果。因此爲了可以支持大規模的集羣管理,它承載了不少的組件,並且分佈式自己的複雜度就很高。又由於 K8S 是谷歌出品的,依賴了不少谷歌本身的鏡像,因此對於國內的同窗環境搭建的難度又增長了一層。github

下面,咱們帶着問題,一步步來看 K8S 中到底有哪些東西?算法

首先,既然是個分佈式系統,那勢必有多個 Node 節點(物理主機或虛擬機),它們共同組成一個分佈式集羣,而且這些節點中會有一個 Master 節點,由它來統一管理 Node 節點。docker

如圖所示:api

問題一:主節點和工做節點是如何通訊的呢?

首先,Master 節點啓動時,會運行一個 kube-apiserver 進程,它提供了集羣管理的 API 接口,是集羣內各個功能模塊之間數據交互和通訊的中心樞紐,而且它頁提供了完備的集羣安全機制(後面還會講到)。安全

在 Node 節點上,使用 K8S 中的 kubelet 組件,在每一個 Node 節點上都會運行一個 kubelet 進程,它負責向 Master 彙報自身節點的運行狀況,如 Node 節點的註冊、終止、定時上報健康情況等,以及接收 Master 發出的命令,建立相應 Pod網絡

在 K8S 中,Pod 是最基本的操做單元,它與 docker 的容器有略微的不一樣,由於 Pod 可能包含一個或多個容器(能夠是 docker 容器),這些內部的容器是共享網絡資源的,便可以經過 localhost 進行相互訪問。架構

關於 Pod 內是如何作到網絡共享的,每一個 Pod 啓動,內部都會啓動一個 pause 容器(google的一個鏡像),它使用默認的網絡模式,而其餘容器的網絡都設置給它,以此來完成網絡的共享問題。負載均衡

如圖所示:

問題二:Master 是如何將 Pod 調度到指定的 Node 上的?

該工做由 kube-scheduler 來完成,整個調度過程經過執行一些列複雜的算法最終爲每一個 Pod 計算出一個最佳的目標 Node,該過程由 kube-scheduler 進程自動完成。常見的有輪詢調度(RR)。固然也有可能,咱們須要將 Pod 調度到一個指定的 Node 上,咱們能夠經過節點的標籤(Label)和 Pod 的 nodeSelector 屬性的相互匹配,來達到指定的效果。

如圖所示:

關於標籤(Label)與選擇器(Selector)的概念,後面會進一步介紹

問題三:各節點、Pod 的信息都是統一維護在哪裏的,由誰來維護?

從上面的 Pod 調度的角度看,咱們得有一個存儲中心,用來存儲各節點資源使用狀況、健康狀態、以及各 Pod 的基本信息等,這樣 Pod 的調度來能正常進行。

在 K8S 中,採用 etcd 組件 做爲一個高可用強一致性的存儲倉庫,該組件能夠內置在 K8S 中,也能夠外部搭建供 K8S 使用。

集羣上的全部配置信息都存儲在了 etcd,爲了考慮各個組件的相對獨立,以及總體的維護性,對於這些存儲數據的增、刪、改、查,統一由 kube-apiserver 來進行調用,apiserver 也提供了 REST 的支持,不只對各個內部組件提供服務外,還對集羣外部用戶暴露服務。

外部用戶能夠經過 REST 接口,或者 kubectl 命令行工具進行集羣管理,其內在都是與 apiserver 進行通訊。

如圖所示:

問題四:外部用戶如何訪問集羣內運行的 Pod ?

前面講了外部用戶如何管理 K8S,而咱們更關心的是內部運行的 Pod 如何對外訪問。使用過 docker 的同窗應該知道,若是使用 bridge 模式,在容器建立時,都會分配一個虛擬 IP,該 IP 外部是無法訪問到的,咱們須要作一層端口映射,將容器內端口與宿主機端口進行映射綁定,這樣外部經過訪問宿主機的指定端口,就能夠訪問到內部容器端口了。

那麼,K8S 的外部訪問是否也是這樣實現的?答案是否認的,K8S 中狀況要複雜一些。由於上面講的 docker 是單機模式下的,並且一個容器對外就暴露一個服務。在分佈式集羣下,一個服務每每由多個 Application 提供,用來分擔訪問壓力,並且這些 Application 可能會分佈在多個節點上,這樣又涉及到了跨主機的通訊。

這裏,K8S 引入了 service 的概念,將多個相同的 Pod 包裝成一個完整的 service 對外提供服務,至於獲取到這些相同的 Pod,每一個 Pod 啓動時都會設置 labels 屬性,在 service 中咱們經過選擇器 selector,選擇具備相同 name 標籤屬性的 Pod,做爲總體服務,並將服務信息經過 apiserver 存入 etcd 中,該工做由 Service Controller 來完成。同時,每一個節點上會啓動一個 kube-proxy 進程,由它來負責服務地址到 Pod 地址的代理以及負載均衡等工做。

如圖所示:

問題五:Pod 如何動態擴容和縮放?

既然知道了服務是由 Pod 組成的,那麼服務的擴容也就意味着 Pod 的擴容。通俗點講,就是在須要時將 Pod 複製多份,在不須要後,將 Pod 縮減至指定份數。K8S 中經過 Replication Controller 來進行管理,爲每一個 Pod 設置一個指望的副本數,當實際副本數與指望不符時,就動態的進行數量調整,以達到指望值。指望數值能夠由咱們手動更新,或自動擴容代理來完成。

如圖所示:

問題六:各個組件之間是如何相互協做的?

最後,講一下 kube-controller-manager 這個進程的做用。咱們知道了 ectd 是做爲集羣數據的存儲中心, apiserver 是管理數據中心,做爲其餘進程與數據中心通訊的橋樑。而 Service Controller、Replication Controller 這些統一交由 kube-controller-manager 來管理,kube-controller-manager 做爲一個守護進程,每一個 Controller 都是一個控制循環,經過 apiserver 監視集羣的共享狀態,並嘗試將實際狀態與指望不符的進行改變。關於 Controller,manager 中還包含了 Node 節點控制器(Node Controller)、資源配額管控制器(ResourceQuota Controller)、命名空間控制器(Namespace Controller)等。

如圖所示:

總結

本文經過問答的方式,沒有涉及任何深刻的實現細節,從總體的角度,概念性的介紹了 K8S 中涉及的基本概念,其中使用相關的包括有:

  • Node

  • Pod

  • Label

  • Selector

  • Replication Controller

  • Service Controller

  • ResourceQuota Controller

  • Namespace Controller

  • Node Controller

以及運行進程相關的有:

  • kube-apiserver

  • kube-controller-manager

  • kube-scheduler

  • kubelet

  • kube-proxy

  • pause

這也是我學習 K8S 後對其總體架構的一次總結,由於在剛上手時,閱讀官方文檔,確實被如此多的內容搞得有點暈,所在在這裏進行了簡單的梳理。文中有理解不到位的地方,歡迎指正!

相關文章
相關標籤/搜索