【雲原生】Kubernetes(k8s)的核心設計介紹

語言: CN / TW / HK

得益於 docker 的特性,服務的建立和銷燬變得非常快速、簡單。Kubernetes 正是以此為基礎,實現了叢集規模的管理、編排方案,使應用的釋出、重啟、擴縮容能夠自動化。本篇介紹Kubernetes的核心設計。

目錄

    • 1. 編排抽象
      • Pod物件
      • Service物件
    • 2. 宣告式API
    • 3. 開放外掛

 

總結Kubernetes核心設計主要概況為如下三點:

1. 編排抽象

容器平臺核心點不在於建立和排程容器,而是在上層架構抽象出各種物件,便於去統一管理。Kubernetes創造性的抽象出了各個編排的關係,例如親密關係(Pod物件)、訪問關係(Service物件)等。

Pod物件

Pod 直譯是豆莢,可以把容器想像成豆莢裡的豆子,把一個或多個關係緊密的豆子包在一起就是豆莢(一個 Pod)。在 k8s 中我們不會直接操作容器,而是把容器包裝成 Pod 再進行管理。
在這裡插入圖片描述

Kubernetes在物件抽象方面,核心創新在於Pod物件的設計。
Pod是 Kubernetes 專案中最小的 API 物件。換句話說Pod是Kubernetes最基本的操作單元,包含一個或多個緊密相關的容器,一個Pod可以被一個容器化的環境看作應用層的“邏輯宿主機”;
一個Pod中的多個容器應用通常是緊密耦合的,Pod在Node上被建立、啟動或者銷燬;
每個Pod裡執行著一個特殊的被稱之為Pause的容器,其他容器則為業務容器,這些業務容器共享Pause容器的網路棧和Volume掛載卷,因此他們之間通訊和資料交換更為高效,在設計時我們可以充分利用這一特性將一組密切相關的服務程序放入同一個Pod中。同一個Pod裡的容器之間僅需通過localhost就能互相通訊。
一個Pod中的應用容器共享同一組資源:

  • PID名稱空間:Pod中的不同應用程式可以看到其他應用程式的程序ID;
  • 網路名稱空間:Pod中的多個容器能夠訪問同一個IP和埠範圍;
  • IPC名稱空間:Pod中的多個容器能夠使用SystemV IPC或POSIX訊息佇列進行通訊;
  • UTS名稱空間:Pod中的多個容器共享一個主機名;
  • Volumes(共享儲存卷):Pod中的各個容器可以訪問在Pod級別定義的Volumes;

Pod的生命週期通過Replication Controller來管理;通過模板進行定義,然後分配到一個Node上執行,在Pod所包含容器執行結束後,Pod結束(其中, pod.status.phase,就是 Pod 的當前狀態,它有如下幾種可能的情況:PendingRunningSucceededFailedUnknown)。

POD操作示例:
–建立一個nginx pod

kubectl run ng --image=nginx:1.9 --port=80

–狀態檢查

kubectl  get pod name
kubectl  describe pod name
kubectl  logs name

–通過yaml建立pod,通過–dry-run來生成一個yaml檔案

kubectl run ng --image=nginx:1.9 --port=80 --dry-run=client -o yaml >ng.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ng
  name: ng
spec:
  containers:
  - image: nginx:1.9
    name: ng
    ports:
    - containerPort: 80
    resources: {
   }
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {
   }

–一個pod執行多個容器

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ng01
  name: multi-pod
spec:
  containers:
    - image: nginx:1.9
      name: ng01
      ports:
        - containerPort: 80
      resources: {
    }
    - image: tomcat:8.0.41-jre8-alpine
      name: tomcat8-1
      ports:
        - containerPort: 8080
      resources: {
    }
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {
    }

這個容器運行了兩個容器nginxtomcat,執行kubectl apply -f multi.yaml後,檢視pod。

–刪除pod

kubectl delete pod ng

Service物件

Kubernetes編排抽象的另一個核心物件是Service物件。
在Kubernetes的世界裡,雖然每個Pod都會被分配一個單獨的IP地址,但這個IP地址會隨著Pod的銷燬而消失,這就引出一個問題:如果有一組Pod組成一個叢集來提供服務,那麼如何來訪問它呢?
Service!一個Service可以看作一組提供相同服務的Pod的對外訪問介面,Service作用於哪些Pod是通過Label Selector來定義的。
下圖是kube-proxy通過iptables模式來實現Service的過程,Service物件有一個虛擬clusterIP,叢集內請求訪問clusterIP時,會由iptables規則負載均衡到後端endpoints。
在這裡插入圖片描述

服務編排通俗地說就是將一個服務在合適的時間放在一個合適的地方,讓其按照規劃的方式執行。

  • 合適的時間:當實際服務狀態和預期狀態不相符的時候;
  • 合適的地方:資源最充足的地方;
  • 規劃的方式:滿足使用者的需求;

K8s編排服務工作流程:

  1. 客戶端提交建立請求;
  2. API Server 篩選合適的節點;
  3. API Server向指定節點Kubelet下發建立任務;
  4. Kubelet建立Pod;
  5. Kubelet上報節點狀態。

