使用FUSE挂载点自愈功能

在应用Pod的生命周期内,FUSE守护进程可能会因为异常情况崩溃,导致应用Pod无法正常访问数据。本文档介绍如何开启并使用FUSE挂载点自愈功能,允许在应用Pod不重启的前提下恢复应用的数据访问。

前提条件

功能概述

使用Fluid数据集(Dataset)的应用Pod通过FUSE文件系统访问分布式缓存系统中的数据,每一个FUSE文件系统对应一个FUSE守护进程(Daemon),该进程负责处理FUSE文件系统上的任何文件访问请求。

在应用Pod的生命周期内,FUSE守护进程可能会因为异常情况(例如:内存使用超出上限被杀死)崩溃,导致应用Pod访问文件时出现“端点未连接”(“Transport Endpoint is Not Connected”)错误。为了解决此类错误,通常需要手动重启应用容器或重建应用Pod以恢复FUSE文件系统的访问。

Fluid支持FUSE文件系统挂载点的自愈功能。通过周期性查询节点各应用Pod挂载的FUSE文件系统状态,Fluid支持在不重启应用容器和不重建应用Pod的前提下,恢复应用Pod内的文件访问。

使用限制

  • 该功能涉及的自愈过程存在一定的延迟,不支持对业务应用的无感自愈。业务应用需要容忍文件访问失败的情况,并持续重试直至自愈完成。

  • 该功能仅支持与只读类型的数据集共同使用,如果集群中包含任意可读写的数据集,必须确保该功能处于关闭状态,以避免预期外的数据写入问题。

  • 该功能不支持应用Pod通过subPath方式挂载数据集对应的存储卷声明(PVC)。

  • FUSE挂载点自愈操作必须在FUSE守护进程自动重启后执行,由于FUSE守护进程运行在容器中,当FUSE守护进程频繁崩溃时,Kubernetes重启该容器的间隔时间将会指数级增长,这将影响到FUSE挂载点自愈的恢复时间。

ACK集群环境中使用FUSE自愈功能

步骤一:开启FUSE挂载点自愈(Feature Gate)

使用以下命令开启FUSE挂载点自愈功能:

kubectl get ds -n fluid-system csi-nodeplugin-fluid -oyaml | sed 's/FuseRecovery=false/FuseRecovery=true/g' | kubectl apply -f -

预期输出如下:

daemonset.apps/csi-nodeplugin-fluid configured

执行以下命令查看FUSE挂载点自愈门控是否已经正常开启:

kubectl get ds -n fluid-system csi-nodeplugin-fluid -oyaml | grep '\- \-\-feature-gates='

如果输出如下结果,则表示FUSE挂载点自愈门控已经成功开启:

- --feature-gates=FuseRecovery=true

步骤二:创建Fluid数据集

本文以加速OSS对象存储中的文件为例,部署JindoFS缓存系统。

  1. 使用以下内容,创建secret.yaml文件。

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    stringData:
      fs.oss.accessKeyId: <YOUR_ACCESS_KEY_ID>
      fs.oss.accessKeySecret: <YOUR_ACCESS_KEY_SECRET>

    其中,fs.oss.accessKeyIdfs.oss.accessKeySecret是用来访问OSSAccessKey IDAccessKey Secret

  2. 执行以下命令,创建Secret。

    kubectl create -f secret.yaml
  3. 使用以下内容,创建dataset.yaml文件。

    apiVersion: data.fluid.io/v1alpha1
    kind: Dataset
    metadata:
      name: demo-dataset
    spec:
      mounts:
        - mountPoint: oss://<oss_bucket>/<bucket_dir>
          options:
            fs.oss.endpoint: <oss_endpoint>
          name: mybucket
          path: "/"
          encryptOptions:
            - name: fs.oss.accessKeyId
              valueFrom:
                secretKeyRef:
                  name: mysecret
                  key: fs.oss.accessKeyId
            - name: fs.oss.accessKeySecret
              valueFrom:
                secretKeyRef:
                  name: mysecret
                  key: fs.oss.accessKeySecret
    ---
    apiVersion: data.fluid.io/v1alpha1
    kind: JindoRuntime
    metadata:
      name: demo-dataset
    spec:
      replicas: 2
      tieredstore:
        levels:
          - mediumtype: MEM
            path: /dev/shm
            volumeType: emptyDir
            quota: 2Gi
            high: "0.99"
            low: "0.95"

    相关参数解释如下表所示:

    参数

    说明

    mountPoint

    oss://<oss_bucket>/<bucket_dir>表示挂载UFS的路径,路径中不需要包含endpoint信息。

    fs.oss.endpoint

    OSS BucketEndpoint信息,公网或私网地址均支持。更多信息,请参见OSS地域和访问域名

    replicas

    表示创建JindoFS集群的Worker数量。

    mediumtype

    表示缓存类型。在创建JindoRuntime模板样例时,JindoFS暂时只支持HDD/SSD/MEM中的其中一种缓存类型。

    path

    表示存储路径,暂时只支持单个路径。当选择MEM做缓存时,需指定一个本地路径来存储Log等文件。

    quota

    表示缓存最大容量,单位GB。

    high

    表示存储容量上限大小。

    low

    表示存储容量下限大小。

  4. 执行以下命令,创建DatasetJindoRuntime资源。

    kubectl create -f dataset.yaml

