应用存储和持久化数据卷

Volumes 介绍

Pod Volumes 的作用

  • pod容器在异常退出后,容器内部的数据不会丢失
  • 同一个pod中多个容器需要共享数据

Pod Volumes 的类型

  • 本地存储,常用的有 emptydir/hostpath
  • 网络存储:网络存储当前的实现方式有两种,一种是 in-tree,它的实现代码是放在 K8s 代码仓库中的,随着 K8s 对存储类型支持的增多,这种方式会给 K8s 本身的维护和发展带来很大的负担;而第二种实现方式是 out-of-tree,它的实现其实是给 K8s 本身解耦的,通过抽象接口将不同存储的 driver 实现从 K8s 代码仓库中剥离,因此 out-of-tree 是后面社区主推的一种实现网络存储插件的方式;
  • Projected Volumes:它其实是将一些配置信息,如 secret/configmap 用卷的形式挂载在容器中,让容器中的程序可以通过 POSIX 接口来访问配置数据;
  • PV 与 PVC

Pod Volumes 的缺点

  • pod 中声明的 volume 生命周期与 pod 是相同的,如用 Deployment 管理的 pod,在做镜像升级的过程中,会产生新的 pod并且删除旧的 pod ,新旧 pod 之间无法复用数据
  • 宿主机宕机的时候,要把上面的 pod 迁移,pod volumes无法迁移
  • 多个pod间无法共享
  • 功能扩展性差

PV(Persistent Volumes)

pv的出现就是为了解决Pod Volumes的缺点,它可以将存储和计算分离,通过不同的组件来管理存储资源和计算资源,然后解耦 pod 和 Volume 之间生命周期的关联

PV的创建方式

  • 静态产生方式 - 静态 Provisioning

由集群管理员事先去规划这个集群中的用户会怎样使用存储,它会先预分配一些存储,也就是预先创建一些 PV;然后用户在提交自己的存储需求(也就是 PVC)的时候,K8s 内部相关组件会帮助它把 PVC 和 PV 做绑定;之后用户再通过 pod 去使用存储的时候,就可以通过 PVC 找到相应的 PV,它就可以使用了

不足:需要集群管理员预分配,预分配其实是很难预测用户真实需求,容易造成资源浪费

  • 动态 Dynamic Provisioning

集群管理员不预分配 PV,他写了一个模板文件,这个模板文件是用来表示创建某一类型存储(块存储,文件存储等)所需的一些参数,这些参数是用户不关心的,给存储本身实现有关的参数。用户只需要提交自身的存储需求,也就是 PVC 文件,并在 PVC 中指定使用的存储模板(StorageClass)。

K8s 集群中的管控组件,会结合 PVC 和 StorageClass 的信息动态,生成用户所需要的存储(PV),将 PVC 和 PV 进行绑定后,pod 就可以使用 PV 了。通过 StorageClass 配置生成存储所需要的存储模板,再结合用户的需求动态创建 PV 对象,做到按需分配,在没有增加用户使用难度的同时也解放了集群管理员的运维工作。

PV Spec 重要字段

  • Capacity:对象存储的大小

  • AccessModes:访问策略控制

    ​ ReadWriteOnce只允许单node读写

    ​ ReadOnlyMany允许多个node只读访问

    ​ ReadWriteMany允许多个node读写访问

  • ReclaimPolicy:用户 PV 的 PVC 在删除之后,PV 应该做如何处理

    ​ Recycle(已弃用)

    ​ delete PVC 被删除之后,PV 也会被删除

    ​ Retain PVC 被删除之后,PV 保留需要管理员手动删除

  • StorageClassName:使用动态 Provisioning 时,必须指定模板

  • NodeAffinity:通过 NodeAffinity 来声明对node的限制

PV 状态流转

img

PVC(Persistent Volumes Claim)

为了简化 K8s 用户对存储的使用方式,做到职责分离。通常用户在使用存储的时候,只用声明所需的存储大小以及访问模式

架构设计

PV 和 PVC 的处理流程

l34

l35

第一个 create 阶段,主要是创建存储;第二个 attach 阶段,就是将那块存储挂载到 node 上面(通常为将存储 load 到 node 的 /dev 下面);第三个 mount 阶段,将对应的存储进一步挂载到 pod 可以使用的路径

csi 是什么?csi 的全称是 container storage interface,它是 K8s 社区后面对存储插件实现 ( out of tree ) 的官方推荐方式:

第一部分是由 k8s 社区驱动实现的通用的部分,像我们这张图中的 csi-provisioner和 csi-attacher controller;

另外一种是由云存储厂商实践的,对接云存储厂商的 OpenApi,主要是实现真正的 create/delete/mount/unmount 存储的相关操作,对应到上图中的 csi-controller-server 和 csi-node-server。

参考链接

https://juejin.im/post/5d9d905351882551347ef124