使用CNFS管理CPFS通用版动态存储卷

更新时间:
复制为 MD 格式

ACK 可通过 CNFS 将 CPFS 通用版文件系统挂载为动态存储卷。配置 StorageClass 后,每个工作负载可自动获得独立的 PV,数据隔离,无需手动管理存储。

流程指引

使用动态存储卷时,应用创建 PVC 后,系统会根据指定的 StorageClass 自动创建存储卷和对应的 PV。无需预先分配,支持自动扩容。

在集群中挂载 CPFS 动态存储卷的主要流程如下。

image

  1. 创建CNFS:在集群中“注册”已有的CPFS文件系统。

  2. 创建StorageClass:定义动态存储卷的供应模板(如回收策略、挂载参数等),并引用CNFS对象作为其后端。

  3. 创建应用:创建PVC并指定使用该StorageClass。系统将自动创建PV并与PVC绑定,随后创建Pod并挂载存储卷。

准备工作

  • 根据集群版本,确认相关组件符合条件。

    如需升级集群,请参见升级集群

    1.26及以上

    • 确保CSI组件版本为v1.32.2-757e24b-aliyun及以上。

      如需升级CSI组件,请参见管理CSI组件
    • 已安装cnfs-nas-daemon组件,并在csi-plugin组件的FeatureGate中增加AlinasMountProxy=true以启用cnfs-nas-daemon,请参见管理cnfs-nas-daemon组件

    1.26以下

    • 确保CSI组件版本为v1.24.11-5221f79-aliyun及以上。

      如需升级CSI组件,请参见管理CSI组件
    • 已安装客户端依赖并重启csi-plugin组件。

      展开查看操作步骤

      需配置csi-pluginConfigMap,使得csi-plugin启动时自动安装客户端依赖。

      1. 检查是否存在名为csi-pluginConfigMap。

        kubectl -n kube-system get cm csi-plugin

        存在

        如果已有名为csi-pluginConfigMap,更新该ConfigMap。

        kubectl edit configmap csi-plugin -n kube-system

        data下新增cnfs-client-properties字段,并配置cpfs-efc=true以安装客户端依赖。

        ...
        data:
          cnfs-client-properties: |
            cpfs-efc=true   # csi-plugin启动时会安装客户端依赖

        不存在

        如果没有名为csi-pluginConfigMap,在kube-system命名空间下创建ConfigMap。

        cat <<EOF | kubectl apply -f -
        apiVersion: v1
        kind: ConfigMap
        metadata:
          name: csi-plugin
          namespace: kube-system
        data:
          cnfs-client-properties: |
            cpfs-efc=true   # csi-plugin启动时会安装相关依赖。
        EOF
      2. 重启csi-plugin组件。

        kubectl -n kube-system rollout restart daemonset csi-plugin
  • 已创建与集群处于同一VPC下的CPFS通用版文件系统和对应的协议服务,并获取挂载点地址,详见创建协议服务并获取挂载地址

    建议CPFS的协议服务挂载点和集群处于同一交换机下,以提升使用性能。

使用限制

  • 仅支持部分地域,请参见CPFS通用版开服地域

  • 仅支持通过NFS协议挂载,不支持通过POSIX协议挂载。

  • 仅支持挂载到x86架构的节点上。

  • 不支持跨VPC挂载,仅支持挂载到同一VPC的集群中。

  • 不支持挂载到操作系统为ContainerOS的节点上。

步骤一:创建CNFS

创建CNFS对象,在集群中“注册”已有的CPFS文件系统。

  1. 参见代码,创建cnfs.yaml

    apiVersion: storage.alibabacloud.com/v1beta1
    kind: ContainerNetworkFileSystem
    metadata:
      name: cnfs-nfs-cpfs
    spec:
      # 指定后端存储类型为 CPFS
      type: cpfs  
      # 删除此 CNFS 时,后端的 CPFS 文件系统不会被删除
      reclaimPolicy: Retain  
      parameters:
        # CPFS 的协议服务的挂载点域名
        protocolServer: cpfs-xxxx.xxxx.cpfs.aliyuncs.com  
        # 使用 NFS 客户端进行挂载
        useClient: NFSClient  

    参数说明:

    参数

    说明

    spec.type

    后端存储类型,此处固定为cpfs

    spec.reclaimPolicy

    回收策略。仅支持Retain,删除CNFS时,CPFS文件系统不会被删除。

    spec.parameters.protocolServer

    CPFS通用版协议服务导出目录的挂载地址中的挂载点域名。

    spec.parameters.useClient

    配置为NFSClient,使用NFS客户端进行挂载。

  2. 创建CNFS。

    kubectl apply -f cnfs.yaml
  3. 查看CNFS状态,确认为Available

    kubectl get cnfs cnfs-nfs-cpfs -o jsonpath='{.status.status}'

