全部產品
Search
文件中心

Container Service for Kubernetes:非易失性儲存卷概述

更新時間:Apr 10, 2025

非易失性儲存卷可以通過Intel的持久化記憶體PMEM等技術實現。本文介紹ACK中非易失性儲存卷的使用方式和使用樣本。

背景資訊

PMEM(Persistent Memory)是一種高效能、持久性記憶體,位於記憶體匯流排,具備DRAM的速度和延遲,同時具有NAND快閃記憶體的非易失性。主要優勢包括:

  • 訪問延遲低於快閃記憶體SSD的訪問延遲。

  • 輸送量提高,超過快閃記憶體儲存。

  • 價格比DRAM便宜,節約成本。

  • PMEM可緩衝,解決PCIe互連不能在CPU中緩衝的問題。

  • 可即時訪問資料,支援對大型資料集進行超高速訪問。

  • 斷電後,資料仍保留在記憶體中,例如快閃記憶體。

使用方式

ACK叢集支援裝置生命週期管理,通過Alibaba Cloud CSI Driver,您可以聲明式分配、掛載和使用資源。

在ACK中,非易失性儲存卷的使用方式有以下兩種:

  • PMEM-LVM方式(無侵入的Block Storage使用方式)

    非易失性儲存作為Block Storage或檔案系統訪問,無需修改應用,直接聲明即可使用。此方案的原則是把節點上PMEM資源統一成VolumeGroup,然後通過聲明PVC類型和容量,使用PMEM-LVM。

    適用於無伺服器化應用、CICD短生命週期高速臨時儲存、低延遲高吞吐的資料類應用。IO效能可以提升2~10倍。更多樣本請參考使用非易失性儲存提升讀寫效能

  • PMEM-直接記憶體(Direct Memory)訪問方式

    非易失性儲存作為直接記憶體存取,需對應用記憶體配置部分函數做有限修改以適配PMEM SDK,實現對PMEM裝置的直接存取,達到接近記憶體訪問的吞吐和時延。

    適用於記憶體資料庫Redis、HANA等大記憶體低成本需求,可以降低記憶體成本30~50%。更多樣本請參考使用非易失性儲存卷的直接記憶體存取方式部署Redis資料庫

各方式的效能對比如下:

方式

片段化

線上擴容

持久化

應用修改

時延 (4K/RW)

吞吐 (4K/RW)

單盤最大容量(ecs.ebmre6p.26xlarge)

PMEM-LVM

支援

10 us

10W

1536 GB

PMEM-Direct

1.2 us

56W

768 GB

SSD

支援

100 us

1W

32 TB

外掛程式部署

外掛程式說明

ACK對非易失性記憶體支援方案的系統組件包含:

  • CSI-Plugin:實現PMEM裝置初始化,卷的具體建立、刪除操作,實現掛載、卸載操作。

  • CSI-Provisioner:感知並發起卷的建立、刪除操作。

  • CSI-Scheduler:容量調度 (ACK調度器內建)。

