從頭開始學習 Kubernetes 核心原理和術語

java06051515發表於2019-03-26

前言

最近 Kubernetes(k8s)的熱度越來越高,正好反映了k8s 已經成為一個領先的自動化容器操作的開源平臺。也許,再過兩年大部分的服務都會執行在 k8s 叢集上面,掌握 k8s 就如同程式設計師需要掌握基本的 Llinux 操作命令一樣基礎。

在現在這個資訊發達的社會下,誰能比別人領先一步掌握新技術,誰就在競爭中贏得了先機。 然而,在瞭解一個大的系統時,應該儘量先了解其基本概念、術語及核心原理。本文將和大家一起學習 Kubernetes 的基本概念、術語及核心原理。

基本概念和術語

k8s 中的大部分概念如 Node、Pod、Volume、Replication Controller、 Service 等都可以理解為資源物件,幾乎所有的資源物件都可以透過 kubectl 工具(或者 API 呼叫)執行 CRUD 等操作。所以也可以把 k8s 理解為一個自動化容器資源的管理和排程平臺。

下圖展示了一個典型的 Kubernetes 架構圖,現在,我們來一起學習:

1. Master

Master 指的是叢集的控制節點,每個 k8s 叢集裡至少需要一個 Master 節點來負責整個叢集的管理和控制,所有控制命令都是發給它,它來負責具體的排程和執行。

Master 上面一般執行著下面這些關鍵程式:

  • Kubernetes API Server(kube-apiserver) : 為叢集提供了 HTTP Rest 介面,是 k8s 叢集叢集操作和資源操作的唯一入口。
  • Kubernetes Controller Manager(kube-controller-manager) : k8s 裡資源物件的自動化控制中心。
  • Kubernetes Scheduler(kube-scheduler) : 資源的排程程式。

2. Node

Node 是 k8s 叢集中用於執行 Pod 的機器,Node 為整個叢集提供可用的叢集資源,比如用於保持資料、執行作業、建立網路路由等。如果某個 Node節點當機,其上的工作負載會被 Master 自動轉移到其它節點上去。

Node 節點上面會執行以下關鍵程式:

  • kubelet :與 Master 協作管理當前 node 節點,從而實現叢集管理的基本功能,比如負責 Pod 的建立、啟停等任務。
  • kube-proxy :負責 Service 的通訊與負載均衡。
  • Docker Engine(docker) :Docker 引擎,負責本機的容器管理工作。

Node 節點加入到叢集后,kubelet 程式就會定期向 Master 節點上報自身的情況,例如 Docker 版本、CPU、記憶體、Pod 執行情況等,這樣 Master 就可以獲得每個節點的資源使用情況的,並實現高效均衡的資源排程策略。

3. Pod

Pod 是一組容器和卷的集合,同一個Pod裡的容器共享同一個網路名稱空間,可以使用 localhost 互相通訊。

Pod是短暫的,不是持續性實體。k8s 會為每一個 pod 分配一個唯一的 IP 地址,稱之為 Pod IP 。k8s 要求底層網路支援叢集內任意兩個 Pod 之間的網路通訊,這通常採用虛擬二層網路技術來實現,例如 Flannel、Open vSwitch 等。

Pod 有兩種類型別:普通的 Pod 和靜態 Pod(Static Pod):

  • 普通的 Pod :建立後會放入 ETCD 中儲存,隨後會被 Master 排程到某個具體的 Node 上面執行。預設情況與當 Pod 裡的某個容器停止時,k8s 會自動檢測到並重啟這個Pod,如果 Pod 所在的 Nod 當機,則會將這個 Nod 上的所有 Pod 排程到其它節點上執行。
  • 靜態 Pod :靜態 Pod 比較特殊,它不會存放到 etcd 中,而是存放在某個具體的 Node 上的一個具體檔案中,並且只在此 Node 上面啟動執行。他們不能透過 API Server 進行管理,無法與 ReplicationController、Deployment 等進行關聯,並且 kubelet 也不會對其進行健康檢查。

4. Replication Controller

ReplicationController(簡稱為 RC)。

在舊版本中,只有 ReplicationController 物件,它的主要作用是確保 Pod 以你指定的副本數執行,即如果有容器異常退出,會自動建立新的 Pod 來替代,如下圖所示。而異常多出來的容器也會自動回收,RC 跨多個 Node 節點監視多個 Pod。可以說 k8s 透過 RC 實現了叢集的高可用性。

在執行時,我們也可以透過修改 RC 來修改副本的數量,從而實現 Pod 的動態縮放功能。但是刪除 RC 並不會刪除透過該 RC 已經建立好的 Pod。

在 k8s V1.2時,RC 升級成了 Replica Set(RS),RS 和 RC 之間的唯一區別是對選擇器的支援。RS 支援基本集合的 Label Selector, 而 RC 只支援基本等式的的 Label Selector。我們不需要直接使用 RC 或者 RS,我們要使用 Deployment 來間接使用。

下面我們看看 Deployment 的概念。

5. Deployment

