Kubernetes 幾種儲存方式效能對比 (轉載)

portworx發表於2019-12-11

原文來自:

https://blog.fleeto.us/post/kubernetes-storage-performance-comparison/

摘要

本文展示了一個簡單的儲存對比,使用未經效能最佳化的多種儲存提供的儲存捲進行測試和比較。

忽略 Azure 的原生 PVC 或  hostPath ,我們可以得出如下測試結果:

  • Portworx 是 AKS 上最快的容器儲存。
  • Ceph 是私有云叢集上最快的開源儲存後端。對公有云來說,其操作太過複雜,這些多餘的複雜性並沒有能提供更好的測試表現。
  • OpenEBS 的概念很棒,但是其後端需要更多最佳化。

如果你正在執行 Kubernetes,你可能正在使用,或者準備使用動態供給的塊存卷 ,而首當其衝的問題就是為叢集選擇合適的儲存技術。這個事情並不能用一個簡單的測試來做出簡單的回答,告訴你目前市面上最好的技術是什麼。儲存技術的選擇過程中,叢集上執行的負載型別是一個重要的輸入。對於裸金屬叢集來說,需要根據實際用例進行選擇,並整合到自己的硬體之中。公有云中的託管 K8s,例如 AKS、EKS 或者 GKE,都具有開箱可用的塊儲存能力,然而這也不見得就是最好的選擇。有很多因素需要考慮,比如說公有云的 StorageClass 的故障轉移時間太長。例如在 一個針對 AWS EBS 的故障測試中,載入了卷的 Pod 用了超過五分鐘才成功的在另一個節點上啟動。Portworx 或者 OpenEBS 這樣的雲原生儲存產品,正在嘗試解決這類問題。

本文的目標是使用最常見的 Kubernetes 儲存方案,進行基本的效能對比。我覺得在 Azure AKS 上使用下列後端:

  • AKS 原生 Storageclass:Azure native premium
  • 使用 cStor 後端的 OpenEBS
  • Portworx
  • Heketi 管理的 Gluster
  • Rook 管理的 Ceph

現在我們來介紹每種儲存後端,並交代一下安裝過程,然後進入 AKS 測試環境進行測試,最後得出結果。

儲存

這一節中介紹測試中用到的儲存方案,包含安裝過程以及該方案的優缺點。

Azure 原生 StorageClass

我選擇這一方案的動機是以此作為所有測試的基線。這個方案 應該 提供最佳效能。Azure 動態的建立託管磁碟,並把它們對映到 K8s 的虛擬機器中,最終成為 Pod 的儲存卷。

這個方案很方便,什麼多餘的步驟都不需要。建立一個新的 AKS 叢集之後,就自動提供了兩個預定義的 StorageClass,分別是  default 和  managed-premium ,premium 使用的是基於 SSD 的高效能低延遲磁碟。

$ kubectl get storageclasses
NAME                PROVISIONER                AGEdefault(default)   kubernetes.io/azure-disk   8mmanaged-premium     kubernetes.io/azure-disk   8m$ kubectl get pvc
NAME              STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
dbench-pv-claim   Bound     pvc-e7bd34a4-1dbd-11e9-8726-ae508476e8ad   1000Gi     RWO            managed-premium   10s$ kubectl get po
NAME           READY     STATUS              RESTARTS   AGE
dbench-w7nqf   0/1ContainerCreating029s

優點

AKS 開箱即用。

缺點

故障轉移非常緩慢,有時需要十分鐘以後,儲存卷才能重新掛載到不同節點上的 Pod 裡。

OpenEBS

對我來說 OpenEBS 是個全新事物,因此我很有興趣做他的測試。他提出了一個新的 Container Attached Storage(容器掛載儲存) 概念,這是一個基於微服務的儲存控制器,以及多個基於微服務的儲存副本。他和 Portworx 同樣,屬於雲原生儲存分類的成員。

它是一個完全開源的方案,目前提供兩種後端——Jiva 和 cStor。我最開始選擇的是 Jiva,後來切換到 cStor。cStor 有很多長處,例如他的控制器和副本被部署到單一的 OpenEBS 所在的名稱空間之中,能夠管理原始磁碟等。每個 K8s 卷都有自己的儲存控制器,能在節點儲存容量的許可範圍內對儲存進行擴充套件。

在 AKS 上執行