部署外掛程式

  1. 在ACK叢集中添加PMEM類型的ECS節點(如ecs.ebmre6p.26xlarge)。具體操作,請參見建立和管理節點池

    第一代PMEM支援持久記憶體型執行個體規格類型系列re6p持久記憶體型ECS Bare Metal Instance執行個體規格類型系列ebmre6p

  2. 為PMEM類型的ECS節點添加標籤,啟用PMEM CSI的掛載能力。

    給節點添加以下Label:

    • pmem.csi.alibabacloud.com:啟用裝置自營運。

    • pmem.csi.alibabacloud.com/type: lvm:表示此節點使用LVM方式提供PV卷。

    • pmem.csi.alibabacloud.com/type: direct:表示此節點使用記憶體訪問方式提供PV卷。

  3. 部署CSI PMEM外掛程式。

    1. 部署CSI-Plugin。

      展開查看部署CSI-Plugin的YAML檔案

      apiVersion: storage.k8s.io/v1
      kind: CSIDriver
      metadata:
        name: localplugin.csi.alibabacloud.com
      spec:
        attachRequired: false
        podInfoOnMount: true
      ---
      kind: DaemonSet
      apiVersion: apps/v1
      metadata:
        name: csi-local-plugin
        namespace: kube-system
      spec:
        selector:
          matchLabels:
            app: csi-local-plugin
        template:
          metadata:
            labels:
              app: csi-local-plugin
          spec:
            tolerations:
              - operator: Exists
            serviceAccount: admin
            priorityClassName: system-node-critical
            hostNetwork: true
            hostPID: true
            containers:
              - name: driver-registrar
                image: registry.cn-hangzhou.aliyuncs.com/acs/csi-node-driver-registrar:v1.3.0-6e9fff3-aliyun
                imagePullPolicy: Always
                args:
                  - "--v=5"
                  - "--csi-address=/csi/csi.sock"
                  - "--kubelet-registration-path=/var/lib/kubelet/csi-plugins/localplugin.csi.alibabacloud.com/csi.sock"
                env:
                  - name: KUBE_NODE_NAME
                    valueFrom:
                      fieldRef:
                        apiVersion: v1
                        fieldPath: spec.nodeName
                volumeMounts:
                  - name: plugin-dir
                    mountPath: /csi
                  - name: registration-dir
                    mountPath: /registration
      
              - name: csi-localplugin
                securityContext:
                  privileged: true
                  capabilities:
                    add: ["SYS_ADMIN"]
                  allowPrivilegeEscalation: true
                image: registry.cn-hangzhou.aliyuncs.com/acs/csi-plugin:v1.20.6-2be29b1-aliyun 
                imagePullPolicy: "Always"
                args :
                  - "--endpoint=$(CSI_ENDPOINT)"
                  - "--v=5"
                  - "--nodeid=$(KUBE_NODE_NAME)"
                  - "--driver=localplugin.csi.alibabacloud.com"
                env:
                  - name: KUBE_NODE_NAME
                    valueFrom:
                      fieldRef:
                        apiVersion: v1
                        fieldPath: spec.nodeName
                  - name: CSI_ENDPOINT
                    value: unix://var/lib/kubelet/csi-plugins/localplugin.csi.alibabacloud.com/csi.sock
                volumeMounts:
                  - name: pods-mount-dir
                    mountPath: /var/lib/kubelet
                    mountPropagation: "Bidirectional"
                  - mountPath: /dev
                    mountPropagation: "HostToContainer"
                    name: host-dev
                  - mountPath: /var/log/
                    name: host-log
            volumes:
              - name: plugin-dir
                hostPath:
                  path: /var/lib/kubelet/csi-plugins/localplugin.csi.alibabacloud.com
                  type: DirectoryOrCreate
              - name: registration-dir
                hostPath:
                  path: /var/lib/kubelet/plugins_registry
                  type: DirectoryOrCreate
              - name: pods-mount-dir
                hostPath:
                  path: /var/lib/kubelet
                  type: Directory
              - name: host-dev
                hostPath:
                  path: /dev
              - name: host-log
                hostPath:
                  path: /var/log/
        updateStrategy:
          rollingUpdate:
            maxUnavailable: 10%
          type: RollingUpdate
      	  
    2. 部署CSI-Provisioner。

      展開查看部署CSI-Provisioner的YAML檔案

      kind: Deployment
      apiVersion: apps/v1
      metadata:
        name: csi-local-provisioner
        namespace: kube-system
      spec:
        selector:
          matchLabels:
            app: csi-local-provisioner
        replicas: 2
        template:
          metadata:
            labels:
              app: csi-local-provisioner
          spec:
            tolerations:
            - operator: "Exists"
            affinity:
              nodeAffinity:
                preferredDuringSchedulingIgnoredDuringExecution:
                - weight: 1
                  preference:
                    matchExpressions:
                    - key: node-role.kubernetes.io/master
                      operator: Exists
            priorityClassName: system-node-critical
            serviceAccount: admin
            hostNetwork: true
            containers:
              - name: external-local-provisioner
                image: registry.cn-hangzhou.aliyuncs.com/acs/csi-provisioner:v1.6.0-b6f763a43-ack
                args:
                  - "--csi-address=$(ADDRESS)"
                  - "--feature-gates=Topology=True"
                  - "--volume-name-prefix=disk"
                  - "--strict-topology=true"
                  - "--timeout=150s"
                  - "--extra-create-metadata=true"
                  - "--enable-leader-election=true"
                  - "--leader-election-type=leases"
                  - "--retry-interval-start=500ms"
                  - "--v=5"
                env:
                  - name: ADDRESS
                    value: /socketDir/csi.sock
                imagePullPolicy: "Always"
                volumeMounts:
                  - name: socket-dir
                    mountPath: /socketDir
              - name: external-local-resizer
                image: registry.cn-hangzhou.aliyuncs.com/acs/csi-resizer:v0.3.0
                args:
                  - "--v=5"
                  - "--csi-address=$(ADDRESS)"
                  - "--leader-election"
                env:
                  - name: ADDRESS
                    value: /socketDir/csi.sock
                imagePullPolicy: "Always"
                volumeMounts:
                  - name: socket-dir
                    mountPath: /socketDir/
            volumes:
              - name: socket-dir
                hostPath:
                  path: /var/lib/kubelet/csi-plugins/localplugin.csi.alibabacloud.com
                  type: DirectoryOrCreate
      	  
    3. 部署StorageClass。

      展開查看部署StorageClass的YAML檔案

      apiVersion: storage.k8s.io/v1
      kind: StorageClass
      metadata:
          name: csi-pmem-direct
      provisioner: localplugin.csi.alibabacloud.com
      mountOptions:
      - dax
      parameters:
          volumeType: PMEM
          pmemType: "direct"
      reclaimPolicy: Delete
      volumeBindingMode: WaitForFirstConsumer
      allowVolumeExpansion: true
      
      ---
      apiVersion: storage.k8s.io/v1
      kind: StorageClass
      metadata:
          name: pmem-lvm
      provisioner: localplugin.csi.alibabacloud.com
      mountOptions:
      - dax
      parameters:
          volumeType: PMEM
          nodeAffinity: "true"
          pmemType: "lvm"
      reclaimPolicy: Delete
      volumeBindingMode: WaitForFirstConsumer
      allowVolumeExpansion: true
      	  	  
      	  

