Kubernetes 之 CRI、CNI、CSI


Kubernetes作為雲原生應用的的基礎調度平台,相當於雲原生的操作系統,為了便於系統的擴展,Kubernetes中開放的以下接口,可以分別對接不同的后端,來實現自己的業務邏輯:

    • CRI(Container Runtime Interface):容器運行時接口,提供計算資源
    • CNI(Container Network Interface):容器網絡接口,提供網絡資源
    • CSI(Container Storage Interface):容器存儲接口,提供存儲資源

 以上三種資源相當於一個分布式操作系統的最基礎的幾種資源類型,而Kuberentes是將他們粘合在一起的紐帶。

 

CRI

CRI中定義了容器和鏡像的服務的接口,因為容器運行時與鏡像的生命周期是彼此隔離的,因此需要定義兩個服務。

CRI架構

Container Runtime實現了CRI gRPC Server,包括RuntimeServiceImageService。該gRPC Server需要監聽本地的Unix socket,而kubelet則作為gRPC Client運行。

兩個gRPC服務:

    • RuntimeService:容器和Sandbox運行時管理
    • ImageService:提供了從鏡像倉庫拉取、查看、和移除鏡像的RPC。

 

啟用CRI

啟用CRI只需要在kubelet的啟動參數重傳入此參數:--container-runtime-endpoint遠程運行時服務的端點。

當前Linux上支持unix socket,windows上支持tcp。例如:unix:///var/run/dockershim.sock、 tcp://localhost:373,默認是unix:///var/run/dockershim.sock,即默認使用本地的docker作為容器運行時。

關於CRI的詳細進展請參考CRI: the Container Runtime Interface

 

CNI

CNI(Container Network Interface)是CNCF旗下的一個項目,由一組用於配置Linux容器的網絡接口的規范和庫組成,同時還包含了一些插件。CNI僅關心容器創建時的網絡分配,和當容器被刪除時釋放網絡資源。通過此鏈接瀏覽該項目:

Kubernetes源碼的vendor/github.com/containernetworking/cni/libcni目錄中已經包含了CNI的代碼,也就是說kubernetes中已經內置了CNI。

接口定義

CNI的接口中包括以下幾個方法:

type CNI interface { AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error } 

該接口只有四個方法,添加網絡、刪除網絡、添加網絡列表、刪除網絡列表。

設計考量

CNI設計的時候考慮了以下問題:

  • 容器運行時必須在調用任何插件之前為容器創建一個新的網絡命名空間。
  • 然后,運行時必須確定這個容器應屬於哪個網絡,並為每個網絡確定哪些插件必須被執行。
  • 網絡配置采用JSON格式,可以很容易地存儲在文件中。網絡配置包括必填字段,如nametype以及插件(類型)。網絡配置允許字段在調用之間改變值。為此,有一個可選的字段args,必須包含不同的信息。
  • 容器運行時必須按順序為每個網絡執行相應的插件,將容器添加到每個網絡中。
  • 在完成容器生命周期后,運行時必須以相反的順序執行插件(相對於執行添加容器的順序)以將容器與網絡斷開連接。
  • 容器運行時不能為同一容器調用並行操作,但可以為不同的容器調用並行操作。
  • 容器運行時必須為容器訂閱ADD和DEL操作,這樣ADD后面總是跟着相應的DEL。 DEL可能跟着額外的DEL,但是,插件應該允許處理多個DEL(即插件DEL應該是冪等的)。
  • 容器必須由ContainerID唯一標識。存儲狀態的插件應該使用(網絡名稱,容器ID)的主鍵來完成。
  • 運行時不能調用同一個網絡名稱或容器ID執行兩次ADD(沒有相應的DEL)。換句話說,給定的容器ID必須只能添加到特定的網絡一次。

CNI插件

CNI插件必須實現一個可執行文件,這個文件可以被容器管理系統(例如rkt或Kubernetes)調用。

CNI插件負責將網絡接口插入容器網絡命名空間(例如,veth對的一端),並在主機上進行任何必要的改變(例如將veth的另一端連接到網橋)。然后將IP分配給接口,並通過調用適當的IPAM插件來設置與“IP地址管理”部分一致的路由。

CNI插件必須支持以下操作:(1)將容器添加到網絡   (2)從網絡中刪除容器    (3)IP分配

 

CSI 

CSI 代表容器存儲接口,CSI 試圖建立一個行業標准接口的規范,借助 CSI 容器編排系統(CO)可以將任意存儲系統暴露給自己的容器工作負載。有關詳細信息,請查看設計方案

csi 卷類型是一種 in-tree(即跟其它存儲插件在同一個代碼路徑下,隨 Kubernetes 的代碼同時編譯的) 的 CSI 卷插件,用於 Pod 與在同一節點上運行的外部 CSI 卷驅動程序交互。部署 CSI 兼容卷驅動后,用戶可以使用 csi 作為卷類型來掛載驅動提供的存儲。