在 AKS 上的安裝非常容易。

  1. 連線到所有 K8s 節點上,安裝 iSCSI,這是因為他需要使用 iSCSI 協議在 K8s 節點之間進行 Pod 和控制器的連線。
    apt-get update
    apt install -y open-iscsi
  2. 使用一個 YAML 定義在 K8s 叢集上完成部署:
    kubectl apply -f 
  3. 下一步,OpenEBS 控制器發現了節點中的所有磁碟。但是我必須手工標識出我附加的 AWS 託管磁碟。
    $ kubectl get disk
    NAME                                      AGE
    disk-184d99015253054c48c4aa3f17d137b15mdisk-2f6bced7ba9b2be230ca5138fd0b07f15mdisk-806d3e77dd2e38f188fdaf9c46020bdc5m
  4. 然後把這些磁碟加入 StoragePoolClaim,這個物件會在 StorageClass 中進行引用:
    ---apiVersion: storage.k8s.io/v1
    kind:StorageClassmetadata:
      name: openebs-custom
      annotations:
        openebs.io/cas-type: cstor
        cas.openebs.io/config?
          - name:StoragePoolClaim
            value:"cstor-disk"provisioner: openebs.io/provisioner-iscsi---apiVersion: openebs.io/v1alpha1
    kind:StoragePoolClaimmetadata:
      name: cstor-disk
    spec:
      name: cstor-disk
      type: disk
      maxPools:3
      poolSpec:
        poolType: striped
      disks:
        diskList:
        - disk-2f6bced7ba9b2be230ca5138fd0b07f1
        - disk-806d3e77dd2e38f188fdaf9c46020bdc
        - disk-184d99015253054c48c4aa3f17d137b1

完成這些步驟之後,就可以用 K8s 的 PVC 來動態的建立儲存捲了。

優點

  • 開源
  • Maya 在資源使用的視覺化方面做得非常好。可以在 K8s 中部署多個服務,方便的為叢集的各方面資料設定監控和日誌。對於排錯工作來說,這十分重要。
  • CAS 概念:我非常欣賞這一概念,我相信這是未來的趨勢。
  • OpenEBS 社群:在社群中我的任何問題都能在幾分鐘內得到解決。Slack 上的團隊非常有幫助。

缺點

  • 不成熟:OpenEBS 還很年輕,目前還沒有釋出穩定版。核心團隊還在進行後端的最佳化,未來幾個月裡會對效能做出很大提升。
  • Kubelet 和儲存控制器之間的 iSCSI 連線是透過 K8s Service 進行的,這在 Tungsten Fabric 之類的 CNI 外掛環境中可能會出問題。
  • 需要在 K8s 節點上安裝額外的軟體(iSCSI),這對於託管叢集來說非常不便。

注:OpenEBS 團隊對我的案例場景進行了調整:

Portworx

Portworx 是另一個面向 Kubernetes 的容器原生儲存方案,它專注於高度分散式的環境。這是一個主機可定址的儲存,每個卷都直接對映到掛在的主機上。他提供了基於應用 I/O 型別的自動微調能力。 官方網站 提供了更多資訊。不幸的是,它也是本文中唯一的非開源產品。然而它提供了 3 節點的免費試用。

在 AKS 上執行

在 AKS 上的安裝同樣簡單,我用了他們 網站 提供的生成器。

azure0
$ kubectl get pods -o wide -n kube-system -l name=portworx
NAME             READY     STATUS    RESTARTS   AGE       IP          NODE                       NOMINATED NODE
portworx-g9csq   1/1Running014m10.0.1.66   aks-agentpool-20273348-2<none>portworx-nt2lq   1/1Running014m10.0.1.4    aks-agentpool-20273348-0<none>portworx-wcjnx   1/1Running014m10.0.1.35   aks-agentpool-20273348-1<none>

為 PVC 建立一個 StorageClass,定義高優先順序,以及三個副本:

root@aks-agentpool-20273348-0:~# kubectl get storageclass -o yaml portworx-scapiVersion: storage.k8s.io/v1
kind:StorageClassmetadata:
  creationTimestamp:2019-01-28T21:10:28Z
  name: portworx-sc
  resourceVersion:"55332"
  selfLink:/apis/storage.k8s.io/v1/storageclasses/portworx-sc
  uid:23455e40-2341-11e9-bfcb-a23b1ec87092
parameters:
  priority_io: high
  repl:"3"provisioner: kubernetes.io/portworx-volume
reclaimPolicy:DeletevolumeBindingMode:Immediate

優點

  • 部署方便:生成器包含配置細節。
  • 不像 Ceph 和 Glusterfs 那樣需要進行額外配置。
  • 雲原生儲存:公有云和裸金屬都可以執行。
  • 儲存級別感知和應用感知的 I/O 微調。

缺點

  • 閉源:商業解決方案

