K8s006 | 数据存储方案
默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问题:
- 当容器挂掉kubelet将重启启动它时,文件将会丢失;
- 当Pod中同时运行多个容器,容器之间需要共享文件时。
Kubernetes的Volume解决了这两个问题。内部实现中,一个Volume只是一个目录,目录中可能有一些数据,pod的容器可以访问这些数据。至于这个目录是如何产生的、支持它的介质、其中的数据内容是什么,这些都由使用的特定Volume类型来决定。
K8s 支持很多类型的卷,包括持久卷(PersistentVolume)和临时卷(EphemeralVolume)。临时卷的生命周期与 Pod 一致,如 emptyDir,其存储的数据会随着 Pod 的销毁而消失,仅可用作临时存储空间。而持久卷的生命周期比 Pod 长,即使 Pod 销毁也可保留下来。值得注意的是,HostPath 虽然也是一种持久卷,但若 Pod 漂移到其他 Node 或当前 Node 故障,也无法保证数据持久化,因此有时被称为“半持久化存储”。
Kubernetes支持Volume类型有很多,比如:
- emptyDir
- hostPath
- local
- persistentVolumeClaim
- image
- nfs
- iscsi
- fc (fibre channel)
- configMap
- secret
- downwardAPI
- projected
参考文档:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes
这么多看着头晕啊,下面介绍几个常用的:
emptyDir
使用emptyDir,当Pod分配到Node上时,将会创建emptyDir,并且只要Node上的Pod一直运行,Volume就会一直存在。当Pod(不管任何原因)从Node上被删除时,emptyDir也同时会删除,存储的数据也将永久删除。注:删除容器不影响emptyDir。
emptyDir是在Pod分配到node时创建的,它的初始内容为空,并且无需指定宿主机上对应的目录文件,因为这是k8s自动分配的,当Pod从node上移除时,emptyDir中的数据也会被永久删除。
下面看一个Pod中有两个容器,共享同一个emptyDir的例子:
|
|
将上面的配置文件保存成emptyDir.yaml
,在K8s主机上执行:
|
|
下面分别进入两个容器操作:
|
|
hostPath
hostPath允许挂载Node上的文件系统到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。
|
|
这里/chende
就是node上的目录。/test-pd
是容器中的目录。
这种挂载方式比emptyDir更为持久,除非所在Node发生故障。不过,除了挂载一些配置文件和二进制文件之外,一般不采用该类挂载方式,因为这样的挂载操作增加了Pod文件与Node主机文件的耦合,不利于统一管理。
PV && PVC
PersistentVolume(PV)和PersistentVolumeClaim(PVC)
这两个概念用于pod和volume之间解耦。Pod根据自己的需要提出数据卷的申请,k8s系统将符合条件的数据卷返回给pod。这样一来pod就无需直接和数据卷本身强绑定了。Pod无需知道数据卷的细节信息,比如具体用的是什么存储。
Pod中对数据卷的申请为PVC,用来和PVC绑定的数据卷称为PV。PV可以有多种存储方式,比如NFS,iSCSI等。PV和PVC的生命周期如下:
A. 供应阶段
PV有两种供应方式
- static 静态方式由系统管理员创建PV
- dynamic 如果没有静态的PV。系统会动态创建出PV来满足PVC。PV的提供者为StorageClass。要使用动态供应,PVC必须要指定一个StorageClass。如果StorageClass设置为空,那么针对这个PVC的动态供应特性会被禁用。
B. 绑定阶段
这个阶段指的是PV和PVC绑定的过程。系统有一个机制,循环检查新创建的PVC,然后找到一个符合条件的PV,把他们绑定到一起。如果有多个满足要求的PV可以绑定,会使用消耗资源最小的那个。PV和PVC之间是一对一的关系。如果找不到符合条件的PV,PVC会一直保持未绑定状态。
C. 使用阶段
PVC绑定合适的PV之后,Pod使用这个PV。和PVC绑定并处于使用状态的PV不会被系统删除,防止数据丢失。如果用户删除了Pod正在使用的PVC,这个PVC不会被立即移除。直到这个PVC不被任何Pod使用的时候,才会被真正的删除。
D. 重新声明阶段
当PV不再使用的时候,k8s根据不同的策略来回收这些PV。如下三种策略:
- Retain策略(默认):在volume不再使用的时候,不删除旧的数据,等待管理员处理。
- Delete策略:会删除不再使用的PV,同时删除这些PV对应真实存储的资源。
- Recycle策略:删除volume内的内容,使得volume可供下次使用。
常用命令
|
|
下面看看简单示例:
|
|
K8s Master上分别执行kubectl create -f xxx.yaml
之后,看看效果。
PersistentVolume(PV)的回收策略、访问策略和状态是Kubernetes存储管理中的重要概念。
回收策略
- Retain:当PV的回收策略设置为Retain时,即使对应的PersistentVolumeClaim(PVC)被删除,PV也不会被自动删除。PV将进入Released状态,此时管理员可以手动回收PV,或者重新创建一个PVC来绑定这个PV。如果PV中包含重要数据,这种策略可以确保数据不会因PVC的删除而丢失。
- Recycle:当PV的回收策略设置为Recycle时,当PVC被删除后,PV中的数据将被清除(类似于执行rm -rf /thevolume/*),然后PV将变为Available状态,可以被新的PVC重新绑定。这种策略可以节省存储空间,但需要注意数据丢失的风险。
- Delete:当PV的回收策略设置为Delete时,当PVC被删除后,对应的PV也会被自动删除。这种策略适用于那些不再需要的PV,或者PV中的数据可以重新生成的情况。
访问策略
PV的访问策略通过accessModes字段来指定,它决定了PV可以以何种方式被访问。Kubernetes支持以下三种访问模式:
- ReadWriteOnce(RWO):PV可以被单个节点以读写模式挂载。这是最常见的访问模式,适用于大多数应用。
- ReadOnlyMany(ROX):PV可以被多个节点以只读模式挂载。这种模式适用于需要共享数据但不需要写入的应用。
- ReadWriteMany(RWX):PV可以被多个节点以读写模式挂载。这是最少见的访问模式,因为它需要存储后端支持多个节点同时读写。
- ReadWriteOncePod(RWOP):k8s v1.22引入的一种新的PV访问模式。与ReadWriteOnce(RWO)模式类似,RWOP也允许一个节点以读写方式挂载PV,但是RWOP更进一步地限制了这个访问权限,确保整个集群中只有一个Pod可以读取或写入该PV。
在选择PV的回收策略和访问策略时,需要根据应用的需求和存储后端的特性来进行权衡。例如,如果PV中包含重要数据,那么可能需要选择Retain策略来避免数据丢失;如果PV中的数据可以重新生成,那么可以选择Delete策略来节省存储空间。同样,如果应用需要同时从多个节点读写数据,那么需要选择RWX访问模式;如果只需要从单个节点读写数据,那么可以选择RWO访问模式。
状态
PV的状态可以反映其当前的可用性和使用情况。以下是PV可能的状态及其含义:
- Available(可用):PV当前未被任何PVC(PersistentVolumeClaim)绑定,可以被任何匹配的PVC绑定。
- Bound(已绑定):PV已经被一个PVC绑定,并且该PVC已经被一个Pod使用。此时,PV的存储资源已经被Pod独占使用。
- Released(已释放):PVC被删除,但是对应的PV还没有被集群自动回收。此时,PV处于空闲状态,但还不能被其他PVC绑定,需要等待一段时间(由管理员设置)后才能重新变为Available状态。
- Failed(失败):PV自动回收失败。这可能是因为PV所在的存储后端出现问题,或者PV的回收策略设置不正确等原因导致的。
需要注意的是,PV的状态是动态变化的,随着PVC的创建、绑定、删除等操作而发生变化。管理员需要密切关注PV的状态,并根据实际情况进行相应的操作,以确保集群中的存储资源能够被高效地利用和管理。
参考阅读:
https://www.jianshu.com/p/b3665b72126e
https://zhuanlan.zhihu.com/p/564242088
各存储方式的特点和使用场景
- EmptyDir:适用于临时文件交换或缓存,不适合长期存储数据。
- HostPath:简单易用,但不适合生产环境,因为可移植性和容错性较差。
- PersistentVolume:适用于需要稳定存储资源的应用,支持动态和静态 provisioning。
- 网络存储:适用于需要跨节点共享数据的应用,如NFS、GlusterFS等。
- Local Volume:适用于需要高性能存储的应用,但需要注意节点故障时的数据恢复。
- StatefulSet:适用于有状态应用,每个实例都有唯一的存储卷,确保数据的一致性和持久性。
持久化存储方案大比拼
随着 K8s 的普及,存储也成为 K8s 用户关注的一个重要问题:为了满足不同的场景需求,K8s 可以支持基于不同架构的多种存储方案,比如本地磁盘、CSI 外接商用存储、K8s 原生存储 3 种 K8s 持久化存储方案。
本地存储小规模系统可以优先考虑。外接商用存储绝大多数场景不推荐使用。下面着重看K8s原始存储方案。
K8s 原生存储
K8s 原生存储是专为支持容器而构建的存储方案。这种存储与 K8s 的集成程度更深,具有容器级别的数据服务粒度和自动化存储资源运维能力,也因此能够为 K8s 上的容器应用提供灵活扩展能力与自动化运维能力。
更多关于 K8s 原生存储的特性与能力,请参考这篇内容:
https://www.smartx.com/blog/2023/06/cloud-native-storage-concept/
目前,主流 K8s 原生存储主要有两种类型:开源产品(以 Rook(基于 Ceph)和 Longhorn 为代表)和闭源商用产品(以 Portworx 和 IOMesh 为代表)。这两种方案都能提供 K8s 原生的数据存储功能,也各有利弊:开源产品没有采购成本,具有技术实力的客户可以自行开发,具有社区支持,但若出现严重故障或漏洞,很难像商业厂商那样通过专业团队提供快速相应、深度解决问题的服务支持。另外,通过性能测试可以看出,目前基于自研闭源技术的 K8s 存储方案,在性能和稳定性方面要优于开源产品。欲了解测试详情,请阅读主流 K8s 持久化存储方案特性与性能对比(Longhorn / Rook / OpenEBS / Portworx / IOMesh):
https://www.smartx.com/blog/2023/07/kubernetes-persistent-storage-comparison/
三种方案总体对比
K8s原生存储产品
参考阅读:
https://www.51cto.com/article/608369.html
(完)
- 原文作者: 闪电侠
- 原文链接:https://chende.ren/2021/01/29184952-k8s-volume.html
- 版权声明:本作品采用 开放的「署名 4.0 国际 (CC BY 4.0)」创作共享协议 进行许可