步骤三:创建应用Pod挂载Fluid数据集

本文以一个Nginx容器为例,尝试挂载Fluid数据集并访问其中的文件数据。

  1. 使用以下内容,创建app.yaml文件。

    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-app
      labels:
        fuse.serverful.fluid.io/inject: "true"
    spec:
      containers:
        - name: demo
          image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
          volumeMounts:
            - mountPath: /data
              name: data-vol
      volumes:
        - name: data-vol
          persistentVolumeClaim:
            claimName: demo-dataset   # 与Dataset资源名称一致

    其中fuse.serverful.fluid.io/inject=true的标签用于为该Pod启用FUSE挂载点自愈能力。

  2. 执行以下命令,创建应用容器。

    kubectl create -f app.yaml
  3. 执行以下命令,查看应用容器状态。

    kubectl get pod demo-app
  4. 如果看到容器STATUS字段已经进入Running状态,则说明应用容器已经成功启动。

    NAME       READY   STATUS    RESTARTS   AGE
    demo-app   1/1     Running   0          16s

步骤四:验证FUSE挂载点自愈功能

  1. 执行以下命令,登录到应用容器中并执行周期性访问文件元信息的脚本,该脚本会每隔1秒钟列举挂载的Fluid数据集中的文件。

    kubectl exec -it demo-app -- bash -c 'while true; do ls -l /data; sleep 1; done'
  2. 保持上述脚本后台运行,执行以下命令,模拟FUSE组件异常崩溃的情况。

    # 获取demo-pod所在节点
    demo_pod_node_name=$(kubectl get pod demo-app -ojsonpath='{.spec.nodeName}')
    # 获取与demo-pod相同节点的FUSE Pod名字
    fuse_pod_name=$(kubectl get pod --field-selector spec.nodeName=$demo_pod_node_name --selector role=jindofs-fuse,release=demo-dataset -oname)
    # 模拟FUSE Pod异常崩溃场景
    kubectl exec -it $fuse_pod_name -- bash -c 'kill 1'
  3. 查看demo-app中执行的脚本输出结果,如果观察到类似如下结果,则说明FUSE挂载点成功自愈。

    ...
    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt
    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt
    ls: cannot access '/data/': Transport endpoint is not connected
    ls: cannot access '/data/': Transport endpoint is not connected
    ls: cannot access '/data/': Transport endpoint is not connected
    ls: cannot access '/data/': Transport endpoint is not connected
    ls: cannot access '/data/': Transport endpoint is not connected
    ls: cannot access '/data/': Transport endpoint is not connected
    ls: cannot access '/data/': Transport endpoint is not connected
    ls: cannot access '/data/': Transport endpoint is not connected
    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt
    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt
    ...

Serverless环境中使用FUSE自愈功能

已创建一个非ContainerOS操作系统的ACK Serverless集群Pro,且集群版本为1.18及以上。具体操作,请参见创建ACK Serverless集群

步骤一:创建Fluid数据集