步骤二:创建StorageClass

创建StorageClass,作为动态供应的模板,并引用此前创建的CNFS。

  1. 参见代码,创建sc.yaml

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: cnfs-nfs-cpfs-sc
    # 挂载参数
    mountOptions:  
      - nolock,tcp,noresvport
      - vers=3
    parameters:
      # 创建子目录类型的 PV
      volumeAs: subpath  
      # 引用此前创建的 CNFS
      containerNetworkFileSystem: "cnfs-nfs-cpfs"  
      # CPFS 通用版协议服务导出目录对应路径
      path: "/share"  
      # 删除 PVC 时的数据处理策略,true 表示归档而非直接删除
      archiveOnDelete: "true"  
    provisioner: nasplugin.csi.alibabacloud.com
    # PV 回收策略,仅支持 Retain
    reclaimPolicy: Retain  
    # 允许存储卷扩容
    allowVolumeExpansion: true  

    参数说明:

    参数

    说明

    mountOptions

    挂载参数。默认参考本文示例即可。

    parameters.volumeAs

    • subpath:子目录模式。一个PV对应一个CPFS文件系统的独立子目录,便于数据隔离。

    • sharepath:共享目录模式。所有PV均对应StorageClass中定义的同一个CPFS目录,所有使用此StorageClassPVC都指向CPFS上同一个共享目录。

    parameters.containerNetworkFileSystem

    待引用的CNFS。

    parameters.path

    CPFS通用版协议服务导出目录对应路径,如/share。支持设置为子目录,如/share/dir

    目前仅支持普通目录,不支持Fileset

    parameters.archiveOnDelete

    仅在volumeAssubpathreclaimPolicyDelete时生效。
    CPFS通用版为共享存储,提供此选项进行双重确认。

    控制删除PVC后子目录数据的处理方式。

    • true(默认):子目录不会被删除,而是归档并重命名,格式为archived-{pvName}.{timestamp},数据可手动恢复。

    • false:子目录及其中的文件会被直接删除,不可恢复。

      此处删除的是CPFSsubpath子目录及其文件,CPFS文件系统本身不会被删除。如需删除CPFS,请参见删除文件系统

    reclaimPolicy

    csi-provisioner托管版时,版本需为v1.34.1及以上;非托管版无版本限制。
    仅在volumeAssubpath时生效。

    PV的回收策略,控制删除PVC后的资源处理方式。

    • Delete:删除PVC时,自动释放PV。后端子目录数据是否真正删除,由archiveOnDelete参数进一步控制。

    • Retain:删除PVC时,PV保留,后端数据不受影响,需手动清理。适用于对数据安全性要求高的场景。

    allowVolumeExpansion

    启用后,CPFS存储卷可自动扩容。

  2. 创建StorageClass。

    kubectl apply -f sc.yaml
  3. 查看StorageClass是否创建成功。

    kubectl get sc cnfs-nfs-cpfs-sc

    预期输出:

    NAME               PROVISIONER                      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
    cnfs-nfs-cpfs-sc   nasplugin.csi.alibabacloud.com   Retain          Immediate           true                   9s

步骤三:创建应用并挂载

创建工作负载,并在其volumeClaimTemplates中声明使用上一步创建的StorageClass。

  1. 参见代码,创建sts.yaml

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: cnfs-nfs-cpfs-sts
    spec:
      selector:
        matchLabels:
          app: nginx
      serviceName: "nginx"
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            volumeMounts:
            - name: pvc
              # 将存储卷挂载到容器内的 /data 目录
              mountPath: /data  
      # 定义 PVC 模板,StatefulSet Controller 会为每个 Pod 动态创建一个PVC
      volumeClaimTemplates:
      - metadata:
          name: pvc
        spec:
          accessModes: [ "ReadWriteOnce" ]
          # 引用此前创建的 StorageClass 
          storageClassName: "cnfs-nfs-cpfs-sc"     
          resources:
            requests:
              storage: 50Gi
  2. 创建应用。

    kubectl apply -f sts.yaml
  3. 查看Pod是否进入Running状态。

    kubectl get pod | grep cnfs-nfs-cpfs-sts

    预期返回:

    cnfs-nfs-cpfs-sts-0   1/1     Running   0          11s
    cnfs-nfs-cpfs-sts-1   1/1     Running   0          9s
  4. 确认Pod已挂载CPFS存储卷。

    kubectl exec cnfs-nfs-cpfs-sts-0 -- mount | grep nfs

    预期输出如下,表明CNFS使用NFS客户端已成功挂载CPFS文件系统。

    cpfs-********-********.cn-shanghai.cpfs.aliyuncs.com:/share/nas-804e8cb1-2355-4026-87fc-ee061e14f5f9 on /data type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,noresvport,proto=tcp,port=30000,timeo=600,retrans=2,sec=sys,mountaddr=127.XX.XX.255,mountvers=3,mountport=30000,mountproto=tcp,local_lock=all,addr=127.XX.XX.255)

