基於 ACK Fluid 的混合雲優化數據訪問(二):搭建彈性計算實例與第三方存儲的橋樑

前文回顧:

本系列將介紹如何基於 ACK Fluid 支持和優化混合雲的數據訪問場景,相關文章請參考:《基於 ACK Fluid 的混合雲優化數據訪問(一):場景與架構》

在前文《基於 ACK Fluid 的混合雲優化數據訪問(一):場景與架構》中,重點介紹 ACK Fluid 支持混合雲數據訪問適用的不同應用場景和架構實現。在本文中會重點介紹如何通過 ACK Fluid 實現公共雲的彈性計算實例訪問雲下存儲系統的能力。

概述

ACK(阿里雲容器服務 Kubernetes)即開即用的彈性能力可以很好做自建IDC的彈性能力補充。特別是隨着 AIGC 的流行,算力推動創新的理念深入人心,許多原本抵制計算上雲的客戶也開始在評估公共雲。他們通常會選擇使用 ECI(彈性計算實例)作爲技術驗證的第一步。但是,如何將自建存儲與雲上彈性資源對接,特別是 ECI 資源對接,就成了混合雲客戶使用阿里雲的門檻。比如,用戶想快速比較通過雲上 ASK 和雲下自建機房運行訓練任務的成本,傳統的做法需要把數據搬到雲上,這就會涉及數據隱私問題,還有遷移的時間和金錢成本,無法做快速驗證。甚至有些客戶短期內無法通過內部安全評審,導致整個創新節奏受到嚴重的影響。

可以看到許多企業的數據都是存在線下,並且使用的存儲類型多樣,包括各種開源存儲(Ceph,lustrure,JuiceFS,CubeFS)和自建存儲。在使用公共雲計算資源的時候,也存在挑戰:

  • 數據遷雲安全性和成本評估時間長:對於數據遷移到雲存儲上,需要安全和存儲團隊的長時間評估,這會延緩整個上雲過程。
  • 數據訪問適配性差:比如公共雲對於彈性計算實例(ECI)支持的分佈式存儲類型有限(比如 NAS,OSS,CPFS),但是對於第三方存儲缺乏支持。
  • 接入雲平臺週期長和難度高:需要開發和維護雲原生兼容的 CSI 插件,一方面需要相關的專家和開發適配工程量,同時要維護版本的升級,同時支持的場景有限。比如自建 CSI 無法適配彈性計算實例(ECI)。
  • 缺乏可信透明的數據接入方式:如何在 Serverless 容器的黑盒系統訪問數據過程中規避泄露,如何確保數據在傳輸、訪問過程中安全,透明,可靠。
  • 避免業務修改的需求:如何確保業務用戶不感知基礎設施層面的差異,避免對現有應用本身進行任何修改。

ACK Fluid 通過提供 ThinRuntime 擴展機制支持將基於 FUSE 實現第三方存儲客戶端以容器化的方式接入 Kubernetes 中,可以支持阿里雲上標準 Kubernetes,邊緣 Kubernetes,Serverless Kubernetes 多種形態。

  1. 簡單的開發接入模式,易擴展: 基於 ThinRuntime 方案,只需要瞭解 Dockerfile 構建就可以完成,一般開發工作 2-3 小時左右,從而顯著降低了接入第三方存儲的工作成本。同時基於開源 Fluid 標準對於 ThinRuntime 提供了完整的支持,只要滿足開源要求就可以適配。
  2. 安全可控的數據訪問:以容器化的方式支持自定義方式實現數據訪問。整個數據訪問過程雲平臺無侵入,無需提供實現細節。
  3. 無降低改造適配的成本:只需要在 PVC 中添加特定 label 即可,滿足了業務用戶無需感知基礎設施層面的差異的需求,能將存儲適配時間縮短爲原計劃的十分之一。
  4. 存儲客戶端的自適應部署:Fluid 同時支持 CSI 和 FUSE Sidecar 兩種客戶端部署模式,根據所在運行平臺選擇合適的部署模式,將 PVC 協議轉換成 Sidecar 模式,無需最終用戶感知。
  5. 增強可觀測性和可控制性:第三方存儲客戶端只需要實現自身的容器化,就可以轉化爲 Fluid 管理的 Pod,無縫接入 Kubernetes 體系,並獲得可觀測性和計算資源可控制性。

總結:ACK Fluid 爲雲上計算訪問雲下數據提供了擴展性好,安全可控,低適配成本和與雲平臺實現無關的好處,應用案例參見小米[1]

演示

以開源 MinIO 爲例,展示如何通過 Fluid 將第三方存儲接入阿里雲彈性計算資源(ECI)。

