ZFS-LocalPV:OpenEBS ZFS CSI Driver

原创
2021/06/22 07:17
阅读数 342

CSI driver 用于本地 PVs,使用ZFS提供基础服务。

Project 状态

版本 1.2.0,  ZFS-LocalPV成为 GA(普遍可用)。为生产环境的使用做好了准备,参见 adopters

Project 进度跟踪

查看 roadmap, e2e-wikie2e-test.

 

用法

要求的环境

在安装 ZFS driver 之前请确认 Kubernetes Cluster 具有下面的能力:

  1. 所有节点安装 zfs utils。
  2. ZPOOL 已经创建并提供 volume。
  3. 安装RBAC components 到 kube-system namespace。该OpenEBS ZFS driver components 安装到 kube-system namespace ,允许标识为system critical components。

支持的系统

K8S : 1.18+

OS : Ubuntu, CentOS

ZFS : 0.7, 0.8

检查  features 支持,确认每一个 k8s 版本的特征。

设置

所有节点安装 zfsutils-linux 。如下:

$ apt-get install zfsutils-linux

到每个节点创建 ZFS Pool,将用于提供 volumes。可以安装需求创建Pool ,可以是 striped, mirrored 或 raidz pool。

If you have the disk(say /dev/sdb) then you can use the below command to create a striped pool:

zpool create zfspv-pool /dev/sdb

可以创建 mirror 或 raidz pool 满足特定需求, 查看 https://github.com/openzfs/zfs 获取更多信息。

如果没有额外的 disk,也可以创建 zpool 到 loopback device,作为 sparse file而存储。建议仅用于测试。

truncate -s 100G /tmp/disk.img
zpool create zfspv-pool `sudo losetup -f /tmp/disk.img --show`

当 ZFS Pool创建好,使用 zpool status 命令确认,如下所示:

$ sudo zpool status
  pool: zfspv-pool
 state: ONLINE
  scan: none requested
config:

	NAME        STATE     READ WRITE CKSUM
	zfspv-pool  ONLINE       0     0     0
	  sdb       ONLINE       0     0     0

errors: No known data errors

配置自定义的 topology keys (if needed),这用在哼多场合,比如创建 PV on nodes到特定的zone。添加标签到节点并且使用key在storageclass,来获取调度决策:

https://github.com/openebs/zfs-localpv/blob/master/docs/faq.md#6-how-to-add-custom-topology-key

安装

安装最新的OpenEBS ZFS driver,运行如下命令:

$ kubectl apply -f https://openebs.github.io/charts/zfs-operator.yaml

定制化参数使用 kubectl apply -k deploy/yamls, 查看 kustomize yaml

⚠️注意: 对于部分 Kubernetes 分发版,在kubelet 目录需要在 YAML中改变以发挥 operator 的能力(在openebs-zfs-controlleropenebs-zfs-node)。

  • 对于 microk8s, 需要改变 kubelet 目录为 /var/snap/microk8s/common/var/lib/kubelet/, 我们需要替换 /var/lib/kubelet/ ,使用 /var/snap/microk8s/common/var/lib/kubelet/ 在operator yaml 中,然后在 microk8s中应用。

  • 对于 k0s, 缺省目录 (/var/lib/kubelet) 将改变为 /var/lib/k0s/kubelet

检查 ZFS driver Components 已经正确安装和运行,如下命令:

$ kubectl get pods -n kube-system -l role=openebs-zfs

取决于节点数量,查看 zfs-controller pod 和 zfs-node daemonset 的运行状态,如下:

NAME                       READY   STATUS    RESTARTS   AGE
openebs-zfs-controller-0   5/5     Running   0          5h28m
openebs-zfs-node-4d94n     2/2     Running   0          5h28m
openebs-zfs-node-gssh8     2/2     Running   0          5h28m
openebs-zfs-node-twmx8     2/2     Running   0          5h28m

当 ZFS driver 安装好,就可以用其提供 volume。

部署

1. 创建 Storage class

$ cat sc.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-zfspv
parameters:
  recordsize: "4k"
  compression: "off"
  dedup: "off"
  fstype: "zfs"
  poolname: "zfspv-pool"
provisioner: zfs.csi.openebs.io

该 storage class 包含 volume parameters如 recordsize(should be power of 2), compression, dedup 和 fstype。可以根据需要选择自己的参数设置。在 zfs properties paramenters 为提供的情况下,该volume 将从 ZFS Pool继承相应的参数。该 poolname 是必须的参数,poolname 可以是 root dataset 或者 child dataset。