步骤四:结果验证

应用创建后,系统会自动完成存储的供应和挂载。

验证自动供应

查看PVC状态,确认已自动创建了两个PVC,并绑定到动态生成的PV。

kubectl get pvc -l app=nginx

预期输出:

NAME                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       VOLUMEATTRIBUTESCLASS   AGE
pvc-cnfs-nfs-cpfs-sts-0   Bound    nas-8d2530eb-fcf9-4ad5-b5f8-bae02a1*****   50Gi       RWO            cnfs-nfs-cpfs-sc   <unset>                 63s
pvc-cnfs-nfs-cpfs-sts-1   Bound    nas-e84cadaf-ce35-4745-8cbb-2a80026*****   50Gi       RWO            cnfs-nfs-cpfs-sc   <unset>                 61s

验证Pod运行与挂载

检查容器内的挂载点,确认CPFS隔离子目录已挂载成功。

kubectl exec cnfs-nfs-cpfs-sts-0 -- mount | grep /data

预期输出中挂载路径包含了自动生成的PV名(例如nas-804e8cb1-xxxx),表明挂载的是隔离子目录。

cpfs-....aliyuncs.com:/share/nas-804e8cb1-2355-4026-87fc-ee061e1****** on /data type nfs (rw,...)

验证存储卷隔离

验证为不同Pod动态创建的存储卷是相互隔离的。

  1. cnfs-nfs-cpfs-sts-0中创建一个临时文件。

    kubectl exec cnfs-nfs-cpfs-sts-0 -- touch /data/test.txt
  2. cnfs-nfs-cpfs-sts-1中查看/data目录,确认不存在该测试文件。

    kubectl exec cnfs-nfs-cpfs-sts-1 -- ls /data

    预期输出不存在该文件,表明动态创建的存储卷是相互隔离的,数据并未共享。

应用于生产环境

  • 性能调优:CPFS适用于高吞吐和高IOPS场景。可在PVmountOptions中调整NFS挂载参数(如rsizewsize)以优化性能,满足特定工作负载需求。

  • 数据保护:建议在StorageClass中将reclaimPolicy设置为Retain,并将archiveOnDelete设置为true,以防止因误删PVC导致后端数据丢失。

资源释放指引

为避免产生预期外费用并确保数据安全,请遵循以下流程释放无需使用的资源。

  1. 删除工作负载

    • 操作:删除所有使用相关PVC的应用,例如StatefulSet。此操作将停止运行的Pod并卸载存储卷。

    • 命令示例:kubectl delete statefulset <your-statefulset-name>

  2. 删除PVC

    • 操作:删除应用关联的PVC。后端数据的处理方式由volumeAsreclaimPolicyarchiveOnDelete共同决定。

      • volumeAs: subpath

        每个PVC对应独立子目录,删除行为如下:

        • reclaimPolicy: Retain:PV保留,CPFS子目录数据不变,需手动清理。

        • reclaimPolicy: Delete + archiveOnDelete: "true":PV自动释放。子目录归档重命名为archived-{pvName}.{timestamp},数据不丢失。

        • reclaimPolicy: Delete + archiveOnDelete: "false":PV自动释放。子目录及文件直接删除,不可恢复。请谨慎操作。

      • volumeAs: sharepath

        多个PVC共享同一目录。删除PVC不会影响后端目录及数据,reclaimPolicyarchiveOnDelete均不生效。

      无论以上哪种配置,CPFS文件系统本身均不会被删除。如需删除CPFS,请参见删除文件系统

    • 命令示例:kubectl delete pvc <your-pvc-name>

  3. 删除Kubernetes存储资源定义

    此操作仅移除集群内的资源定义,不会删除后端的CPFS文件系统。

    1. 删除PV

      • 操作:若reclaimPolicyRetain,删除PVCPV状态变为Released,如确认数据无需保留,可手动删除PV。

      • 命令示例:kubectl delete pv <your-pv-name>

    2. 删除StorageClass

      • 操作:如不再需要该类型的存储,可删除对应的StorageClass。

      • 命令示例:kubectl delete sc <your-storageclass-name>

    3. 删除CNFS

      • 操作:如不再需要在集群中使用该CPFS文件系统,可删除CNFS对象。删除CNFS不会删除后端CPFS文件系统。

      • 命令示例:kubectl delete cnfs <your-cnfs-name>