CCE集群使用开源juicefs文件存储

举报
可以交个朋友 发表于 2023/12/28 20:14:10 2023/12/28
【摘要】 一、背景客户系统在IDC k8s集群使用JuiceFS作为容器存储引擎,迁移到CCE 集群需要使用对象存储作为底层存储,JuiceFS作为存储引擎驱动。 二、JuiceFS介绍 2.1 架构预览说明:JuiceFS 文件系统由三个部分组成JuiceFS 客户端、数据存储元数据引擎JuiceFS 客户端(Client)客户端是文件系统最重要的部分,因为所有文件读写,包括碎片合并、回收站文件过...

一、背景

客户系统在IDC k8s集群使用JuiceFS作为容器存储引擎,迁移到CCE 集群需要使用对象存储作为底层存储,JuiceFS作为存储引擎驱动。

二、JuiceFS介绍

2.1 架构预览

image.png

说明:JuiceFS 文件系统由三个部分组成JuiceFS 客户端、数据存储元数据引擎

  • JuiceFS 客户端(Client)
    客户端是文件系统最重要的部分,因为所有文件读写,包括碎片合并、回收站文件过期删除等后台任务,均在客户端中发生。服务端(也就是下面将会介绍的「元数据引擎」)不会也不能直接修改任何文件系统数据。可想而知,客户端需要同时与对象存储和元数据存储服务打交道。
  • 数据存储(Data Storage)
    文件将会切分上传保存在对象存储服务。JuiceFS 支持几乎所有的公有云对象存储,同时也支持 OpenStack Swift、Ceph、MinIO 等私有化的对象存储。
    在 JuiceFS 中,只有客户端会直接与存储打交道,服务端(元数据引擎)与对象存储完全解耦,不关心也不会访问对象存储服务,所有实际的文件数据都坐落在你自己选择的对象存储上。
    − FUSE 挂载:使用 JuiceFS 客户端将文件系统挂载到本地,在服务器直接访问海量云端存储
    − Hadoop Java SDK:直接替代 HDFS,为 Hadoop 提供低成本的海量存储
    − Kubernetes CSI 驱动:接入 Kubernetes 集群,为容器提供弹性存储
    − S3 网关:对外暴露 S3 API,已有的支持 S3 应用可直接无缝接入
  • 元数据引擎(Metadata Engine)​
    Juicedata 自研的高性能元数据服务,用于存储文件元数据(metadata),包含以下内容:
    − 常规文件系统的元数据:文件名、文件大小、权限信息、创建修改时间、目录结构、文件属性、符号链接、文件锁等。
    − JuiceFS 独有的元数据:文件的 chunk 及 slice 映射关系、客户端 session 等。
    Juicedata 已经在大多数公有云都部署了元数据服务,供云服务用户开箱即用。客户端默认通过公网直接访问同区域的元数据服务,但在对网络延迟有着更高要求的大规模场景下,也可以通过内网打通的方式来进一步优化元数据服务的访问延迟

2.2 架构原理

JuiceFS CSI 驱动包含以下组件:
JuiceFS CSI Controller(StatefulSet)和 JuiceFS CSI Node Service(DaemonSet)
CSI 默认采用容器挂载(Mount Pod)模式,也就是让 JuiceFS 客户端运行在独立的 Pod 中,其架构如下:
image.png

采用独立 Mount Pod 来运行 JuiceFS 客户端,并由 CSI Node Service 来管理 Mount Pod 的生命周期。这样的架构提供如下好处:

  • 多个 Pod 共用 PV 时,不会新建 Mount Pod,而是对已有的 Mount Pod 做引用计数,计数归零时删除 Mount Pod。
  • CSI 驱动组件与客户端解耦,方便 CSI 驱动自身的升级。
    在同一个节点上,一个 PVC 会对应一个 Mount Pod。而使用了相同 PV 的容器,则可以共享一个 Mount Pod。PVC、PV、Mount Pod 之间的关系如下图所示:
    image.png

2.3 使用方式介绍

2.3.1 静态配置

一般在以下场景使用静态配置:

  • 你在JuiceFS中已经存储了大量数据,想要直接在 Kubernetes 容器中访问;
  • 对 CSI 驱动功能做简单验证;

静态配置方式最为简单直接

  1. 需要 Kubernetes 管理员创建 PersistentVolume(PV)以及文件系统认证信息(以 Kubernetes Secret 形式保存),
  2. 用户创建 PersistentVolumeClaim(PVC),在定义中绑定该 PV,
  3. 最后在 Pod 定义中引用该 PVC。
    资源间关系如下图所示:
    image.png

