通过CNFS使用EFC客户端挂载NAS

EFC提供了分布式缓存等能力以提升文件存储NAS的访问性能,同时支持高并发和大规模数据集的并行访问,适用于数据密集型和高并发访问的容器化应用场景(例如大数据分析、AI训练与推理等)。相比使用默认的NFS协议挂载NAS,使用EFC挂载NAS可以加速文件访问,提升读写性能。本文介绍如何通过CNFS使用EFC客户端挂载NAS文件系统。

EFC介绍

EFC弹性文件客户端(Elastic File Client)是阿里云提供的基于FUSE的用户态POSIX客户端。它可以替代传统的内核态NFS客户端,提供多链接访问、元数据缓存、分布式数据缓存等加速能力,并结合阿里云Prometheus监控提供端侧性能监控能力。

相比于内核态NFS客户端和其他基于开源FUSE的客户端,EFC客户端具有以下优势:

  • 数据一致性保证:通过强一致的分布式锁机制实现文件和目录的强一致;文件写入可以立即被其他客户端读取;新文件创建出来后,就可以立即让所有的其他客户端同步访问到,便于您在多节点间管理数据。

  • 单节点读写缓存能力:优化了FUSE的缓存逻辑,利用计算节点上的少量内存缓存数据,提供了更好的小文件读写性能。相比于传统的NFS客户端,性能提升了50%以上。

  • 分布式只读缓存能力:支持基于多节点的内存构建分布式缓存池,可以随计算规模自动扩展且免运维。

  • 小文件预取能力:可以自动识别并预取热目录和热文件,节省拉取数据的开销。

  • 热升级和Failover能力:客户端版本更新无需重启应用,客户端异常时支持自动切换,业务无感知。

前提条件

  • 集群中已安装cnfs-nas-daemon组件,并在csi-plugin组件的FeatureGate中增加AlinasMountProxy=true以启用cnfs-nas-daemon。具体操作,请参见管理cnfs-nas-daemon组件

  • 节点操作系统为Alibaba Cloud Linux 3ContainerOS,内核版本为5.10.134-17.2及以上。

    重要

    当节点操作系统或内核版本不满足要求时,系统将自动切换为NFS协议进行挂载。

(可选)部署CNFS-EFC分布式缓存

如需使用EFC的分布式缓存能力,需要先部署CNFS-EFC分布式缓存插件。

  1. 在集群中创建并部署csi-pluginConfigMap,用于部署CNFS-EFC分布式缓存插件。

    ConfigMap部署完成后,会根据已配置的ConfigMap自动部署缓存的DaemonSet以及Service。

    1. 将以下内容保存为csi-configmap.yaml。

      以下YAML示例用于部署分布式缓存的DaemonSet,DaemonSet会在带有cache=true标签的节点上创建Pod,每个Pod包含3个容器,挂载了15 GiBtmpfs卷(基于内存)。您可以根据实际需求修改参数配置。

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: csi-plugin
        namespace: kube-system
      data:
        nas-efc-cache: |
          enable=true
          container-number=3
          volume-type=memory
          volume-size=15Gi
        node-selector: |
          cache=true

      参数

      说明

      nfs-efc-cache

      enable

      配置为true,开启分布式缓存。

      container-number

      缓存的DaemonSet中每个Pod包含的容器数量,当缓存出现性能瓶颈时,可以增加容器数量。

      volume-type

      缓存Pod挂载的EmptyDir卷所使用的存储介质。

      • disk:磁盘。

      • memory:内存。

      重要

      使用磁盘或内存时,会使用节点的数据盘和内存资源,请确保不影响业务运行。

      volume-size

      缓存PodVolume的大小。单位:GiB。

      node-selector

      缓存的DaemonSet通过Label进行调度。如果不配置,则所有节点都会部署DaemonSet。

    2. 部署ConfigMap。

      kubectl apply -f csi-configmap.yaml
  2. 确认分布式缓存的DaemonSet是否启动。

    kubectl get ds/cnfs-cache-ds -n kube-system -o wide

    返回示例如下,本示例的集群中有2个带有cache=true标签的节点,对应DaemonSet中的2Pod均处于可用状态,说明分布式缓存的DaemonSet已经启动完成。

    NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE   CONTAINERS                                                            IMAGES                                                                                                                                                                                   SELECTOR
    cnfs-cache-ds   2         2         2       2            2           cache=true      13m   alinas-dadi-container,alinas-dadi-container1,alinas-dadi-container2   registry-cn-hangzhou.ack.aliyuncs.com/acs/nas-cache:20220420,registry-cn-hangzhou.ack.aliyuncs.com/acs/nas-cache:20220420,registry-cn-hangzhou.ack.aliyuncs.com/acs/nas-cache:20220420   app=cnfs-cache-ds
  3. 确认分布式缓存的Service是否实现服务发现。

    kubectl get ep cnfs-cache-ds-service  -n kube-system -o wide

    返回示例如下,Service已经发现后端缓存Pod对应的Endpoints。

    NAME                    ENDPOINTS                                                              AGE
    cnfs-cache-ds-service   192.168.3.217:6500,192.168.5.247:6500,192.168.3.217:6502 + 3 more...   2d3h

