CSI driver 用于本地 PVs,使用ZFS提供基础服务。
Project 状态
版本 1.2.0, ZFS-LocalPV成为 GA(普遍可用)。为生产环境的使用做好了准备,参见 adopters。
Project 进度跟踪
查看 roadmap, e2e-wiki 和 e2e-test.
用法
要求的环境
在安装 ZFS driver 之前请确认 Kubernetes Cluster 具有下面的能力:
- 所有节点安装 zfs utils。
- ZPOOL 已经创建并提供 volume。
- 安装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 版本的特征。
- 关于ZFS的使用,参考:
设置
所有节点安装 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-controller
和 openebs-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,可以设置 volumeBindingMode
为 WaitForFirstConsumer
在 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
modeBlock
mode
- 支持的 fsTypes:
ext4
,btrfs
,xfs
,zfs
- Volume metrics
- Snapshot
- Clone
- Volume Resize
- Raw Block Volume
- Backup/Restore
- Ephemeral inline volume