Block Devices(块存储)
在 Rook 中,块存储有两种存储类型:副本存储和纠删码存储。这两种存储类型都可以在 Kubernetes 集群中使用,可以通过在 CephBlockPool 中指定不同的存储类别来实现。
- 「副本存储:」 是一种基于副本的存储方式,其中数据被复制到多个节点上,以提高数据的可靠性和可用性。在副本存储中,数据被复制到指定数量的节点,当其中任何一个节点出现故障时,系统仍然可以从其它节点读取数据,从而保证了数据的可靠性和可用性。
- 「纠删码存储:」 是一种基于纠删码的存储方式,其中数据被编码为多个数据块,并在不同的节点上存储这些数据块的编码片段。在纠删码存储中,数据被编码为多个数据块,并根据指定的参数对这些数据块进行编码。编码后的数据块被分散存储到不同的节点上,当某个节点出现故障时,系统可以使用存储在其它节点上的数据块编码片段来恢复数据。纠删码存储在数据可靠性和存储效率方面具有优势,但它通常需要更多的 CPU 和网络资源来执行编码和解码操作。
如何选择
在生产环境中选择 Rook 中的副本存储或纠删码存储需要考虑多个因素,包括数据的重要性、可用性要求、存储成本和系统性能等。
- 副本存储提供了简单、易于管理的数据冗余解决方案,通过复制多个数据副本到不同的节点上来提高数据的可靠性和可用性。在副本存储中,数据的每个副本都可以直接读取和写入,因此可以提供较低的读写延迟和较高的吞吐量。
- 纠删码存储通过对数据进行编码和分片,将数据的冗余信息分布到不同的节点上,以提高数据的可靠性和可用性。纠删码存储通常需要更少的存储空间和更低的存储成本,因为它只需要存储数据的冗余分片而不是完整的副本。但是,在读取和写入数据时,需要对多个节点进行通信和协调,因此可能会带来更高的读写延迟和较低的吞吐量,而且在发生节点故障时,恢复数据的时间也可能会更长
在选择 Rook 中的副本存储或纠删码存储时,需要考虑数据的重要性和可用性要求,以及存储成本和系统性能等因素。如果数据的重要性较高,可用性要求较高,并且存储成本较高,可以选择副本存储;如果数据的可用性要求较高,存储成本较低,并且可以容忍较高的读写延迟和较低的吞吐量,可以选择纠删码存储。在选择存储方案时,还需要考虑硬件资源和网络带宽等因素,以确保所选方案可以满足系统性能和可用性要求。
实战
- 创建CephBlockPool和StorageClass资源对象
apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: replicapool spec: failureDomain: host replicated: size: 3 requireSafeReplicaSize: true --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rook-ceph-block provisioner: rook-ceph.rbd.csi.ceph.com parameters: pool: replicapool imageFormat: "2" imageFeatures: layering csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node csi.storage.k8s.io/fstype: ext4 allowVolumeExpansion: true reclaimPolicy: Delete
这是一个用于配置Rook与Ceph集群交互的 Kubernetes StorageClass 的 YAML 文件。 StorageClass 提供了一种抽象方式,允许应用程序请求动态卷(PVC),而不需要事先了解存储资源的底层细节。
在这个 YAML 文件中,有两个 Kubernetes 对象:CephBlockPool 和 StorageClass。
CephBlockPool 是 Rook 中用于管理 Ceph 存储集群的块存储池的 Kubernetes 对象。这个特定的块存储池名为 replicapool,它使用主机故障域进行故障域分离,使用副本存储策略,并将每个对象的副本数量设置为 3,要求所有副本都必须是安全的。每个 CephBlockPool 都对应一个特定的存储后端,用于提供块存储服务。通过创建不同的 CephBlockPool,可以为不同的应用程序提供不同的存储配置和性能要求。
StorageClass 对象指定了使用 Rook Ceph 提供的 CSI 驱动程序创建的存储卷的默认设置。其中 provisioner 指定使用的 CSI 驱动程序名称,pool 指定使用的 Ceph 块存储池名称,imageFormat 指定创建块设备时要使用的映像格式,imageFeatures 指定要启用的块设备特性,例如层次化,csi.storage.k8s.io/provisioner-secret-name,csi.storage.k8s.io/controller-expand-secret-name 和 csi.storage.k8s.io/node-stage-secret-name 分别指定用于身份验证和授权的 Kubernetes 密钥名称,而 allowVolumeExpansion 和 reclaimPolicy 分别定义了动态卷是否允许扩容以及何时删除。
当使用rook搭建好集群后,它已经将用于身份验证和授权所需的 Kubernetes Secret 对象创建好了,使用下面命令可以查看:
[root@k8s-a-master rbd]# kubectl get secret -n rook-ceph NAME TYPE DATA AGE cluster-peer-token-rook-ceph kubernetes.io/rook 2 22h rook-ceph-admin-keyring kubernetes.io/rook 1 22h rook-ceph-config kubernetes.io/rook 2 22h rook-ceph-crash-collector-keyring kubernetes.io/rook 1 22h rook-ceph-dashboard-password kubernetes.io/rook 1 22h rook-ceph-mgr-a-keyring kubernetes.io/rook 1 22h rook-ceph-mgr-b-keyring kubernetes.io/rook 1 22h rook-ceph-mon kubernetes.io/rook 4 22h rook-ceph-mons-keyring kubernetes.io/rook 1 22h rook-csi-cephfs-node kubernetes.io/rook 2 22h rook-csi-cephfs-provisioner kubernetes.io/rook 2 22h rook-csi-rbd-node kubernetes.io/rook 2 22h rook-csi-rbd-provisioner kubernetes.io/rook 2 22h
- provisioner-secret-name 用于 CSI 驱动程序和存储卷创建器之间的身份验证和授权。
- controller-expand-secret-name 用于 CSI 驱动程序和存储卷扩展控制器之间的身份验证和授权。
- node-stage-secret-name 用于 CSI 驱动程序和节点挂载器之间的身份验证和授权。
- 开始创建
kubectl create -f storageclass.yaml
- 创建后验证
# 查看 Rook CephBlockPool 的资源定义 [root@k8s-a-master rbd]# kubectl get crd | grep cephblockpools.ceph.rook.io cephblockpools.ceph.rook.io 2023-04-03T08:28:30Z # 查看存储类 [root@k8s-a-master rbd]# kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE rook-ceph-block rook-ceph.rbd.csi.ceph.com Delete Immediate true 18h [root@k8s-a-master rbd]# # 查看 Rook CephBlockPool 的列表 [root@k8s-a-master rbd]# kubectl get cephblockpool -n rook-ceph NAME PHASE replicapool Ready # 查看详细信息 kubectl describe cephblockpool replicapool -n rook-ceph
我们已经将Kubernetes使用了Rook Ceph作为存储后端,并创建好了CephBlockPool和StorageClass,接着我们还需要创建一个PersistentVolumeClaim(PVC)对象来请求持久化存储资源。PV将在PVC创建后自动创建。
在创建PVC时,Kubernetes将检查可用的PV列表,寻找一个匹配请求的存储大小、访问模式和StorageClass的PV。如果找到一个可用的PV,则该PV将被绑定到PVC上,并成为PVC的一部分。如果没有可用的PV,则Kubernetes将等待,直到有足够的存储资源可用为止。
在这个过程中,Kubernetes将使用先前创建的StorageClass中指定的CephBlockPool的名称来确定要使用的Ceph存储池。Kubernetes将使用这个信息来自动创建一个对应的PV,该PV将在后台映射到Ceph存储池中。在创建PVC时,PV将自动创建并绑定到PVC上,以提供所需的持久化存储资源。
- 提前创建一个PVC
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: rook-ceph-block
在这里,PVC名称为my-pvc,请求5GB的存储空间,并将存储类设置为rook-ceph-block。
- 创建一个应用pod
apiVersion: v1 kind: Pod metadata: name: test-nginx-pod spec: containers: - name: test-nginx-container image: nginx volumeMounts: - name: storage mountPath: /data volumes: - name: storage persistentVolumeClaim: claimName: my-pvc
- 验证是否挂载成功
# 查看定义的pvc [root@k8s-a-master ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE my-pvc Bound pvc-76d69972-2a95-44bc-953d-1028b4b69435 5Gi RWO rook-ceph-block 74s # 看看pv有没有自动创建 [root@k8s-a-master ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-76d69972-2a95-44bc-953d-1028b4b69435 5Gi RWO Delete Bound default/my-pvc rook-ceph-block 77s # 进入pod查看数据目录 [root@k8s-a-master ~]# kubectl exec -it test-nginx-pod -- bash root@test-nginx-pod:/# root@test-nginx-pod:/# df -h Filesystem Size Used Avail Use% Mounted on overlay 250G 4.9G 246G 2% / tmpfs 64M 0 64M 0% /dev tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/rbd0 4.9G 24K 4.9G 1% /data # 在这里 /dev/mapper/centos-var 250G 4.9G 246G 2% /etc/hosts shm 64M 0 64M 0% /dev/shm tmpfs 7.7G 12K 7.7G 1% /run/secrets/kubernetes.io/serviceaccount tmpfs 3.9G 0 3.9G 0% /proc/acpi tmpfs 3.9G 0 3.9G 0% /proc/scsi tmpfs 3.9G 0 3.9G 0% /sys/firmware
- 卸载块存储
kubectl delete -f pod.yml kubectl delete -f pvc.yml kubectl delete -f storageclass.yaml # 这个yaml就是之前我们用于创建的,已经包含了CephBlockPool和StorageClass # 或者也可以单独执行删除指定的CephBlockPool和StorageClass,不过还是建议storageclass.yaml的方式 kubectl delete cephblockpools.ceph.rook.io replicapool -n rook-ceph kubectl delete storageclass rook-ceph-block
- kubectl delete -f pod.yml:这个命令将删除包含 Rook 块存储的 Pod。这将停止 Rook 块存储的所有实例和进程。
- kubectl delete -f pvc.yml:这个命令将删除 PVC (Persistent Volume Claim) 对象,这个对象定义了要使用的持久化存储资源。这将释放 Rook 块存储占用的存储空间。
- kubectl delete cephblockpools.ceph.rook.io replicapool -n rook-ceph:这个命令将删除名为 replicapool 的 Rook 块存储池。块存储池是一个逻辑卷,可以在其中创建块设备。删除块存储池将确保不再创建新的块设备。
- kubectl delete storageclass rook-ceph-block:这个命令将删除名为 rook-ceph-block 的 Rook 存储类。存储类指定了用于存储数据的存储类型和属性。删除存储类将确保不再创建新的 Rook 存储卷。
需要注意的是,这4个命令需要按照指定的顺序执行,以确保完全卸载 Rook 块存储。否则,可能会导致未清理的资源或数据遗留在集群中。