使用樣本

建立Block Storage類型資料卷

  1. 使用以下YAML,建立PVC。

    添加annotations: volume.kubernetes.io/selected-node以定向調度PVC到某個非易失性儲存卷節點。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      annotations:
        volume.kubernetes.io/selected-node: cn-zhangjiakou.192.168.XX.XX
      name: pmem-lvm
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
      storageClassName: pmem-lvm
  2. 使用以下YAML,建立應用負載。

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: sts-lvm
      labels:
        app: busybox-lvm
    spec:
      selector:
        matchLabels:
          app: busybox-lvm
      serviceName: "busybox"
      template:
        metadata:
          labels:
            app: busybox-lvm
        spec:
          containers:
          - name: busybox
            image: busybox
            command: ["sh", "-c"]
            args: ["sleep 10000"]
            volumeMounts:
              - name: pmem-pvc
                mountPath: "/data"
          volumes:
            - name: pmem-pvc
              persistentVolumeClaim:
                claimName: pmem-lvm
  3. 查看結果。

    • 查看建立的PVC。

      kubectl get pvc 

      預期輸出:

      NAME               STATUS    VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS              AGE
      pmem-lvm           Bound    disk-****   10Gi       RWO            pmem-lvm                  10m
    • 查看建立的Pod。

      kubectl get pod

      預期輸出:

      NAME                                READY   STATUS    RESTARTS   AGE
      sts-lvm-0                           1/1     Running   0          10m
  4. 進入應用,查看掛載路徑詳情。

    kubectl exec -ti sts-lvm-0 -- df /data

    預期輸出如下,可以看到已經動態建立了一個Block Storage資料卷,並掛載給Pod使用。

    Filesystem                            1K-blocks  Used   Available Use% Mounted on
    /dev/mapper/pmemvgregion0-disk--****  10255636   36888  10202364  1%   /data

建立直接記憶體類型資料卷

  1. 使用以下YAML,建立PVC。

    添加annotations: volume.kubernetes.io/selected-node以定向調度PVC到某個非易失性儲存卷節點。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      annotations:
        volume.kubernetes.io/selected-node: cn-zhangjiakou.192.168.XX.XX
      name: pmem-direct
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 9Gi
      storageClassName: pmem-direct
  2. 使用以下YAML,建立應用負載。

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: sts-direct
      labels:
        app: busybox-direct
    spec:
      selector:
          matchLabels:
            app: busybox-direct
      serviceName: "busybox"
      template:
        metadata:
          labels:
            app: busybox-direct
        spec:
          containers:
          - name: busybox
            image: busybox
            command: ["sh", "-c"]
            args: ["sleep 1000"]
            volumeMounts:
              - name: pmem-pvc
                mountPath: "/data"
          volumes:
            - name: pmem-pvc
              persistentVolumeClaim:
                claimName: pmem-direct
  3. 查看結果。

    • 查看PVC。

      kubectl get pvc pmem-direct

      預期輸出:

      NAME          STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
      pmem-direct   Bound    disk-****   9Gi        RWO            pmem-direct    17m
    • 查看Pod。

      kubectl get pod

      預期輸出:

      NAME                                READY   STATUS    RESTARTS   AGE
      sts-direct-0                        1/1     Running   0          17m
  4. 進入應用,查看掛載路徑詳情。

    kubectl exec -ti sts-direct-0 -- df /data

    預期輸出如下,可以看到已經動態建立了一個PMEM資料卷,並掛載給Pod使用。

    Filesystem     1K-blocks  Used    Available  Use%  Mounted on
    /dev/pmem0     9076344    36888   9023072    1%    /data