poolname: "zfspv-pool"
poolname: "zfspv-pool/child"

该 dataset provided under poolname 必须在所有节点上都存在。查看文档 storageclasses 了解 ZFS-LocalPV 支持的参数。

  • ext2/3/4 或 xfs 或 btrfs 作为 FsType

如果提供 fstype 为 ext2/3/4 or xfs or btrfs, 该驱动程序将创建 ZVOL,是一个 blockdevice carved out of ZFS Pool。该 blockdevice 将格式化为对应的文件系统(ext2/3/4 or xfs),从而为应用提供对应的文件系统。该情况下, filesystem layer on top of ZFS filesystem, 应用无法得到最优的性能。示例的 storage class for ext4 fstype 如下:

$ cat sc.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-zfspv
parameters:
  volblocksize: "4k"
  compression: "off"
  dedup: "off"
  fstype: "ext4"
  poolname: "zfspv-pool"
provisioner: zfs.csi.openebs.io

注意这里 volblocksize 替代了recordsize ,因为创建了 ZVOL, 从而创建 block device。注意在ZFS, volblocksize 必须是 power of 2。

  • zfs as FsType

如果提供 "zfs" as the fstype, zfs driver 将创建ZFS DATASET 在 ZFS Pool。在 application and storage没有额外的中间层,applications可以获得更好的性能示例的 storage class 如下:

$ cat sc.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-zfspv
parameters:
  recordsize: "4k"
  compression: "off"
  dedup: "off"
  fstype: "zfs"
  poolname: "zfspv-pool"
provisioner: zfs.csi.openebs.io

注意这里提供 recordsize 用于创建 ZFS datasets,指定了maximum block size 。该 recordsize 必须是 power of 2 for ZFS datasets。

  • ZPOOL 可用性

如果ZFS pool只在特定节点可用,使用topology 告诉可用的节点列表。如下的storage class, 使用 allowedTopologies描述那些节点的 ZFS pool 可用:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-zfspv
allowVolumeExpansion: true
parameters:
  recordsize: "4k"
  compression: "off"
  dedup: "off"
  fstype: "zfs"
  poolname: "zfspv-pool"
provisioner: zfs.csi.openebs.io
allowedTopologies:
- matchLabelExpressions:
  - key: kubernetes.io/hostname
    values:
      - zfspv-node1
      - zfspv-node2

上面的 storage class告诉 ZFS pool "zfspv-pool" 在节点 zfspv-node1 和 zfspv-node2 可用。 ZFS driver 将只在这两个节点上创建存储卷。

  • 注意 provisioner name for ZFS driver 是 "zfs.csi.openebs.io", 我们必须使用这个来创建 storage class,从而 volume provisioning/deprovisioning 请求能达到 ZFS driver。
  • 调度-Scheduler

ZFS driver有自己的scheduler将分布PV到所有节点,因此一个节点将不会载入整个的volumes。目前的driver支持两种调度算法:VolumeWeighted 和 CapacityWeighted, 将尝试发现更少卷或容量的pool作为 ZFS pool。了解如何通过 storage-class 选择调度器查看 this。一旦找到 node, 将为该节点创建 PV以及创建一个 ZFSVolume custom resource for the volume with the NODE information。该watcher for this ZFSVolume CR 将获得该object 并创建 ZFS dataset(zvol) ,并使用上面的节点的给定的ZFS property。

该调度算法目前只支持 number of ZFS volumes 或者 total capacity,没有考虑内存和CPU占用的情况。如果想要使用cpu/memory 限制,kubernetes scheduler 可以使用。为了使用 kubernetes scheduler,可以设置 volumeBindingModeWaitForFirstConsumer在 storage class中,这将触发delayed binding, i.e kubernetes scheduler将首先调度 application pod first 然后询问 ZFS driver 来创建 PV. 该驱动将 PV 将创建到 pod调度的节点上。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-zfspv
allowVolumeExpansion: true
parameters:
  recordsize: "4k"
  compression: "off"
  dedup: "off"
  fstype: "zfs"
  poolname: "zfspv-pool"
provisioner: zfs.csi.openebs.io
volumeBindingMode: WaitForFirstConsumer

⚠️注意:一旦 PV 在节点上创建,使用该PV的应用将一直被调度到该节点上。该 application 不能移动到非PV所在的其它节点上。