CSI 持久化卷支持是在 Kubernetes v1.9 中引入的,作為一個 alpha 特性,必須由集群管理員明確啟用。換句話說,集群管理員需要在 apiserver、controller-manager 和 kubelet 組件的 “--feature-gates =” 標志中加上 “CSIPersistentVolume = true”。

CSI 持久化卷具有以下字段可供用戶指定:

  • driver:一個字符串值,指定要使用的卷驅動程序的名稱。必須少於 63 個字符,並以一個字符開頭。驅動程序名稱可以包含 “.”、“-”、“_” 或數字。
  • volumeHandle:一個字符串值,唯一標識從 CSI 卷插件的 CreateVolume 調用返回的卷名。隨后在卷驅動程序的所有后續調用中使用卷句柄來引用該卷。
  • readOnly:一個可選的布爾值,指示卷是否被發布為只讀。默認是 false。

下面將介紹如何使用 CSI:

動態配置

可以通過為 CSI 創建插件 StorageClass 來支持動態配置的 CSI Storage 插件啟用自動創建/刪除 。

例如,以下 StorageClass 允許通過名為 com.example.team/csi-driver 的 CSI Volume Plugin 動態創建 “fast-storage” Volume。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: fast-storage
provisioner: com.example.team/csi-driver
parameters:
  type: pd-ssd 

要觸發動態配置,請創建一個 PersistentVolumeClaim 對象。例如,下面的 PersistentVolumeClaim 可以使用上面的 StorageClass 觸發動態配置。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-request-for-storage
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: fast-storage 

當動態創建 Volume 時,通過 CreateVolume 調用,將參數 type:pd-ssd 傳遞給 CSI 插件 com.example.team/csi-driver 。作為響應,外部 Volume 插件會創建一個新 Volume,然后自動創建一個 PersistentVolume 對象來對應前面的 PVC 。然后,Kubernetes 會將新的 PersistentVolume 對象綁定到 PersistentVolumeClaim,使其可以使用。

如果 fast-storage StorageClass 被標記為默認值,則不需要在 PersistentVolumeClaim 中包含 StorageClassName,它將被默認使用。

預配置 Volume

您可以通過手動創建一個 PersistentVolume 對象來展示現有 Volumes,從而在 Kubernetes 中暴露預先存在的 Volume。例如,暴露屬於 com.example.team/csi-driver 這個 CSI 插件的 existingVolumeName Volume

apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-manually-created-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  csi:
    driver: com.example.team/csi-driver
    volumeHandle: existingVolumeName
    readOnly: false 

附着和掛載

您可以在任何的 pod 或者 pod 的 template 中引用綁定到 CSI volume 上的 PersistentVolumeClaim

kind: Pod
apiVersion: v1
metadata:
  name: my-pod
spec:
  containers:
    - name: my-frontend
      image: dockerfile/nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: my-csi-volume
  volumes:
    - name: my-csi-volume
      persistentVolumeClaim:
        claimName: my-request-for-storage 

當一個引用了 CSI Volume 的 pod 被調度時, Kubernetes 將針對外部 CSI 插件進行相應的操作,以確保特定的 Volume 被 attached、mounted, 並且能被 pod 中的容器使用。

關於 CSI 實現的詳細信息請參考設計文檔

創建 CSI 驅動

Kubernetes 盡可能少地指定 CSI Volume 驅動程序的打包和部署規范。這里記錄了在 Kubernetes 上部署 CSI Volume 驅動程序的最低要求。

最低要求文件還包含概述部分,提供了在 Kubernetes 上部署任意容器化 CSI 驅動程序的建議機制。存儲提供商可以運用這個機制來簡化 Kubernetes 上容器式 CSI 兼容 Volume 驅動程序的部署。

作為推薦部署的一部分,Kubernetes 團隊提供以下 sidecar(輔助)容器:

可監聽 Kubernetes VolumeAttachment 對象並觸發 ControllerPublish 和 ControllerUnPublish 操作的 sidecar 容器,通過 CSI endpoint 觸發 ;

監聽 Kubernetes PersistentVolumeClaim 對象的 sidecar 容器,並觸發對 CSI 端點的 CreateVolume 和DeleteVolume 操作;

使用 Kubelet(將來)注冊 CSI 驅動程序的 sidecar 容器,並將 NodeId (通過 GetNodeID 調用檢索到 CSI endpoint)添加到 Kubernetes Node API 對象的 annotation 里面。

存儲供應商完全可以使用這些組件來為其插件構建 Kubernetes Deployment,同時讓它們的 CSI 驅動程序完全意識不到 Kubernetes 的存在。

另外 CSI 驅動完全是由第三方存儲供應商自己維護的,在 kubernetes 1.9 版本中 CSI 還處於 alpha 版本。

 

 

===================================================================================================

抄錄來源:https://zhuanlan.zhihu.com/p/33390023

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM