如何使用Fluid访问线下存储

Fluid是一个开源的Kubernetes原生的分布式数据集编排和加速引擎,主要服务于云原生场景下的数据密集型应用,例如大数据应用、AI应用等。除了Fluid原生集成的存储、缓存系统外,Fluid还提供了ThinRuntime CRD。ThinRuntime CRD允许用户描述任何自定义的存储系统,并将其对接到Fluid中。本文以Minio为例介绍如何在注册集群中通过Fluid管理并访问Minio存储中的数据。

实现原理

通过Fluid管理并访问线下存储的实现原理如下图所示。

连接图.png

前提条件

步骤一:安装ack-fluid组件

通过onectl安装

  1. 在本地安装配置onectl。具体操作,请参见通过onectl管理注册集群

  2. 执行以下命令,安装ack-fluid组件。

    onectl addon install ack-fluid --set pullImageByVPCNetwork=false

    pullImageByVPCNetwork:为可选参数,设置是否使用VPC网络拉取组件镜像。

    预期输出:

    Addon ack-fluid, version **** installed.

通过控制台安装

  1. 登录容器服务管理控制台,在左侧导航栏选择市场 > 应用市场

  2. 应用目录页面,搜索并选中ack-fluid

  3. 在页面右上角,单击一键部署

  4. 创建面板中,选择集群命名空间发布名称可保持系统默认,然后单击下一步

  5. 选择Chart 版本为当前最新版本,设置组件相关参数,然后单击确定

步骤二:在集群中部署Minio

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

    apiVersion: v1
    kind: Service
    metadata:
      name: minio
    spec:
      type: ClusterIP
      ports:
        - port: 9000
          targetPort: 9000
          protocol: TCP
      selector:
        app: minio
    ---
    apiVersion: apps/v1  # 1.9.0之前版本的k8s使用apps/v1beta2, 1.8.0之前的版本使用extensions/v1beta1
    kind: Deployment
    metadata:
      name: minio
    spec:
      selector:
        matchLabels:
          app: minio
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: minio
        spec:
          containers:
          - name: minio
            image: bitnami/minio
            env:
            # 访问Minio的Access key和Secret key。
            - name: MINIO_ROOT_USER
              value: "minioadmin"
            - name: MINIO_ROOT_PASSWORD
              value: "minioadmin"
            - name: MINIO_DEFAULT_BUCKETS
              value: "my-first-bucket:public"
            ports:
            - containerPort: 9000
              hostPort: 9000
  2. 执行以下命令,在集群中部署Minio。

    kubectl create -f minio.yaml

    以上Minio配置中,Minio的用户名与密码均为minioadmin,Minio在启动时,将默认创建一个名为my-first-bucket的存储桶。

  3. 执行以下命令,在my-first-bucket中存储示例文件。

    kubectl exec -it minio-69c555f4cf-np59j -- bash -c "echo fluid-minio-test > testfile"
    
    kubectl exec -it minio-69c555f4cf-np59j -- bash -c "mc cp ./testfile local/my-first-bucket/" 
    
    kubectl exec -it  minio-69c555f4cf-np59j -- bash -c "mc cat local/my-first-bucket/testfile"
    fluid-minio-test

步骤三:准备包含Minio Fuse客户端的容器镜像

Fluid会把ThinRuntime中Fuse所需的运行参数、Dataset中描述数据路径的挂载点等参数传入到ThinRuntime Fuse的Pod容器中。在容器内部,用户需要执行参数解析脚本,并将解析完的运行时参数传递给Fuse客户端程序,由客户端程序完成Fuse文件系统在容器内的挂载。因此,使用ThinRuntime CRD描述存储系统时,需要使用特制的容器镜像,镜像中需要包括以下两个程序。

  • Fuse客户端程序:本示例选择S3协议兼容的goofys客户端连接并挂载minio存储系统。

  • Fuse客户端程序所需的运行时参数解析脚本:您可以通过自定义如下Python脚本fluid-config-parse.py。

    import json
    
    with open("/etc/fluid/config.json", "r") as f:
        lines = f.readlines()
    
    rawStr = lines[0]
    print(rawStr)
    
    
    script = """
    #!/bin/sh
    set -ex
    export AWS_ACCESS_KEY_ID=`cat $akId`
    export AWS_SECRET_ACCESS_KEY=`cat $akSecret`
    
    mkdir -p $targetPath
    
    exec goofys -f --endpoint "$url" "$bucket" $targetPath
    """
    
    obj = json.loads(rawStr)
    
    with open("mount-minio.sh", "w") as f:
        f.write("targetPath=\"%s\"\n" % obj['targetPath'])
        f.write("url=\"%s\"\n" % obj['mounts'][0]['options']['minio-url'])
        if obj['mounts'][0]['mountPoint'].startswith("minio://"):
          f.write("bucket=\"%s\"\n" % obj['mounts'][0]['mountPoint'][len("minio://"):])
        else:
          f.write("bucket=\"%s\"\n" % obj['mounts'][0]['mountPoint'])
        f.write("akId=\"%s\"\n" % obj['mounts'][0]['options']['minio-access-key'])
        f.write("akSecret=\"%s\"\n" % obj['mounts'][0]['options']['minio-access-secret'])
    
        f.write(script)

    该Python脚本将按以下步骤执行。

    1. 读取/etc/fluid/config.json文件中的JSON字符串,Fluid会将Fuse客户端挂载所需的参数存储并挂载到Fuse容器的/etc/fluid/config.json文件。

    2. 解析JSON字符串,从中提取Fuse客户端挂载所需的参数。例如,上述示例中的urlbucketminio-access-keyminio-access-secret等参数。

    3. 所需参数提取后,输出挂载脚本到mount-minio.sh文件中。

  1. 使用如下Dockerfile制作镜像。

    此处选择包含goofys客户端程序的镜像(例如cloudposse、goofys)作为Dockerfile的基镜像。

    FROM cloudposse/goofys
    
    RUN apk add python3 bash
    
    COPY ./fluid-config-parse.py /fluid-config-parse.py
  2. 执行以下命令,构建并推送镜像到镜像仓库。

    IMG_REPO=<your image repo>
    docker build -t $IMG_REPO/fluid-minio-goofys:demo .
    docker push $IMG_REPO/fluid-minio-goofys:demo

步骤四:创建ThinRuntimeProfile

ThinRuntimeProfile是一种Cluster-level的Fluid CRD资源,它描述了一类需要与Fluid对接的存储系统的基础配置(例如容器镜像信息、Pod Spec描述信息等)。创建Fluid Dataset和ThinRuntime CR用于挂载Minio存储系统之前,需要先创建ThinRuntimeProfile CR资源。

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

    apiVersion: data.fluid.io/v1alpha1
    kind: ThinRuntimeProfile
    metadata:
      name: minio-profile
    spec:
      fileSystemType: fuse
      fuse:
        image: $IMG_REPO/fluid-minio-goofys
        imageTag: demo
        imagePullPolicy: IfNotPresent
        command:
        - sh
        - -c
        - "python3 /fluid-config-parse.py && chmod u+x ./mount-minio.sh && ./mount-minio.sh"
  2. 执行以下命令,创建ThinRuntimeProfile。

    kubectl create -f profile.yaml

步骤五:创建Dataset和Runtime

  1. 执行以下命令,将访问Minio所需的访问凭证存储于Secret。

    kubectl create secret generic minio-secret \                                                                                   
      --from-literal=minio-access-key=minioadmin \ 
      --from-literal=minio-access-secret=minioadmin
  2. 使用以下内容,创建dataset.yaml文件。

    此YAML文件包含创建Dataset和ThinRuntime CR,通过创建Dataset和ThinRuntime CR用于挂载访问Minio存储系统中的数据。

    apiVersion: data.fluid.io/v1alpha1
    kind: Dataset
    metadata:
      name: minio-demo
    spec:
      mounts:
      - mountPoint: minio://my-first-bucket   # minio://<bucket name>
        name: minio
        options:
          minio-url: http://minio:9000  # minio service <url>:<port>
        encryptOptions:
          - name: minio-access-key
            valueFrom:
              secretKeyRef:
                name: minio-secret
                key: minio-access-key
          - name: minio-access-secret
            valueFrom:
              secretKeyRef:
                name: minio-secret
                key: minio-access-secret
    ---
    apiVersion: data.fluid.io/v1alpha1
    kind: ThinRuntime
    metadata:
      name: minio-demo
    spec:
      profileName: minio-profile

    类别

    参数

    说明

    示例值

    Dataset

    mountPoint

    指定所需访问的数据桶。

    my-frist-bucket

    minio-url

    指定Minio在集群中可访问的URL。

    http://minio:9000

    ThinRuntime

    profileName

    指定已创建的ThinRuntimeProfile。

    minio-profile

  3. 执行以下命令,部署Dataset CR和ThinRuntime CR。

    kubectl create -f dataset.yaml
  4. 执行以下命令,查看minio-demo状态。

    kubectl get dataset minio-demo

    预期输出:

    NAME         UFS TOTAL SIZE   CACHED   CACHE CAPACITY   CACHED PERCENTAGE   PHASE   AGE
    minio-demo                    N/A      N/A              N/A                 Bound   2m18s

    预期输出中Dataset和Phase状态变为Bound,表明Dataset可正常挂载使用。

步骤六:创建Pod访问Minio存储系统中的数据

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

    该Pod用于访问Minio中的数据。

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-minio
      # 如果云上为ECI节点,需要添加以下标签:
      # labels:
        # alibabacloud.com/eci: true
        # alibabacloud.com/fluid-sidecar-target: "eci"
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          command: ["bash"]
          args:
          - -c
          - ls -lh /data && cat /data/testfile && sleep 3600
          volumeMounts:
            - mountPath: /data
              name: data-vol
      volumes:
        - name: data-vol
          persistentVolumeClaim:
            claimName: minio-demo
  2. 使用以下内容,部署Pod。

    kubectl create -f pod.yaml
  3. 执行以下命令,查看数据访问结果。

    kubectl logs test-minio      

    预期输出:

    total 512
    -rw-r--r-- 1 root root 17 Dec 15 07:58 testfile
    fluid-minio-test

    预期输出表明,名为test-minio的Pod可正常访问Minio存储系统中的数据。

(可选)步骤七:清理环境

当不再需要访问云下存储时,您需要执行以下命令清理环境。

kubectl delete -f pod.yaml
kubectl delete -f dataset.yaml
kubectl delete -f profile.yaml
kubectl delete -f minio.yaml