配置CNFS使用EFC客户端挂载NAS

  1. 创建CNFS,指定使用EFC客户端。

    1. 将以下内容保存为cnfs-efc.yaml。

      说明

      示例以使用CNFS配置已有NAS文件系统为例,演示如何开启EFC客户端。如果使用CNFS新建NAS文件系统,也可以通过在ContainerNetworkFileSystem资源的parameters添加useClient: EFCClient的方式来开启EFC客户端。关于如何使用CNFS创建NAS文件系统,请参见通过CNFS管理NAS文件系统(推荐)

      apiVersion: storage.alibabacloud.com/v1beta1
      kind: ContainerNetworkFileSystem
      metadata:
        name: cnfs-efc-test
      spec:
        description: "cnfs"
        type: nas
        reclaimPolicy: Retain
        parameters:
          server: 17f7e4****-h****.cn-beijing.nas.aliyuncs.com
          useClient: EFCClient

      参数

      说明

      description

      文件系统的描述。

      type

      需要创建的存储卷类型。

      reclaimPolicy

      回收策略,目前仅支持Retain策略,删除CNFS时并不会删除NAS文件系统。

      parameters

      server

      NAS挂载点的地址。挂载点需满足以下要求:

      • 挂载点的VPC必须和集群中Pod使用的VPC一致,否则会导致挂载失败。

      • 挂载点的交换机建议和集群中Pod使用的交换机一致,性能相对更优。

      • 挂载点的状态为可用

      如果已有挂载点不满足要求,可创建新的挂载点。更多信息,请参见管理挂载点

      useClient

      配置为EFCClient,表示开启EFC客户端。

    2. 创建CNFS。

      kubectl create -f cnfs-efc.yaml
  2. 使用CNFS创建对应的存储卷。

    kubectl create -f cnfs-pv-pvc.yaml

    cnfs-pv-pvc.yaml的内容示例如下。如果集群中已部署CNFS-EFC分布式缓存,您可以通过 mountOptions配置EFC开启缓存和预读能力;若未部署,请删除示例中的 mountOptions配置。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: efc-pv
    spec:
      accessModes:
      - ReadWriteMany
      capacity:
        storage: 50Gi
      claimRef:
        name: efc-pvc
        namespace: default
      csi:
        driver: nasplugin.csi.alibabacloud.com
        volumeAttributes:
          containerNetworkFileSystem: cnfs-efc-test
          path: /
        volumeHandle: efc-pv
      mountOptions:
      - g_tier_EnableClusterCache=true              # 挂载时,分布式缓存使用缓存配置。
      - g_tier_EnableClusterCachePrefetch=true      # 挂载时,分布式缓存开启预读功能。
      volumeMode: Filesystem
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: efc-pvc
      namespace: default
    spec:
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 50Gi
      storageClassName: ""
      volumeMode: Filesystem
      volumeName: efc-pv

创建工作负载并挂载NAS

  1. 创建Deployment并挂载NAS。

    kubectl create -f cnfs-deployment.yaml

    cnfs-deployment.yaml的内容示例如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: efc-test
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: efc-test
      template:
        metadata:
          labels:
            app: efc-test
        spec:
          containers:
          - command:
            - sh
            - -c
            - |
              sleep infinity
            image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
            name: test
            volumeMounts:
            - mountPath: /mnt
              name: pvc
          volumes:
          - name: pvc
            persistentVolumeClaim:
              claimName: efc-pvc
  2. 查看DeploymentPod的部署情况。

    kubectl get pod -l app=efc-test

    预期返回:

    NAME                       READY   STATUS    RESTARTS   AGE
    efc-test-f545b86d6-spr7p   1/1     Running   0          29m
  3. 等待Pod Running后,在Pod中查看EFC挂载点。

    kubectl exec <pod-name> -- mount -t fuse.aliyun-alinas-efc

    预期返回:

    bindroot-3889a-8TzEY5mc:3d2804****-w****.cn-shanghai.nas.aliyuncs.com:/ on /mnt type fuse.aliyun-alinas-efc (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=1048576)