2. 创建 PVC

$ cat pvc.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: csi-zfspv
spec:
  storageClassName: openebs-zfspv
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

创建一个PVC,使用ZFS driver的 storage class。分配的volume size 将取整到Mi 或 Gi 单位,查看 faq 获取详情。

如果食用storageclass的立即绑定,可以立即查看kubernetes resource 的对应 zfs volume。在延迟binding情况下,在pod被调度以后检查。

$ kubectl get zv -n openebs
NAME                                       ZPOOL        NODE           SIZE         STATUS   FILESYSTEM   AGE
pvc-34133838-0d0d-11ea-96e3-42010a800114   zfspv-pool   zfspv-node1    4294967296   Ready    zfs          4s
$ kubectl describe zv pvc-34133838-0d0d-11ea-96e3-42010a800114 -n openebs
Name:         pvc-34133838-0d0d-11ea-96e3-42010a800114
Namespace:    openebs
Labels:       kubernetes.io/nodename=zfspv-node1
Annotations:  <none>
API Version:  openebs.io/v1alpha1
Kind:         ZFSVolume
Metadata:
  Creation Timestamp:  2019-11-22T09:49:29Z
  Finalizers:
    zfs.openebs.io/finalizer
  Generation:        1
  Resource Version:  2881
  Self Link:         /apis/openebs.io/v1alpha1/namespaces/openebs/zfsvolumes/pvc-34133838-0d0d-11ea-96e3-42010a800114
  UID:               60bc4df2-0d0d-11ea-96e3-42010a800114
Spec:
  Capacity:       4294967296
  Compression:    off
  Dedup:          off
  Fs Type:        zfs
  Owner Node ID:  zfspv-node1
  Pool Name:      zfspv-pool
  Recordsize:     4k
  Volume Type:    DATASET
Status:
  State: Ready
Events:           <none>

该 ZFS driver将创建一个ZFS dataset(or zvol as per fstype in the storageclass) 在节点 zfspv-node1的 ZFS pool中,该dataset name与 PV 名称一样。到节点 zfspv-node1 查看卷,如下:

$ zfs list
NAME                                                  USED  AVAIL  REFER  MOUNTPOINT
zfspv-pool                                            444K   362G    96K  /zfspv-pool
zfspv-pool/pvc-34133838-0d0d-11ea-96e3-42010a800114    96K  4.00G    96K  legacy

3. 部署应用

创建deployment yaml 使用由ZFS-LocalPV storage支持的pvc,如下:

$ cat fio.yaml

apiVersion: v1
kind: Pod
metadata:
  name: fio
spec:
  restartPolicy: Never
  containers:
  - name: perfrunner
    image: openebs/tests-fio
    command: ["/bin/bash"]
    args: ["-c", "while true ;do sleep 50; done"]
    volumeMounts:
       - mountPath: /datadir
         name: fio-vol
    tty: true
  volumes:
  - name: fio-vol
    persistentVolumeClaim:
      claimName: csi-zfspv

在application得到deployment 之后,到节点查看zfs volume,可以看到 ZFS pool的空间已经被消费。

4. ZFS 属性修改

ZFS Volume Property 可以改变,如 压缩设为 on/off,可以简单滴编辑 kubernetes resource,如下:

kubectl edit zv pvc-34133838-0d0d-11ea-96e3-42010a800114 -n openebs

可以编辑对应的 property 如 compression on 或者dedup on,然后保存。该特性将被应用到相应的 volume,在相应的节点使用下面的命令进行检查:

zfs get all zfspv-pool/pvc-34133838-0d0d-11ea-96e3-42010a800114

5. 移除卷

为了移除卷可以删除使用该volume的应用然后删除该pv。该卷将从 ZFS pool中删除,数据将被释放。

$ kubectl delete -f fio.yaml
pod "fio" deleted
$ kubectl delete -f pvc.yaml
persistentvolumeclaim "csi-zfspv" deleted

特点

  • 存取模式
    • ReadWriteOnce(单读写)
    • ReadOnlyMany(多读单写)
    • ReadWriteMany(多读多写)
  • Volume 模式
    • Filesystem mode
    • Block mode
  • 支持的 fsTypes: ext4, btrfs, xfs, zfs
  • Volume metrics
  • Snapshot
  • Clone
  • Volume Resize
  • Raw Block Volume
  • Backup/Restore
  • Ephemeral inline volume
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部