本文以加速OSS对象存储中的文件为例,部署JindoFS缓存系统。

  1. 使用以下内容,创建secret.yaml文件

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    stringData:
      fs.oss.accessKeyId: <YOUR_ACCESS_KEY_ID>
      fs.oss.accessKeySecret: <YOUR_ACCESS_KEY_SECRET>

    其中,fs.oss.accessKeyIdfs.oss.accessKeySecret是用来访问OSSAccessKey IDAccessKey Secret

  2. 执行以下命令,创建Secret。

    kubectl create -f secret.yaml
  3. 使用以下内容,创建dataset.yaml文件。

    apiVersion: data.fluid.io/v1alpha1
    kind: Dataset
    metadata:
      name: demo-dataset
    spec:
      mounts:
        - mountPoint: oss://<oss_bucket>/<bucket_dir>
          options:
            fs.oss.endpoint: <oss_endpoint>
          name: mybucket
          path: "/"
          encryptOptions:
            - name: fs.oss.accessKeyId
              valueFrom:
                secretKeyRef:
                  name: mysecret
                  key: fs.oss.accessKeyId
            - name: fs.oss.accessKeySecret
              valueFrom:
                secretKeyRef:
                  name: mysecret
                  key: fs.oss.accessKeySecret
    ---
    apiVersion: data.fluid.io/v1alpha1
    kind: JindoRuntime
    metadata:
      name: demo-dataset
    spec:
      replicas: 2
      tieredstore:
        levels:
          - mediumtype: MEM
            path: /dev/shm
            volumeType: emptyDir
            quota: 2Gi
            high: "0.99"
            low: "0.95"

    相关参数解释如下表所示:

    参数

    说明

    mountPoint

    oss://<oss_bucket>/<bucket_dir>表示挂载UFS的路径,路径中不需要包含endpoint信息。

    fs.oss.endpoint

    OSS BucketEndpoint信息,公网或私网地址均支持。更多信息,请参见OSS地域和访问域名

    replicas

    表示创建JindoFS集群的Worker数量。

    mediumtype

    表示缓存类型。在创建JindoRuntime模板样例时,JindoFS暂时只支持HDD/SSD/MEM中的一种缓存类型。

    path

    表示存储路径,暂时只支持单个路径。当选择MEM做缓存时,需指定一个本地路径来存储Log等文件。

    quota

    表示缓存最大容量,单位GB。

    high

    表示存储容量上限大小。

    low

    表示存储容量下限大小。

  4. 执行以下命令,创建DatasetJindoRuntime资源。

    kubectl create -f dataset.yaml

步骤二:创建应用Pod挂载Fluid数据集

本文以一个Nginx容器为例,尝试挂载Fluid数据集并访问其中的文件数据。

  1. 使用以下内容,创建app.yaml文件。

    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-app
      labels:
        alibabacloud.com/fluid-sidecar-target: eci
      annotations:
        # 禁用虚拟节点调度功能。
        alibabacloud.com/burst-resource: eci_only
        # 开启FUSE挂载点自愈功能
        alibabacloud.com/fuse-recover-policy: auto
    spec:
      containers:
        - name: demo
          image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
          volumeMounts:
            - mountPath: /data
              name: data-vol
      volumes:
        - name: data-vol
          persistentVolumeClaim:
            claimName: demo-dataset  # 与Dataset资源名称一致

    其中alibabacloud.com/fuse-recover-policy=auto的注解用于为该Pod启用FUSE挂载点自愈能力,该注解仅对运行于Serverless环境的应用Pod生效。

  2. 执行以下命令,创建应用Pod。

    kubectl create -f app.yaml
  3. 执行以下命令,查看应用容器状态。

    kubectl get pod demo-app
  4. 如果看到容器STATUS字段已经进入Running状态,则说明应用容器已经成功启动。

    NAME       READY   STATUS    RESTARTS   AGE
    demo-app   2/2     Running   0          110s

步骤三:验证FUSE挂载点自愈功能

  1. 执行以下命令,登录到应用容器中并执行周期性访问文件元信息的脚本,该脚本会每隔1秒钟列举挂载的Fluid数据集中的文件。

    kubectl exec -it demo-app -c demo -- bash -c 'while true; do ls -l /data; sleep 1; done'
  2. 保持上述脚本后台运行,执行以下命令,模拟FUSE组件异常崩溃的情况。

    # 模拟FUSE Pod异常崩溃场景
    kubectl exec -it demo-app -c fluid-fuse-0 -- bash -c 'kill 1'
  3. 查看demo-app中执行的脚本输出结果,如果观察到类似如下结果,则说明FUSE挂载点成功自愈。

    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt
    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt
    ls: cannot access '/data/demo2': Transport endpoint is not connected
    ls: cannot access '/data/demo2': Transport endpoint is not connected
    ls: cannot access '/data/demo2': Transport endpoint is not connected
    ls: cannot access '/data/demo2': Transport endpoint is not connected
    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt
    total 172
    -rwxrwxr-x 1 root root          18 Jul  1 15:17 myfile
    -rwxrwxr-x 1 root root         154 Jul  1 17:06 myfile.txt