1. 前提條件

  • 已創建 ACK Pro 版集羣,且集羣版本爲 1.18 及以上。具體操作,請參見創建 ACK Pro 版集羣[2]
  • 已安裝雲原生 AI 套件並部署 ack-fluid 組件。重要:若您已安裝開源 Fluid,請卸載後再部署 ack-fluid 組件。
  • 未安裝雲原生 AI 套件:安裝時開啓 Fluid 數據加速。具體操作,請參見安裝雲原生 AI 套件[3]
  • 已安裝雲原生 AI 套件:在容器服務管理控制檯的雲原生 AI 套件頁面部署 ack-fluid。
  • 已部署 ACK 虛擬節點(Virtual Node)。具體操作,請參見通過部署 ACK 虛擬節點組件創建 ECI Pod[4]
  • 已通過 kubectl 連接 ACK 集羣。具體操作,請參見通過 kubectl 工具連接集羣[5]

2. 準備MinIO環境

部署 Minio 存儲到 ACK 集羣中。

如下 YAML 文件 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 #  for k8s versions before 1.9.0 use apps/v1beta2  and before 1.8.0 use extensions/v1beta1
kind: Deployment
metadata:
  # This name uniquely identifies the Deployment
  name: minio
spec:
  selector:
    matchLabels:
      app: minio
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        # Label is used as selector in the service.
        app: minio
    spec:
      containers:
      - name: minio
        # Pulls the default Minio image from Docker Hub
        image: bitnami/minio
        env:
        # Minio access key and 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

部署上述資源到 ACK 集羣:

$ kubectl create -f minio.yaml

部署成功後,ACK 集羣內的其他 Pod 即可通過 http://minio:9000的Minio API 端點訪問 Minio 存儲系統中的數據。上述 YAML 配置中,我們設置 Minio 的用戶名與密碼均爲 minioadmin,並在啓動 Minio 存儲時默認創建一個名爲 my-first-bucket 的存儲桶,在接下來的示例中,我們將會訪問 my-first-bucket 這個存儲桶中的數據。在執行以下步驟前,首先執行以下命令,在 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

3. 集羣管理員將 MinIO 接入 Fluid 的開發和部署過程

作爲一個 MinIO 存儲管理員,接入 Fluid 的工作主要是三個步驟,以下調試過程可以在開源 Kubernetes 中完成:

  1. 開發和構建 MinIO 容器鏡像
  2. 開發和部署 MinIO 的 RuntimeProfile
  3. 創建訪問 MinIO 的 Fluid 數據集,並且生成對應的數據卷

3.1. 容器鏡像的開發和構建

Fluid 將會把 ThinRuntime 中 FUSE 所需的運行參數、Dataset 中描述數據路徑的掛載點等參數傳入到 ThinRuntime FUSE Pod 容器中。在容器內部,需要執行參數解析腳本,並將解析完的運行時參數傳遞給 FUSE 客戶端程序,由客戶端程序完成 Fuse 文件系統在容器內的掛載。

因此,使用 ThinRuntime CRD 描述存儲系統時,需要使用特製的容器鏡像,鏡像中需要包括以下兩個程序:

  • FUSE 客戶端程序
  • FUSE 客戶端程序所需的運行時參數解析腳本

對於 FUSE 客戶端程序,在本示例中選擇 S3 協議兼容的 goofys 客戶端連接並掛載 minio 存儲系統。

對於運行時所需的參數解析腳本,定義如下 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 客戶端掛載所需的參數。例如,上述示例中的 url、bucket、minio-access-key、minio-access-secret 等參數。
  3. 提取出所需參數後,輸出掛載腳本到文件 mount-minio.sh。

⚠️注意:在 Fluid 中,/etc/fluid/config.json 文件中僅會提供各個加密參數具體值的存儲路徑,因此需要參數解析腳本額外執行文件讀取操作(例如:上述示例中的 "export AWS_ACCESS_KEY_ID=`cat $akId`")。

接着,使用如下 Dockerfile 製作鏡像,這裏我們直接選擇包含 goofys 客戶端程序的鏡像(i.e. cloudposse/goofys)作爲 Dockerfile 的基鏡像:

FROM cloudposse/goofys

RUN apk add python3 bash

COPY ./fluid-config-parse.py /fluid-config-parse.py

使用以下命令構建並推送鏡像到鏡像倉庫:

$ IMG_REPO=<your image repo>

$ docker build -t $IMG_REPO/fluid-minio-goofys:demo .

$ docker push $IMG_REPO/fluid-minio-goofys:demo

3.2. 開發和部署 MinIO 的 ThinRuntimeProfile