GlusterFS Heketi

GlusterFS 是知名的開源儲存方案,是由 Redhat 提供的開源儲存方案。 Heketi 是 GlusterFS 的 RESTful 卷管理介面。它提供了易用的方式為 GlusterFS 卷提供了動態供給的功能。如果沒有 Heketi 的輔助,就只能手工建立 GlusterFS 卷並對映到 K8s PV 了。關於 GlusterFS 的更多資訊,請閱讀 官方文件 。

在 AKS 上執行

根據 Heketi 的 快速入門 文件進行部署。

  1. 參照 樣例 ,建立一個包含磁碟和主機名的拓撲檔案。
  2. Heketi 主要的開發和測試都在基於 RHEL 的作業系統上,我在 AKS 上使用 Ubuntu 主機時,出現了核心模組路徑錯誤的問題,我提交了一個 PR 來修正這個問題。

    ~~~ +++ b/deploy/kube-templates/glusterfs-daemonset.yaml @@ -67,7 +67,7 @@ spec: mountPath: “/etc/ssl” readOnly: true – name: kernel-modules

    name: kernel-modules hostPath:

    mountPath: “/usr/lib/modules”

    mountPath: “/lib/modules” readOnly: true securityContext: capabilities: {} @@ -131,4 +131,4 @@ spec: path: “/etc/ssl”

    path: “/usr/lib/modules”

    path: “/lib/modules” ~~~

  3.  

    我在 AKS 環境中遇到的另一個問題是一個非空磁碟,所以我用  wipefs 為 glusterfs 進行清理。這個磁碟並未用過。

     

    $ wipefs -a /dev/sdc /dev/sdc: 8 bytes were erased at offset 0x00000218 (LVM2_member): 4c 56 4d 32 20 30 30 31

  4. 最後執行  gk-deploy -g -t topology.json ,會在每個節點上執行 Heketi 控制器管理之下的 GlusterFS Pod。
    $ kubectl get po -o wide
    NAME                     READY   STATUS    RESTARTS IP        NODE                       NOMINATED NODE
    glusterfs-fgc8f          1/1Running010.0.1.35  aks-agentpool-20273348-1glusterfs-g8ht6          1/1Running010.0.1.4   aks-agentpool-20273348-0glusterfs-wpzzp          1/1Running010.0.1.66  aks-agentpool-20273348-2heketi-86f98754c-n8qfb   1/1Running010.0.1.69  aks-agentpool-20273348-2

    然後我遇到了新問題。K8s 控制面無法使用 Heketi 的  restURL 。我測試了一下 kube dns 的記錄,pod IP 和 svc IP 都沒有生效。最後只能手工使用 Heketi CLI 來建立儲存卷。 

$ export HEKETI_CLI_SERVER=| kubectl create -f -persistentvolume/glusterfs-efb3b155 created
$ kubectl get pv
NAME                 CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
glusterfs-efb3b155   10Gi       RWX            RetainAvailable

然後把現存 PV 對映為 PVC,載入給測試 工具 進行測試。

kind:PersistentVolumeClaimapiVersion: v1
metadata:
  name: glusterfs-efb3b155
spec:
  accessModes:
    -ReadWriteMany
  storageClassName:""
  resources:
    requests:
      storage:10Gi
  volumeName: glusterfs-efb3b155
$ kubectl get pvc
NAME                 STATUS    VOLUME               CAPACITY   ACCESS MODES   STORAGECLASS   AGE
glusterfs-efb3b155   Bound     glusterfs-efb3b155   10Gi       RWX                           36m

Heketi 的更多輸出:

$ gluster volume info vol_efb3b15529aa9aba889d7900f0ce9849VolumeName: vol_efb3b15529aa9aba889d7900f0ce9849Type:ReplicateVolume ID:96fde36b-e389-4dbe-887b-baae32789436Status:StartedSnapshotCount:0Number of Bricks:1 x 3=3Transport-type: tcpBricks:Brick1:10.0.1.66:/var/lib/heketi/mounts/vg_5413895eade683e1ca035760c1e0ffd0/brick_cd7c419bc4f4ff38bbc100c6d7b93605/brickBrick2:10.0.1.35:/var/lib/heketi/mounts/vg_3277c6764dbce56b5a01426088901f6d/brick_6cbd74e9bed4758110c67cfe4d4edb53/brickBrick3:10.0.1.4:/var/lib/heketi/mounts/vg_29d6152eeafc57a707bef56f091afe44/brick_4856d63b721d794e7a4cbb4a6f048d96/brickOptionsReconfigured:transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off
$ kubectl get svc
NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
heketi                     ClusterIP192.168.101.75<none>8080/TCP   5hheketi-storage-endpoints   ClusterIP192.168.103.66<none>1/TCP      5h$ kubectl get endpoints
NAME                       ENDPOINTS                            AGE
heketi                     10.0.1.69:80805hheketi-storage-endpoints   10.0.1.35:1,10.0.1.4:1,10.0.1.66:15hkubernetes                 172.31.22.152:4431droot@aks-agentpool-20273348-0:~# kubectl get endpoints heketi-storage-endpoints -o yamlapiVersion: v1
kind:Endpointsmetadata:
  creationTimestamp:2019-01-29T15:14:28Z
  name: heketi-storage-endpoints  namespace:default
  resourceVersion:"142212"
  selfLink:/api/v1/namespaces/default/endpoints/heketi-storage-endpoints
  uid:91f802eb-23d8-11e9-bfcb-a23b1ec87092
