簡介 Kubernetes 容器儲存介面

簡介 Kubernetes 容器儲存介面

簡介 Kubernetes 容器儲存介面

容器儲存介面(Container Storage Interface, CSI)是 Kubernetes 在 1.9 版時為了解決以下議題所提出來的機制。

K8s 既有的 Volume plugin 是 in-tree 的,代表 plugin 的原始碼位於於 K8s 的 repository 中,這讓 plugin 除了在開發時需要對 K8s 的專案發出 pull request 才能將 commits 合併外,plugin 也會隨著 K8s repository 一起編譯成執行檔,這不只需要讓第三方 volume plugin 開發人員需要參與進 K8s 的開發過程,更讓 plugin 的更新。

特定的 volume plugin 需要在 K8s 的節點上安裝套件,如欲使用 Ceph 的 Block Device 作為 K8s 上的 volume 時,必須在 node 上使用套件管理工具安裝 ceph-common 才能正常掛載 RBD image,這使得我們在必須建立 K8s 叢集前就先將安裝套件的 script 寫入部署工具或著在需要前再連線至 node 中安裝, 而理想的狀況是 plugin 的依賴可以整合進容器中,隨著 Pod 建立即擁有掛載 volume 的能力而不必處理依賴關係。

單節點的 hostPath CSI driver

在開始使用 CSI 前,必須確認 kubelet 和 api-server 在啟動時加入 –allow-privileged=true 的 flag,讓 Pod 可以運行在 privileged 模式。

1.建立 Pod

$ kubectl create -f https://raw.githubusercontent.com/kubernetes-csi/docs/master/book/src/example/csi-setup.yaml
storageclass "csi-hostpath-sc" created
serviceaccount "csi-service-account" created
clusterrole "csi-cluster-role" created
clusterrolebinding "csi-role-binding" created
pod "csi-pod" created

我們可以看到 YMAL 檔中除了 hostPath 的 CSI driver 外,還有三個由 K8s 官方所提供 sidecar 容器:external-attacher、external-provisioner 和 driver-registrar,它們的作用分別是:

  • external-attacher

關注 K8s 叢集的 VolumeAttachment 物件,當有物件產生時在 Pod 中透過 unix domain socket 對 CSI driver 進行 gRPC 呼叫 ControllerPublish 和 ControllerUnpublish。在 hostPath 的 CSI driver 中並未實作以上函數。

  • external-provisioner

關注 K8s 叢集的 PersistentVolumeClaim 物件,當有物件產生時在 Pod 中透過 unix domain socket 對 hostPath CSI driver 進行 gRPC 呼叫 CreateVolume 和 DeleteVolume。在 hostPath 的 CSI driver 中 CreateVolume 在 driver 所在的 node 上建立了所需的資料夾;DeleteVolume 則在 刪除了指定的資料夾

  • driver-registrar

將 CSI driver 自訂的 NodeID 到增加到所屬 K8s 節點的 annotation 中。

$ kubectl describe no/k8s-01
...
Annotations:        csi.volume.kubernetes.io/nodeid={"csi-hostpath":"k8s-01"}
...

2.建立 PersistentVolumeClaim

$ kubectl create -f https://raw.githubusercontent.com/kubernetes-csi/docs/master/book/src/example/csi-pvc.yaml
persistentvolumeclaim "csi-pvc" created
$ kubectl get pvc
NAME      STATUS    VOLUME                 CAPACITY   ACCESS MODES   STORAGECLASS      AGE
csi-pvc   Bound     pvc-c84b83e188d711e8   1Gi        RWO            csi-hostpath-sc   6s

建立了 PVC 後,動態建立了 PV。

$ kubectl get pv
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM             STORAGECLASS      REASON    AGE
pvc-c84b83e188d711e8   1Gi        RWO            Delete           Bound     default/csi-pvc   csi-hostpath-sc             4s

發現 PVC 物件的建立後,external provisioner 便在 hostpath-driver 容器中的 /tmp 目錄下建立了資料夾

$ kubectl exec -it csi-pod -c hostpath-driver -- /bin/sh
$ ls -l /tmp
total 4
drwxr-xr-x    2 root     root          4096 Jul 16 09:08 c85f4370-88d7-11e8-b7ad-0a580ae94006

3.建立 Pod 掛載 PVC

$ kubectl create -f https://raw.githubusercontent.com/kubernetes-csi/docs/master/book/src/example/csi-app.yaml
pod "my-csi-app" created

4.寫入檔案至 volume 中並檢查是否寫入至 hostpath-driver 容器中

$ kubectl exec -it my-csi-app /bin/sh
/ # touch /data/test.txt
$ kubectl exec -it csi-pod -c hostpath-driver -- /bin/sh
/ # cd /tmp/c85f4370-88d7-11e8-b7ad-0a580ae94006/
/tmp/c85f4370-88d7-11e8-b7ad-0a580ae94006 # ls
test.txt

參考資料

  1. Introducing Container Storage Interface (CSI) Alpha for Kubernetes  – Kubernetes
  2. Introduction – Kubernetes CSI Documentation

撰文:  杜永鴻 迎棧科技工程師