Deployment 的引入更好的解決了 Pod 的編排問題,Deployment 內部使用 RS 來實現,可以把 Deployment 理解為 RC 的升級版本。

由於 Pod 的建立、排程、繫結到節點及在目標節點上面啟動都需要一定的時間,整個過程是一個連續變化的“部署過程”,所以使用 Deployment 來描述這個過程再好不過了。

Deployment 的典型使用場景有下面幾個:

  • 建立一個 Deployment 物件來生成對應的 RS 並完成 Pod 副本的建立
  • 透過 Deployment 的狀態來看部署動作是否完成
  • 更新 Deployment 以建立新的 Pod(比如應用升級)
  • 回滾升級
  • 暫停 Deployment 以便於一次性修改多個 PodTemplateSpec 的配置項,之後再恢復Deployment,進行新的釋出
  • 擴容

6. Lable

Label 可以理解為給資源打的標籤。 一個 Lable 是一個 Key=Value 的鍵值對。Label 可以附加到所有資源上面,一個資源可以定義任意數量的 Lable,同一個 Lable 也可以被新增到任意資源物件上。我們可以透過 Lable Selector(標籤選擇器)查詢和篩選擁有某些 Label 的資源物件,k8s 透過這種方式實現了類似 SQL 的物件查詢機制。

例如,給系統中所有 Worker Pod 打上標籤:app=worker,之後即可在 kubectl 或 k8s API 中使用– Selector 欄位對其進行選擇。

7. Service

Service 是定義一系列 Pod 以及訪問這些 Pod 的策略的一層抽象。Service 透過 Label 找到 Pod 組。k8s 裡的每個 Service 可以理解為我們微服務架構中的一個“微服務”,每個 Service 都有一個唯一的 Cluster IP 及唯一的名字,名字由開發者定義,服務間的呼叫可以直接呼叫 Cluster IP+埠 或者服務名+埠的方式呼叫。

假定有 2 個後臺 Pod,並且定義後臺 Service 的名稱為‘backend-service’,Lable 選擇器為(tier=backend, app=myapp)。

backend-service 的 Service 會完成如下兩件重要的事情:

  • 會為 Service 建立一個本地叢集的 DNS 入口,因此前端 Pod 只需要 DNS 查詢主機名為 ‘backend-service’,就能夠解析出前端應用程式可用的 IP 地址。
  • 現在前端已經得到了後臺服務的 IP 地址,但是它應該訪問 2 個後臺 Pod 的哪一個呢?
    Service 在這 2 個後臺 Pod 之間提供透明的負載均衡,會將請求分發給其中的任意一個(如下面的動畫所示)。透過每個 Node 上執行的代理(kube-proxy)完成。

下圖簡單地展示了 Service 的功能:

Kubernetes ServiceTypes 允許指定一個需要的型別的 Service,預設是 ClusterIP 型別。

Type 的取值以及行為如下:

  • ClusterIP :透過叢集的內部 IP 暴露服務,選擇該值,服務只能夠在叢集內部可以訪問,這也是預設的 ServiceType。
  • NodePort :透過每個 Node 上的 IP 和靜態埠(NodePort)暴露服務。NodePort 服務會路由到 ClusterIP 服務,這個 ClusterIP 服務會自動建立。透過請求  <NodeIP>:<NodePort> ,可以從叢集的外部訪問一個 NodePort 服務。
  • LoadBalancer :使用雲提供商的負載局衡器,可以向外部暴露服務。外部的負載均衡器可以路由到 NodePort 服務和 ClusterIP 服務。
  • ExternalName :透過返回 CNAME 和它的值,可以將服務對映到 externalName 欄位的內容(例如, foo.bar.example.com)。 沒有任何型別代理被建立,這隻有 Kubernetes 1.7 或更高版本的 kube-dns 才支援。

8. Volume

Volume 是 Pod 中能夠被多個容器訪問的共享目錄。

k8s 的 Volume 的概念、用途和目的與 Docker 的 Volume 比較類似,但是不完全一樣。k8s 中的 Volume 定義在 Pod 上,然後被 Pod 裡面的多個容器掛載到具體的檔案目錄下,其生命週期與 pod 相同。

k8s 支援的 volume 型別比較豐富,例如 emptyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、cephFs……

9. Persistent Volume

與 Volume 對應的是 Persistent Volume。

Persistent Volume(簡稱 PV):可以理解成 k8s 叢集中的某個網路儲存中對應的一塊儲存。它與 Volume 有以下區別:

  • PV 只能是網路儲存,不屬於任何 Node,但是可以在每個 Node 上訪問
  • PV 是獨立定義於 Pod 之外的

PV 支援的型別也比較豐富,例如:gcePersistentDisk、awsElasticBlockStore、cephFs、NFS……

10. Namespace

Namespace(名稱空間):主要用於實現多個租戶的資源隔離,屬於邏輯上的隔離,多個名稱空間中的資源其實還是可以相互訪問及操作的(這是 k8s 的缺點)。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559758/viewspace-2637576/,如需轉載,請註明出處,否則將追究法律責任。

相關文章