在創建 Fluid Dataset 和 ThinRuntime 掛載 Minio 存儲系統前,首先需要開發 ThinRuntimeProfile CR 資源。ThinRuntimeProfile 是一種 Kubernetes 集羣級別的 Fluid CRD 資源,它描述了一類需要與 Fluid 對接的存儲系統的基礎配置(例如:容器、計算資源描述信息等)。集羣管理員需提前在集羣中定義若干 ThinRuntimeProfile CR 資源,在這之後,集羣用戶需要顯示聲明引用一個 ThinRuntimeProfile CR 來創建 ThinRuntime,從而完成對應存儲系統的掛載。

以下爲 MinIO 存儲系統的 ThinRuntimeProfile CR 示例(profile.yaml):

apiVersion: data.fluid.io/v1alpha1
kind: ThinRuntimeProfile
metadata:
  name: minio
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"

在上述 CR 示例中:

  • fileSystemType 描述了 ThinRuntime FUSE 所掛載的文件系統類型 (fsType)。需要根據使用的存儲系統 Fuse 客戶端程序填寫,例如,goofys 掛載的掛載點 fsType爲fuse,s3fs 掛載的掛載點 fsType 爲 fuse.s3fs)
  • fuse 描述了 ThinRuntime FUSE 的容器信息,包括鏡像信息 (image、imageTag、imagePullPolicy) 以及容器啓動命令 (command) 等。

創建 ThinRuntimeProfile CR minio 並且部署到 ACK 集羣。

3.3. 創建 Dataset 和 ThinRuntime CR 來掛載訪問 Minio 存儲系統中的數據。

創建訪問 minio 所需的憑證 Secret:

$ kubectl create secret generic minio-secret \                                                                                   
  --from-literal=minio-access-key=minioadmin \ 
  --from-literal=minio-access-secret=minioadmin

創建 Dataset 和 ThinRuntime CR 的示例(dataset.yaml),目的是生成用戶可用的存儲數據卷:

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
  • Dataset.spec.mounts[*].mountPoint 指定所需訪問的數據桶 (e.g. my-frist-bucket)
  • Dataset.spec.mounts[*].options.minio-url 指定 minio 在集羣可訪問的 URL(e.g. http://minio:9000
  • ThinRuntime.spec.profileName 指定已創建的 ThinRuntimeProfile(e.g. minio-profile)

創建 Dataset 和 ThinRuntime CR:

$ kubectl create -f dataset.yaml

檢查 Dataset 狀態,一段時間後,可發現 Dataset 和 Phase 狀態變爲 Bound,Dataset 可正常掛載使用:

$ 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

4. 最終用戶使用 ECI(彈性容器實例)直接通過 PVC(數據卷申請)直接訪問 MinIO

對於最終用戶來說,訪問 MinIO 的過程是非常簡單的。以下爲示例 Pod Spec 的 YAML 文件(pod.yaml),用戶只需要使用和 Dataset 同名的 PVC:

apiVersion: v1
kind: Pod
metadata:
  name: test-minio
  labels:
    alibabacloud.com/fluid-sidecar-target: eci
    alibabacloud.com/eci: "true"
spec:
  restartPolicy: Never
  containers:
    - name: app
      image: nginx:latest
      command: ["bash"]
      args:
      - -c
      - ls -lh /data && cat /data/testfile && sleep 180
      volumeMounts:
        - mountPath: /data
          name: data-vol
  volumes:
    - name: data-vol
      persistentVolumeClaim:
        claimName: minio-demo

創建數據訪問Pod:

$ kubectl create -f pod.yaml

查看數據訪問 Pod 結果:

$ kubectl logs test-minio -c app
total 512
-rw-r--r-- 1 root root 6 Aug 15 12:32 testfile
fluid-minio-test

可以看到,Pod test-minio 可正常訪問 Minio 存儲系統中的數據。

5. 環境清理

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

⚠️注意

本示例用於展示整個數據接入流程,相關的 MinIO 環境配置僅作爲演示目的。

相關鏈接:

[1] 小米

https://www.infoq.cn/article/kco7hi5TcVE08ySwNIw7

[2] 創建 ACK Pro 版集羣

https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/create-an-ack-managed-cluster-2#task-skz-qwk-qfb

[3] 安裝雲原生 AI 套件

https://help.aliyun.com/zh/ack/cloud-native-ai-suite/user-guide/deploy-the-cloud-native-ai-suite#task-2038811

[4] 通過部署 ACK 虛擬節點組件創建 ECI Pod

https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/deploy-the-virtual-node-controller-and-use-it-to-create-elastic-container-instance-based-pods#task-1443354

[5] 通過 kubectl 工具連接集羣

https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/obtain-the-kubeconfig-file-of-a-cluster-and-use-kubectl-to-connect-to-the-cluster#task-ubf-lhg-vdb

作者:車漾

點擊立即免費試用雲產品 開啓雲上實踐之旅!

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章