subsets:- addresses:
  - ip:10.0.1.35
  - ip:10.0.1.4
  - ip:10.0.1.66
  ports:
  - port:1
    protocol: TCP

優點

  • 久經考驗的儲存方案。
  • 比 Ceph 輕量。

缺點

  • Heketi 在公有云上表現不佳。在私有云上表現良好,安裝會方便一些。
  • 並非為結構化資料設計,例如 SQL 資料庫。然而可以使用 GlusterFS 為 資料庫 提供備份和恢復支援。

Ceph Rook

我在 OpenStack 私有云上嘗試過安裝和執行 Ceph。它需要為特定硬體定製引數,根據資料型別設計 pg 組、SSD 分割槽和 CRUSH 圖等。所以第一次聽說在 3 節點的 K8s 叢集上執行 Ceph 的時候,我不太相信它能工作。結果 Rook 的編排工具讓我印象深刻,它把所有的步驟和 K8s 的編排能力結合在一起,讓安裝變得非常簡便。

在 AKS 上執行

Rook 的預設安裝無需任何特定步驟,如果沒什麼高階配置,會非常簡單。

  1. 我使用的是 Ceph 快速入門指南

  2. 為 AKS 配置  FLEXVOLUME_DIR_PATH ,這是因為它需要  /etc/kubernetes/volumeplugins/ ,而不是 Ubuntu 中預設的  /usr/libexec ,沒有這個步驟,Kubelet 就 無法載入 PVC 了。

    ~~~ diff –git a/cluster/examples/kubernetes/ceph/operator.yaml b/cluster/examples/kubernetes/ceph/operator.yaml index 73cde2e..33f45c8 100755 — a/cluster/examples/kubernetes/ceph/operator.yaml +++ b/cluster/examples/kubernetes/ceph/operator.yaml @@ -431,8 +431,8 @@ spec: # – name: AGENT_MOUNT_SECURITY_MODE # value: “Any” # Set the path where the Rook agent can find the flex volumes

    • # – name: FLEXVOLUME_DIR_PATH
    • # value: “

    • – name: FLEXVOLUME_DIR_PATH
    • value: “/etc/kubernetes/volumeplugins” # Set the path where kernel modules can be found # – name: LIB_MODULES_DIR_PATH # value: “

      “ ~~~

  3. 還要在  deviceFilter 中指定要使用的裝置,這裡是  /dev/sdc 。

    ~~~ diff –git a/cluster/examples/kubernetes/ceph/cluster.yaml b/cluster/examples/kubernetes/ceph/cluster.yaml index 48cfeeb..0c91c48 100755 — a/cluster/examples/kubernetes/ceph/cluster.yaml +++ b/cluster/examples/kubernetes/ceph/cluster.yaml @@ -227,7 +227,7 @@ spec: storage: # cluster level storage configuration and selection useAllNodes: true useAllDevices: false

    • deviceFilter:
    • deviceFilter: “^sdc” location: config: ~~~
  4. 安裝之後,建立一個 Ceph block pool,以及 StorageClass,使用如下配置。
    apiVersion: ceph.rook.io/v1
    kind:CephBlockPoolmetadata:
      name: replicapool  namespace: rook-ceph
    spec:
      failureDomain: host
      replicated:
        size:3---apiVersion: storage.k8s.io/v1
    kind:StorageClassmetadata:
       name: rook-ceph-block
    provisioner: ceph.rook.io/block
    parameters:
      blockPool: replicapool
      clusterNamespace: rook-ceph
      fstype: xfs
    reclaimPolicy:Retain
  5. 最後使用部署 工具 進行檢查。