2.3.2 动态配置

考虑到静态配置的管理更加复杂,规模化使用 CSI 驱动时,一般会以「动态配置」方式使用。

  1. 管理员会负责创建一个或多个 StorageClass,
  2. 用户只需要创建 PVC,指定 StorageClass,
  3. 在 Pod 中引用该 PVC,CSI 驱动就会按照 StorageClass 中配置好的参数,为你自动创建 PV。
    资源间关系如下:
    image.png

以容器挂载模式为例,从创建到使用的流程大致如下:

  • 用户创建 PVC,指定已经创建好的 StorageClass;
  • CSI Controller 负责在 JuiceFS 文件系统中做初始化,默认以 PV ID 为名字创建子目录,同时创建对应的 PV。该过程所需的配置,都在 StorageClass 中指定或引用;
  • Kubernetes (PV Controller 组件) 将上述用户创建的 PVC 与 CSI Controller 创建的 PV 进行绑定,此时 PVC 与 PV 的状态变为「Bound」;
  • 用户创建应用Pod,声明使用先前创建的 PVC;
  • CSI Node Service 负责在应用 Pod 所在节点创建 Mount Pod;
  • Mount Pod 启动,执行 JuiceFS 客户端挂载,将挂载点暴露给宿主机,路径为 /var/lib/juicefs/volume/[pv-name];
  • CSI Node Service 等待 Mount Pod 启动成功后,将 PV 对应的 JuiceFS 子目录 bind 到容器内,路径为其声明的 VolumeMount 路径;
  • Kubelet 启动应用 Pod。

三、在CCE部署和使用JuiceFS

3.1 前提条件

  • Kubernetes 集群是 1.14 及以上版本
  • 集群能从外网拉取镜像,比如 Docker Hub 和 Quay,如果无法从这两个镜像仓库下载资源,考虑先「搬运镜像」,具体见:https://juicefs.com/docs/zh/csi/administration/offline#copy-images
  • 在集群中一台节点上安装 Helm 3.1.0 及以上版本
  • 已经创建了obs桶或者并行文件系统
  • 已获取redis服务地址
  • 在 JuiceFS 企业版私有部署环境下,需要在「文件系统认证信息」中需要填写 envs 字段,指定私有部署的控制台地址

3.2 使用helm安装JuiceFS

3.2.1 拉取chart包

步骤1: 加入 JuiceFS CSI 驱动的 Helm 仓库

helm repo add juicefs https://juicedata.github.io/charts/
helm repo update

步骤2: 然后查看charts资源包情况

# helm repo list |grep juicefs
juicefs https://juicedata.github.io/charts

# helm search repo juicefs
NAME                            CHART VERSION   APP VERSION     DESCRIPTION
juicefs/juicefs-csi-driver      0.19.3          0.23.0          A Helm chart for JuiceFS CSI Driver
juicefs/juicefs-s3-gateway      0.11.2          1.6.0           A Helm chart for JuiceFS S3 Gateway

步骤3: 检查 kubelet 根目录,用于更改values.yaml的kubeletDir配置
在CCE集群中任意一个worknode节点上执行以下命令:

ps -ef | grep kubelet |grep root-dir

image.png

以实际看到的为准,当前集群kubelet 根目录是:/mnt/paas/kubernetes/kubelet

3.2.2 修改values.yaml

新创建values-new.yaml,原values.yaml可以从chart包解压获取。
编辑 values-new.yaml 文件

vim values-new.yaml
image: 
  repository: juicedata/juicefs-csi-driver 
  tag: "v0.23.0"
  pullPolicy: "IfNotPresent"

dashboardImage: 
  repository: juicedata/csi-dashboard
  tag: "v0.23.0"
  pullPolicy: "IfNotPresent"

# The kubelet working directory, can be set using --root-dir when starting kubelet
# 必须更改为当前集群节点kubelet 工作目录
kubeletDir: /mnt/paas/kubernetes/kubelet

3.2.3 执行helm install进行安装

指定配置文件进行安装

# helm install juicefs-csi-driver juicefs/juicefs-csi-driver -n kube-system -f ./values-new.yaml

安装结果如下图所示
image.png

3.2.4 安装完后查看运行的pod

使用 kubectl 查看JuiceFS CSI 驱动 服务pod状态:

