首页 / 最佳实践 / 存储 / 使用混合类型设备部署分布式存储

使用混合类型设备部署分布式存储

本方案可帮助您在同一集群中更高效、合理地同时利用 SSD(Solid State Drives,固态硬盘)和 HDD(Hard Disk Drives,机械硬盘)两类存储设备。对于有高 I/O 要求的存储使用场景,可实现存储设备性能分层管理,提高存储读写性能。

使用限制

仅适用于 CephFS 文件存储(文件存储)及 CephRBD 块存储(块存储)。

方案概述

本方案借助 rook-ceph Operator 及 TopoLVM Operator 实现。考虑到 SSD 容量小但速度更快,HDD 大容量却速度较慢的特点,相关设计如下。

准备工作

提示:本方案所指 集群 均为存储设备所在的目标集群,所提及界面操作均为在目标集群下的操作。

  1. 检查集群 所有节点 的 SSD,确保均未进行过分区,也即为裸盘。 如果磁盘并非裸盘,可执行下面命令快速清空磁盘。

    注意:请确保磁盘上没有重要数据,或者已完成相关备份。

    dd if=/dev/zero of=/dev/$sda bs=4k count=512 # 替换 $sda 为具体磁盘名
  2. 在集群 所有节点 上,依次安装 lvm2 (Logical Volume Manager) 和 bc(Basic Calculator)。

    yum install -y lvm2 bc

配置 TopoLVM

提示:如果集群中已使用 TopoLVM,请确保现有 TopolvmCluster 实例满足步骤 2 中要求,然后可继续创建存储类(步骤 3 )供本方案使用。

操作步骤

  1. 在平台管理的左侧导航栏中,单击 应用商店管理 > Operators

  2. 已部署 Operators 页签中,单击 topolvm-operator,创建 / 更新 TopolvmCluster 实例。

    实例要求如下。等待 YAML 文件中 successClasses.state 为 create successful 状态时,说明操作成功。

    参数 说明
    name 实例的名称。
    spec.topolvmVersion TopoLVM 的镜像地址。如无特殊要求,使用默认镜像即可。
    deviceClasses.nodeName 待使用的 SSD 磁盘所在节点的名称。

    注意:如有多个节点,需分别设置。
    deviceClasses.classes 设备类,每个设备类对应一组相同特性的存储设备。

    提示:本方案中,每个节点只需要设置 1 个设备类。多个存储方案并存时,您也可设置多个设备类,以分别用于本方案及单独使用的 TopoLVM 存储方案。
    classes.className 设备类名称。建议根据磁盘性质填写,例如:osd-meta。

    注意:本方案中,各节点上设备类名称需一致。
    classes.volumeGroup 用于创建卷的组,需保证当前节点中名称唯一。
    classes.default 每个节点上都必须有且仅有一个设备类设为 true,即默认使用该类别。
    classes.devices 待挂载的磁盘,需为块设备。可挂载多个。
    devices.name 磁盘名称,请根据实际情况填写,例如 /dev/sda

    YAML 示例如下。

    apiVersion: topolvm.cybozu.com/v1
    kind: TopolvmCluster
    metadata:
      name: topolvmcluster
    spec:
      topolvmVersion: 10.0.130.54:5000/acp/topolvm:fb8bb31
      deviceClasses:
        - nodeName: 10.0.100.200
          classes:
            - className: osd-meta
              volumeGroup: mygroup
              default: true
              devices:
                - name: /dev/sda
        - nodeName: 10.0.100.300
          classes:
            - className: osd-meta
              volumeGroup: mygroup
              default: true
              devices:
                - name: /dev/sda
  3. <span =id=StorageClass>在集群的 任一控制节点 上,创建 TopoLVM 存储类。

    cat << EOF | kubectl create -n rook-ceph -f -
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: osd-meta # 存储类的名称,建议保持此值
    provisioner: topolvm.cybozu.com
    parameters:
      "topolvm.cybozu.com/device-class": "osd-meta"  #TopoLVM 实例中指定的 class 名称
    volumeBindingMode: WaitForFirstConsumer
    allowVolumeExpansion: true
    EOF

配置 local-storage

需依次创建 local-storage 存储类及本地持久卷。

操作步骤

  1. 在集群的 任一控制节点 上,创建 local-storage 存储类。

    cat << EOF | kubectl create -n rook-ceph -f -
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: osd-data # 存储类的名称,建议保持此值
    provisioner: kubernetes.io/no-provisioner
    reclaimPolicy: Delete
    volumeBindingMode: WaitForFirstConsumer
    EOF
  2. 在所有具备 HDD 磁盘 的集群节点上创建本地持久卷。

    说明:不同于 TopoLVM,local-storage 无法支持动态创建持久卷。您需手动将所有 HDD 用于创建本地持久卷。

    export HOSTIP=X.X.X.X #节点的 IP
    
    for i in "sdXX" "sdXX" "sdXX" #节点上所有 HDD 磁盘的名称
    do
    export SIZE=$(echo $( expr $(lsblk -rbno SIZE /dev/$i)/1024/1024/1024)  | bc)Gi
    cat << EOF | kubectl create -f -
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      generateName: osd-data-
      labels:
        used-by: rook-ceph-osd
    spec:
      capacity:
        storage: $SIZE
      volumeMode: Block
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Delete
      storageClassName: osd-data #前述章节中设置的 local-storage 存储类名称
      local:
        path: /dev/$i
      nodeAffinity:
        required:
          nodeSelectorTerms:
            - matchExpressions:
                - key: kubernetes.io/hostname
                  operator: In
                  values:
                    - $HOSTIP
    EOF
    done
  3. 检查持久卷创建结果。

    kubectl get pv -l used-by=rook-ceph-osd

配置 Ceph 分布式存储

部署 Rook-Ceph Operator

提示:如果您已在集群成功配置过分布式存储,说明已部署 Rook-Ceph Operator,可跳过此章节。

操作步骤

  1. 在平台管理的 存储管理 > 分布式存储 页面,单击 立即配置

  2. 在 安装 Operator 向导页中,单击 开始部署

    • 请耐心等待,当页面自动进入下一步时,说明 Operator 部署成功。

    • 如果部署失败,请参考界面提示处理。随后单击 清理,并重新部署 Operator。

创建 Ceph 集群

  1. 在集群的 任一控制节点 上,创建 Ceph 集群。

    #请根据实际环境修改环境变量
    export REGISTRY=192.160.0.0:8080  #私有仓库地址
    export OSDCOUNT=2 #集群中所有 HDD 磁盘个数
    export DATASIZE=300Gi #单块 HDD 磁盘的大小
    export METADATASIZE=30Gi #建议至少为 DATASIZE 的10%
    
    cat << EOF | kubectl create -f -
    
    apiVersion: ceph.rook.io/v1
    kind: CephCluster
    metadata:
      name: ceph-cluster #Ceph 集群的名称
      namespace: rook-ceph
    spec:
      cephVersion:
        image: $REGISTRY/3rdparty/ceph/ceph:v14.2.11
      storage:
        storageClassDeviceSets:
          - name: set1
            count: $OSDCOUNT
            portable: false
            tuneDeviceClass: true
            tuneFastDeviceClass: false
            encrypted: false
            placement:
              tolerations:
                - effect: NoSchedule
                  operator: Exists
              topologySpreadConstraints:
                - maxSkew: 1
                  topologyKey: kubernetes.io/hostname
                  whenUnsatisfiable: ScheduleAnyway
                  labelSelector:
                    matchExpressions:
                      - key: app
                        operator: In
                        values:
                          - rook-ceph-osd
            volumeClaimTemplates:
              - metadata:
                  name: data
                spec:
                  resources:
                    requests:
                      storage: $DATASIZE
                  storageClassName: osd-data #前述章节中设置的 local-storage 存储类名称
                  volumeMode: Block
                  accessModes:
                    - ReadWriteOnce
              - metadata:
                  name: metadata
                spec:
                  resources:
                    requests:
                      storage: $METADATASIZE
                  storageClassName: osd-meta #前述章节中设置的 TopoLVM 存储类名称
                  volumeMode: Block
                  accessModes:
                    - ReadWriteOnce
      network:
        hostNetwork: true
      mon:
        count: 3
        allowMultiplePerNode: false
      mgr:
        modules:
          - name: pg_autoscaler
            enabled: true
      crashCollector:
        disable: false
      dashboard:
        enabled: true
      monitoring:
        enabled: true
      dataDirHostPath: /var/lib/rook
      disruptionManagement:
        managePodBudgets: false
      placement:
        all:
          tolerations:
            - effect: NoSchedule
              operator: Exists
      removeOSDsIfOutAndSafeToRemove: false
      resources:
        mgr:
          requests:
            cpu: 500m
            memory: 512Mi
        mon:
          requests:
            cpu: 500m
            memory: 1024Mi
        osd:
          requests:
            cpu: 500m
            memory: 2048Mi
    
    EOF
  2. 创建过程需要一定耗时,请等待 30 分钟左右,检查 Ceph 集群部署结果。

    kubectl get pod -n rook-ceph -l app=rook-ceph-osd

    当查得 osd 容器组个数与 HDD 个数一致,且均为 Running 状态时,Ceph 集群部署成功。

    如果等待时间过长,请检查前述配置,确保内容正确后继续等待。

创建存储池

  1. 在集群的 任一控制节点 上,按需创建存储池。

    文件存储池

    cat << EOF | kubectl create -f -
    
    apiVersion: ceph.rook.io/v1
    kind: CephFilesystem
    metadata:
      name: cephfs #CephFS 存储池的名称
      namespace: rook-ceph
    spec:
      metadataPool:
        replicated:
          size: 3
          requireSafeReplicaSize: true
      dataPools:
        - failureDomain: host
          replicated:
            size: 2
            requireSafeReplicaSize: true
      preservePoolsOnDelete: true
      metadataServer:
        activeCount: 1
        activeStandby: false
        placement:
          tolerations:
            - effect: NoSchedule
              operator: Exists
          podAffinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - key: app
                        operator: In
                        values:
                          - rook-ceph-mds
                    topologyKey: kubernetes.io/hostname
                  preferredDuringSchedulingIgnoredDuringExecution:
                    - weight: 100
                      podAffinityTerm:
                        labelSelector:
                          matchExpressions:
                            - key: app
                              operator: In
                              values:
                                - rook-ceph-mds
        resources:
          requests:
            cpu: 500m
            memory: 2048Mi
    
    EOF

    块存储池

    cat << EOF | kubectl create -f -
    
    apiVersion: ceph.rook.io/v1
    kind: CephBlockPool
    metadata:
      name: cephrbd #CephRBD 存储池的名称
      namespace: rook-ceph
    spec:
      failureDomain: host
      replicated:
        size: 2
    
    EOF
  2. 在平台管理的 存储管理 > 分布式存储 页面可看到成功添加的存储池。

创建存储类

  1. 在平台管理的 存储管理 > 存储类 页面,单击 创建存储类

  2. 选择 CephFS 文件存储 或 CephRBD 块存储 ,单击 下一步

  3. 按要求配置参数,单击 创建

验证

使用前述章节中创建的 Ceph 相关存储类创建持久卷声明,并在计算组件中绑定该持久卷,随后进行读写验证。

  1. 在平台管理的 存储管理 > 分布式存储 页面可看到已成功添加 SSD 和 HDD 磁盘。

  2. 在平台管理的 存储管理持久卷声明 页面,使用前述步骤创建的 Ceph 相关存储类创建持久卷声明。

  3. 在 计算组件 > 部署页面中,为任一部署(Deployment)绑定上述持久卷声明,并挂载持久卷。

  4. 使用 EXEC 方式进入上述部署中的任一容器,并进行读写验证。

常见问题

如果 TopoLVM 实例迟迟无法变为 create successful 状态,请参考下述步骤排查并处理。

  1. 检查 TopoLVM 相关容器组状态。

    下述回显为正常状态的示例。如果任一容器组,例如 topolvm-prepare-vg-192.168.25.200-7jwfw 为其他状态,请继续执行后续步骤。

    # kubectl get pod -n operators
    NAME READY STATUS RESTARTS AGE
    topolvm-controller-6fd488cb9b-plwf8 5/5 Running 0 5h8m
    topolvm-controller-6fd488cb9b-t7s9p 5/5 Running 0 5h8m
    topolvm-node-192.168.25.200-84d7f64c54-pb8gt 4/4 Running 0 5h8m
    topolvm-operator-868f85bfb7-qkq8j 1/1 Running 0 5h24m
    topolvm-prepare-vg-192.168.25.200-7jwfw 0/1 Completed 0 5h8m
  2. 检查集群 所有节点,确保已  安装 lvm2

  3. 检查集群 所有节点 的 SSD, 确保均为裸盘

  4. 清理 TopoLVM 集群。

    1. 进入平台管理的 应用商店管理 > Operators页面。

    2. 已部署 Operators 页签中,单击 topolvm-operator

    3. 导出 TopoLVM 实例 YAML 文件,然后删除 TopoLVM 实例。

    4. 根据 YAML 文件中信息,依次在相关节点上删除所有卷组和物理卷。

      lvm vgremove {卷组的名称}
      lvm pvremove {该卷组中的物理卷}
  5. 重新 创建 TopoLVM 实例