ceph status
  cluster:
    id:     bee70a10-dce1-4725-9285-b9ec5d0c3a5e
    health: HEALTH_OK
  services:
    mon:3 daemons, quorum c,b,a
    mgr: a(active)
    osd:3 osds:3 up,3in
  data:
    pools:0 pools,0 pgs
    objects:0  objects,0 B
    usage:3.0GiB used,3.0TiB/3.0TiB avail
    pgs:[root@aks-agentpool-27654233-0/]#[root@aks-agentpool-27654233-0/]#[root@aks-agentpool-27654233-0/]# ceph osd status+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+| id |           host           |  used | avail | wr ops | wr data | rd ops | rd data |   state   |+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+|0| aks-agentpool-27654233-0|1025M|1021G|0|0|0|0| exists,up ||1| aks-agentpool-27654233-1|1025M|1021G|0|0|0|0| exists,up ||2| aks-agentpool-27654233-2|1025M|1021G|0|0|0|0| exists,up |+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+

優點

  • 在大型生產環境上的健壯儲存系統。
  • Rook 很好的簡化了生命週期管理。

缺點

  • 複雜:更加重量級,也不太適合在公有云上執行。在私有云上的執行可能更加合適。

AKS 測試環境

我用 3 個虛擬機器建立了基本的 Azure AKS 叢集。為了連線到 Premium SSD 上,我只能使用 type E 以上級別的虛擬機器。因此我選擇了 Standard_E2s_v3 ,其上配備了 2 vCPU 以及 16GB 的記憶體。

在 AKS 叢集所在的資源足中,可以看到所有的虛擬機器、網路介面等資源。在這裡建立 3 個 1TB 的 Premium SSD 儲存,並手工掛載到每個虛擬機器上。

這樣在每個例項上,我都有 1TB 的空磁碟。Azure 的頁面上,根據我們選擇的虛擬機器和磁碟尺寸來看,效能應該有 5000 IOPS 以及 200MB/s 的吞吐量。最後一節會顯示我們的真實結果。

效能結果

注意:每種儲存的結果並不能作為獨立的評估結果,但是其比較情況是可以參考的。有很多種對比測試的方法,這是最簡單的一種。

為了執行測試,我決定使用現成的測試工具 Dbench ,它是一個 k8s 的 YAML 檔案,會使用 FIO 執行 8 個測試用例。可以在 Dockerfile 中 指定不同測試 :

  • 隨機讀寫頻寬。
  • 隨機讀寫 IOPS。
  • 讀寫延遲。
  • 順序讀寫。
  • 混合讀寫 IOPS。

所有測試的結果可以在 Github 上找到。

隨機讀寫頻寬

隨機讀寫測試表明,GlusterFS、Ceph 以及 Portworx 的讀取效能比 AWS 本地盤的  hostPath 快了幾倍。讀快取是罪魁禍首。GlusterFS 和 Portworx 的寫入更快,其效率直逼本地磁碟。

隨機讀寫 IOPS

隨機 IOPS 測試中,Portworx 和 Ceph 表現最好。Portworx 在寫入方面獲得了接近 Azure 原生 PVC 的 IOPS。

讀寫延遲

延遲測試的結果比較有趣,Azure 原生 PVC 比多數其它儲存都差。Portworx 和 Ceph 表現最好。寫入方面,GlusterFS 要優於 Ceph。OpenEBS 的延遲相對來說非常的高。

順序讀寫

順序讀寫的結果和前面的隨機測試差不多,然而 Cpeh 在讀取方面比 GlusterFS 快了一倍多。寫入結果基本一致,只有 OpenEBS 表現奇差。

混合讀寫 IOPS

最後一個測試用例檢查的是混合讀寫情況下的 IOPS,Portworx 和 Ceph 都給出了優於 Azure 原生 PVC 的結果。

結論

本文展示了一個簡單的儲存對比,使用未經效能最佳化的多種儲存提供的儲存捲進行測試和比較。建議關注本文所述方法,不建議直接採用結果進行判斷。

忽略 Azure 的原生 PVC 或  hostPath ,我們可以得出如下測試結果:

  • Portworx 是 AKS 上最快的容器儲存。
  • Ceph 是私有云叢集上最快的開源儲存後端。對公有云來說,其操作太過複雜,這些多餘的複雜性並沒有能提供更好的測試表現。
  • OpenEBS 的概念很棒,但是其後端需要更多最佳化。

調整效能資料的測試規模應該會很有意思。另外值得關注的對比就是 CPU 和記憶體的消耗。我會持續關注,並分享更多。


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

相關文章