2. 宣告式API

宣告式API是整個系統自動化的核心要點,kubernetes提供了以宣告式API的方式將抽象對外暴露,同時也方便了使用者管理物件。

Declarative(宣告式設計)指的是一種軟體設計理念和程式設計方式,描述了目標狀態,由工具自行判斷當前狀態並執行相關操作至目標狀態。宣告式強調What,目標是什麼。而Imperative(命令式)需要使用者描述一系列詳細指令來達到期望的目標狀態。命令式強調How,具體如何做。

kubernetes的一大核心設計就是採用了宣告式API,利用該設計思想有效的實現了系統的自動化執行。Kubernetes宣告式API指定了叢集期望的執行狀態,叢集控制器會通過List&Watch機制來獲取當前狀態,並根據當前狀態自動執行相應的操作至目標狀態。
在這裡插入圖片描述

Kubernetes中,使用者通過提交定義好的API物件來宣告期望狀態,系統允許有多個API寫端,以PATCH方式對API物件進行修改。Kubectl工具支援三種物件管理方式:命令式命令列、命令式物件配置(yaml)、宣告式物件配置(yaml)。舉例如下:

  • 命令式命令列:
    特點:僅需一步就對叢集做了修改。示例:建立一個deployment型別的object
kubectl run nginx --image nginx

kubectl create deployment nginx --image nginx
  • 命令式物件配置:命令式物件配置:
kubectl create –f nginx.yaml
kubectl replace –f nginx.yaml
  • 宣告式物件配置:宣告式物件配置:
    特點:
    1)便捷性:不必新增大量的引數到命令列中執行命令。
    2)靈活性:YAML可以建立比命令列更加複雜的結構。
    3)可維護性:YAML檔案可以通過源頭控制,跟蹤每次操作;並且物件配置可以儲存在源控制系統中(比如Git);物件配置同時也提供了用於建立物件的模板。
    kubectl apply –f nginx.yaml

Kubernetes推薦使用:宣告式物件配置(YAML)。

3. 開放外掛

支援系統資源外掛化(比如計算、儲存、網路);同時也支援使用者自定義CRD和開發Operator。

Kubernetes的設計初衷就是支援可插拔的架構,解決PaaS平臺不好用、不能用、需要定製化等問題。為了便於系統的擴充套件,K8S集成了外掛、附加元件、服務和介面來擴充套件平臺的核心功能。附加元件被定義為與環境的其他部分無縫整合的元件,提供類似本機的特性,並擴充套件叢集管理員可用的元件,擴充套件還可以用於新增自定義軟硬體的支援;服務和介面提供了看似繁瑣和冗餘的設計(比如我們常見的PV、PVC、SC),實際上為開發人員提供了更多的可擴充套件性。

Kubernetes作為雲原生應用的的基礎排程平臺,相當於雲原生的作業系統,為了便於系統的擴充套件,Kubernetes中開放的以下介面可對系統資源(計算、網路、儲存)外掛進行擴充套件,可分別對接不同的後端來實現自己的業務邏輯。
在這裡插入圖片描述

  • 網路外掛 CNI
    CNI(Container Network Interface):容器網路介面,提供網路資源。
    跨主機容器間的網路互通已經成為基本要求,K8S網路模型要求所有容器都可以直接使用IP地址與其他容器通訊,而無需使用NAT;所有宿主機都可以直接使用IP地址與所有容器通訊,而無需使用NAT。反之亦然。容器自己的IP地址,和別人(宿主機或者容器)看到的地址是完全一樣的。K8S提供了一個外掛規範,稱為容器網路介面(CNI),只要滿足K8S的基本需求,第三方廠商可以隨意使用自己的網路棧,通過使用overlay網路來支援多子網或者一些個性化使用場景,所以出現很多優秀的CNI外掛被新增到Kubernetes叢集中。
  • 容器執行時CRI
    CRI(Container Runtime Interface):容器執行時介面,提供計算資源。
    CRI介面設計的一個重要原則是隻關注介面本身,而不關心具體實現,kubelet就只需要跟這個介面打交道。而作為具體的容器專案,比如Docker、rkt、containerd、kata container它們就只需要自己提供一個該介面的實現,然後對kubelet暴露出gRPC服務即可。簡單來說,CRI主要作用就是實現了kubelet和容器執行時之間的解耦。
  • 儲存介面CSI
    CSI(Container Storage Interface):容器儲存介面,提供儲存資源。
    K8S將儲存體系抽象出了外部儲存元件介面,第三方儲存廠商可以釋出和部署公開的儲存外掛,無需接觸Kubernetes核心程式碼,同時為Kubernetes使用者提供了更多的儲存選項。例如:AWS、NFS、Ceph。

小結:無論多麼複雜的應用程式,Kubernetes都可以很好的支援,這使得基於K8S的PaaS平臺非常健壯,並且能夠更有效地應對現代雲端計算帶來的挑戰。

🍒如果您覺得博主的文章還不錯或者有幫助的話,請關注一下博主,如果三連點贊評論收藏就更好啦!謝謝各位大佬給予的支援!