# kubectl -n kube-system get pod -l app.kubernetes.io/name=juicefs-csi-driver 
NAME                                      READY    STATUS   RESTARTS    AGE
juicefs-csi-controller-0                   4/4     Running   0          5m15s
juicefs-csi-controller-1                   4/4     Running   0          4m9s
juicefs-csi-dashboard-6cfdb7fd69-n78wp     1/1     Running   0          5m15s 
juicefs-csi-node-mwfjw                     3/3     Running   0          5m15s

3.3 动态创建

本次仅介绍动态配置方式,如果要使用静态配置方式创建pv请参考: https://juicefs.com/docs/zh/csi/guide/pv#static-provisioning

3.3.1 创建secret

场景:社区版,即元数据引擎使用自建的数据库
本次使用社区版,创建 Kubernetes Secret参考文档:https://juicefs.com/docs/zh/csi/guide/pv

apiVersion: v1
kind: Secret
metadata:
  name: juicefs-secret-test1
type: Opaque
stringData:
  name: juicefs-obs-test11
  # 填写存储元数据的数据库地址,支持多种类型数据库,具体以官方为准
  metaurl: "redis://:1********G@192.168.xx.xx:6379/1"
  storage: obs
  # 填写提前创建的OBS 桶的访问地址
  bucket: "https://aaaaa-hzj.obs.cn-north-4.myhuaweicloud.com"
  # 填写IAM用户的Access Key Id
  access-key: WL**********RU
  # 填写IAM用户的Secret Access Key
  secret-key: Ye*********************************Gf
  # 设置 Mount Pod 时区,默认为 UTC。
  envs: "{TZ: Asia/Shanghai}"
# kubectl apply -f secret1.yaml
secret/juicefs-secret-test1 created

3.3.2 创建StorageClass

用 kubectl 创建 StorageClass,需要提前创建好secret,创建完毕后,将相关信息按照下方示范填入对应字段。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: 
  name: juicefs-sc
provisioner: csi.juicefs.com
parameters:
  # 指定创建的secret名称juicefs-secret-test1 
  csi.storage.k8s.io/provisioner-secret-name: juicefs-secret-test1
  # 指定创建的secret所在名称空间 
  csi.storage.k8s.io/provisioner-secret-namespace: default
  # 指定创建的secret名称juicefs-secret-test1 
  csi.storage.k8s.io/node-publish-secret-name: juicefs-secret-test1
  # 指定创建的secret所在名称空间
  csi.storage.k8s.io/node-publish-secret-namespace: default
# kubectl apply -f sc.yaml
storageclass.storage.k8s.io/juicefs-sc created

3.3.3 创建pvc

kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim 
metadata: 
  name: juicefs-pvc
  namespace: default
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      # 从 StorageClass 中申请 10GiB 存储容量
      storage: 10Gi
  storageClassName: juicefs-sc
EOF

创建后,查看pvc 和 pv
image.png
image.png

433.4 创建deployment 挂载pvc

如果pod能挂载 pvc ,说明创建的secret和storageClass 正确。deployment yaml参考如下

kind: Deployment
apiVersion: apps/v1
metadata: 
  name: nginx-t1
  namespace: default
spec: 
  replicas: 1
  selector: 
    matchLabels:
      app: nginx-t1
      version: v1
  template:
    metadata:
      labels:
        app: nginx-t1
        version: v1
    spec:
      containers:
        - name: container-1
          image: swr.cn-north-4.myhuaweicloud.com/testapp/my-nginx:1.22.1-perl
          command:
            - nginx
            - '-g'
            - daemon off;
          ports:
            - containerPort: 80
              protocol: TCP
          resources:
            limits:
              cpu: 100m
              memory: 100Mi
            requests:
              cpu: 100m
              memory: 100Mi
          lifecycle:
            postStart:
              exec:
                command:
                  - /bin/bash
                  - '-c'
                  - sleep 1; echo $(date -u) >> /data/out.txt;
          volumeMounts:
          - mountPath: /data
            name: juicefs-pv
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
          securityContext:
            runAsUser: 0
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      securityContext: {}
      imagePullSecrets:
        - name: default-secret
      schedulerName: default-scheduler
      volumes:
      - name: juicefs-pv
        persistentVolumeClaim:
          claimName: juicefs-pvc

创建deployment后,查看pod状态

# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
nginx-t1-755675f4db-tghpd   1/1     Running   0          88s

查看pod 事件,显示挂载卷成功
image.png

查看对象存储,自动创建了一个目录:juicefs-obs-test11
image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。