非易失性存儲卷概述
非易失性存儲卷是由Intel推出的一種持久化內(nèi)存PMEM(Persistent Memory)產(chǎn)品,通過經(jīng)濟地擴展內(nèi)存容量 ,增加對持久數(shù)據(jù)的低延遲訪問,從而將一流的內(nèi)存和存儲特性集成于一個產(chǎn)品中。本文介紹ACK中非易失性存儲卷的使用方式和使用示例。
背景信息
PMEM是一類高性能、數(shù)據(jù)可持久、內(nèi)存存儲的統(tǒng)稱。PMEM位于內(nèi)存總線上,支持像DRAM一樣訪問數(shù)據(jù),具備與DRAM相當(dāng)?shù)乃俣群脱舆t,而且兼具NAND閃存的非易失性。主要優(yōu)勢包括:
訪問延遲低于閃存SSD的訪問延遲。
吞吐量提高,超過閃存存儲。
價格比DRAM便宜,節(jié)約成本。
PMEM可緩存,解決PCIe互連不能在CPU中緩存的問題。
可實時訪問數(shù)據(jù),支持對大型數(shù)據(jù)集進行超高速訪問。
斷電后,數(shù)據(jù)仍保留在內(nèi)存中,例如閃存。
RE6P配合第一代PMEM,RE7P配合第二代PMEM。
第一代PMEM支持的實例規(guī)格族有以下兩類:
持久內(nèi)存型實例規(guī)格族re6p,更多信息,請參見持久內(nèi)存型實例規(guī)格族re6p。
持久內(nèi)存型彈性裸金屬服務(wù)器實例規(guī)格族ebmre6p,更多信息,請參見持久內(nèi)存型彈性裸金屬服務(wù)器實例規(guī)格族ebmre6p。
第二代PMEM支持內(nèi)存增強型實例規(guī)格族re7p,更多信息,請參見內(nèi)存型。
非易失性存儲卷的使用方式
目前ACK集群已經(jīng)支持設(shè)備的生命周期管理,通過Alibaba Cloud CSI Driver,您可以以聲明式的方式對資源進行分配、掛載、使用。
在ACK中,非易失性存儲卷的使用方式有以下兩種:
PMEM-LVM方式(無侵入的塊存儲使用方式)
您無需修改應(yīng)用,直接聲明即可使用。此方案的原則是把節(jié)點上PMEM資源統(tǒng)一成VolumeGroup,然后通過聲明PVC類型和容量,使用PMEM-LVM。對無服務(wù)器化應(yīng)用,CICD短生命周期高速臨時存儲,以及低延遲高吞吐的數(shù)據(jù)類應(yīng)用,無需修改應(yīng)用,即可實現(xiàn)IO性能的2~10倍的提升。更多使用示例,請參考使用非易失性存儲提升讀寫性能。
PMEM-直接內(nèi)存(Direct Memory)訪問方式
為了達到極致的,可以媲美DRAM的訪問性能,對應(yīng)用的內(nèi)存分配部分函數(shù)做有限的修改,可以實現(xiàn)對PMEM設(shè)備的直接訪問。對內(nèi)存數(shù)據(jù)庫Redis、HANA等大內(nèi)存低成本需求,同時滿足對TB級別的DRAM和成本的訴求,降低了內(nèi)存成本30%~50%。更多使用示例,請參考使用非易失性存儲卷的直接內(nèi)存訪問方式部署Redis數(shù)據(jù)庫。
邏輯卷管理LVM方式:在ACK環(huán)境下,非易失性存儲作為塊存儲或文件系統(tǒng)方式訪問,無任何應(yīng)用侵入和修改,讀寫性能相比SSD提升2~10倍。
直接內(nèi)存方式:在ACK環(huán)境下,非易失性存儲作為直接內(nèi)存訪問,需要修改應(yīng)用適配PMEM SDK做內(nèi)存分配的代碼,達到接近內(nèi)存訪問的吞吐和時延。
表 1. PMEM和普通SSD對比
方式 | 碎片化 | 在線擴容 | 持久化 | 應(yīng)用修改 | 時延 (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對非易失性內(nèi)存支持方案的系統(tǒng)組件包含:
CSI-Plugin:實現(xiàn)PMEM設(shè)備初始化,卷的具體創(chuàng)建、刪除操作,實現(xiàn)掛載、卸載操作。
CSI-Provisioner:感知并發(fā)起卷的創(chuàng)建、刪除操作。
CSI-Scheduler:容量調(diào)度 (ACK調(diào)度器內(nèi)置)。
在部署CSI-Plugin時,您需注意:
在節(jié)點加上標簽
pmem.csi.alibabacloud.com
后才會啟用設(shè)備自運維。pmem.csi.alibabacloud.com: lvm
表示此節(jié)點使用LVM方式提供PV卷。pmem.csi.alibabacloud.com: direct
表示此節(jié)點使用內(nèi)存訪問方式提供PV卷。
創(chuàng)建ACK集群。
ACK集群中添加PMEM類型的ECS節(jié)點實例,例如:ecs.ebmre6p.26xlarge。具體操作,請參見創(chuàng)建ACK托管集群。
配置PMEM節(jié)點類型。
您所添加的節(jié)點需要配置上相應(yīng)的標簽,方可啟用PMEM CSI的掛載能力。
給節(jié)點添加以下Label。
pmem.csi.alibabacloud.com/type: direct
或:
pmem.csi.alibabacloud.com/type: lvm
部署CSI PMEM插件。
部署CSI-Plugin。
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
部署CSI-Provisioner。
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
部署StorageClass。
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
使用示例
創(chuàng)建塊存儲類型數(shù)據(jù)卷
使用以下內(nèi)容,創(chuàng)建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
為了定向?qū)VC調(diào)度到某個非易失性存儲卷節(jié)點,可以配置
annotations: volume.kubernetes.io/selected-node
。使用以下內(nèi)容,創(chuàng)建應(yīng)用負載。
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
查看結(jié)果。
執(zhí)行以下命令查看創(chuàng)建的PVC。
kubectl get pvc
預(yù)期輸出:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pmem-lvm Bound disk-**** 10Gi RWO pmem-lvm 10m
執(zhí)行以下命令查看創(chuàng)建的Pod。
kubectl get pod
預(yù)期輸出:
NAME READY STATUS RESTARTS AGE sts-lvm-0 1/1 Running 0 10m
執(zhí)行以下命令進入應(yīng)用查看掛載路徑詳情。
kubectl exec -ti sts-lvm-0 -- df /data
預(yù)期輸出:
Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/pmemvgregion0-disk--**** 10255636 36888 10202364 1% /data
由預(yù)期輸出可見已經(jīng)動態(tài)創(chuàng)建了一個塊存儲數(shù)據(jù)卷,并掛載給Pod使用。
創(chuàng)建直接內(nèi)存類型數(shù)據(jù)卷
使用以下內(nèi)容,創(chuàng)建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
為了定向?qū)VC調(diào)度到某個非易失性存儲卷節(jié)點,可以配置
annotations: volume.kubernetes.io/selected-node
。使用以下內(nèi)容,創(chuàng)建應(yīng)用負載。
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
查看結(jié)果。
執(zhí)行以下命令查看PVC。
kubectl get pvc pmem-direct
預(yù)期輸出:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pmem-direct Bound disk-**** 9Gi RWO pmem-direct 17m
執(zhí)行以下命令查看Pod。
kubectl get pod
預(yù)期輸出:
NAME READY STATUS RESTARTS AGE sts-direct-0 1/1 Running 0 17m
執(zhí)行以下命令進入應(yīng)用查看掛載目錄詳情。
kubectl exec -ti sts-lvm-0 -- df /data
預(yù)期輸出:
Filesystem 1K-blocks Used Available Use% Mounted on /dev/pmem0 9076344 36888 9023072 1% /data
由預(yù)期輸出可見已經(jīng)動態(tài)創(chuàng)建了一個PMEM數(shù)據(jù)卷,并掛載給Pod使用。