当前位置: 首页 > news >正文

Kubernetes持久卷实战

前言

因为容器有数据持久化、以及容器间共享数据的需求,所以 kubernetes 提供了 Volume 机制。通过将 Volume 挂载到容器的一个目录中,容器便可以读写该目录,随后容器停止或销毁,Volume 数据得以保留。

Volume 支持很多类型,接入了大部分的存储后端,例如:基于宿主机目录的、基于 Secret 的、基于网络存储设备的,等等。

但是,Volume 还是有明显缺点的。那就是,Volume 不便于管理和维护。

举几个例子:

  • 当某个 Volume 不再被挂载使用,里面的数据如何处理?是保留 or 清理?
  • 如何限制挂载 Volume 的读写权限?如果我只想给某个容器读权限呢?
  • 如何限制 Volume 被挂载的 Pod 数量,我只想给某一个 Pod 挂载呢?

综上所述,Volume 只是实现了底层的数据存储需求,却没有对存储卷的生命周期以及权限进行管理,功能性和灵活性不够。

另外,不同类型的 Volume 配置方式都不一样。例如,基于 hostPath 和 基于 NFS 的 Volume 配置方式天差地别,要让非运维同学掌握所有 Volume 配置方式,不太现实。

因此,我们急需一个 Volume 的抽象,我不管你 Volume 底层是如何配置实现的,只要我的容器有存储需求,我就去申请一个 Volume,然后把它挂载到容器内,容器就可以对它进行读写了。

这个 Volume 抽象,kubernetes 给我们提供了,就是 PersistentVolume 和 PersistentVolumeClaim,简称 PV 和 PVC。

PersistentVolume

PersistentVolume (PV) 是由 kubernetes 管理员创建的存储卷资源,用于容器的数据持久化存储。

PV 是一个抽象层,它将底层存储(如云盘,NFS,本地磁盘等)抽象为 kubernetes 可管理的资源,屏蔽了底层存储的实现细节。PV 拥有独立与 Pod 之外的生命周期,确保数据在 Pod 重启或迁移后仍可访问。

PV 的一些关键属性如下:

  • 容量:定义存储卷的最大容量,如 10Gi
  • 访问模式:如 ReadWriteOnce(单节点读写)、ReadOnlyMany(多节点只读)等
  • 回收策略:Retain(保留数据)、Delete(删除数据)、Recycle(已废弃,不推荐)
  • 存储类:可关联 StorageClass 实现动态分配

PV回收策略

存储卷使用完毕后,可以通过 API 删除 PVC 对象,从而允许回收资源。回收策略告诉 PV 如何处理该卷。

可选项有:

  • Retain:PVC 删除,PV 仍然保留,确认数据没用了,再手动回收卷
  • Delete:删除 PVC 的同时会自动删除 PV,前提是插件支持
  • Recycle:删除 PVC 的同时,执行rm -rf清理 PV,使其成为一个新的 PV 服务下一个 PVC,前提也是要插件支持才行

PV访问策略

PV 的访问策略,用于限制 Pod 对 PV 的读写权限,以及 PV 可以被多个 Pod 同时读写等。

可选项有:

  • ReadWriteOnce:只能被单节点以读写模式挂载,缩写 RWO
  • ReadOnlyMany:可以被多个节点以只读模式挂载,缩写 ROX
  • ReadWriteMany:可以被多个节点以读写模式挂载,缩写 RWX
  • ReadWriteOncePod:只能被一个Pod以读写的模式挂载,缩写 RWOP

这是 PV 抽象层提供的选项,但是未必所有 PV 实现都支持,具体要看插件实现,使用前查阅相关文档。

PV的状态

命令kubectl get pv用于查看 PV 的状态:

STATUS 字段会有如下几种状态:

  • Available:可用,还没有被 PVC 绑定
  • Bound:已绑定,已经被 PVC 绑定
  • Released:已释放,PVC 被删除,但是资源还未被重新使用
  • Failed:失败,回收失败

PersistentVolumeClaim

PersistentVolumeClaim(简称PVC)是对 PV 资源的申请对象,kubernetes 管理员创建好 PV 后,其他人可以在部署 Pod 时创建 PVC 来申请 PV,用于 Pod 数据存储。

在创建 PVC 时,需要指定你要申请一个什么样的后端存储,申请多大的空间,以及 Pod 要对 PV 以什么访问模式进行挂载。描述好 PVC 后,kubernetes 会根据你的需求分配 PV。就像在部署 Pod 时,描述好需要多少 CPU 和内存,kubernetes 会帮你调度到合适的节点上一样。

这样的优点就是,使用 PVC 的同学彻底解放了,再也不用关心各种各样的 Volume 怎么配置了。

实战PV&PVC

案例:创建一个基于 HostPath 的 PV 和 PVC,然后部署一个 redis-pod,PVC 挂载到 redis-pod 实现 Redis 数据库的持久化存储。然后尝试删除并重启 redis-pod,查看数据是否丢失。

创建PV

HostPath 类型的 PV 创建是最简单的,它直接使用宿主机上的目录作为存储介质。

apiVersion: v1
kind: PersistentVolume
metadata:name: redis-pv
spec:capacity:storage: 1GiaccessModes:- ReadWriteOncehostPath:path: /opt/pv/redis

解释下这个配置:

  • 资源类型是 PersistentVolume,名称是 redis-pv
  • spec.capacity.storage指定 PV 的容量是 1Gi
  • spec.accessModesPV 的访问模式是 ReadWriteOnce,单节点读写模式
  • spec.hostPathPV 的类型是 hostPath,对应的宿主机目录是/opt/pv/redis

创建 PV 后,kubectl get pv查看 PV 是否创建成功,目前的状态是 Available 还未和 PVC 绑定

创建PVC

创建 PVC 申请 PV,注意访问模式和容量必须和 PV 匹配,否则会申请失败。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: redis-pvc
spec:accessModes:- ReadWriteOnceresources:requests:storage: 1Gi

kubectl get pvc查看 PVC 是否创建成功,可以看到当前 PVC 状态是 Bound,已经和 PV 绑定,绑定的 Volume 是 redis-pv。

同样,PV 状态也是 Bound,关联的是 default/redis-pvc。

创建Pod并挂载PVC

这里创建一个 redis-pod,启动一个 Redis 服务并暴露 6379 端口,将 PVC 挂载到 /data 目录。一旦 Redis 触发持久化操作,就会将 RDB 文件写入 /data 目录,因为挂载的是 HostPath 类型的 PV,实际 RDB 文件会写入到宿主机上的/opt/pv/redis目录。

apiVersion: v1
kind: Pod
metadata:name: redislabels:app: redis
spec:containers:- name: redisimage: docker.io/library/redis:7imagePullPolicy: Neverports:- containerPort: 6379volumeMounts:- mountPath: /dataname: redis-storagevolumes:- name: redis-storagepersistentVolumeClaim:claimName: redis-pvc

启动 Pod,kubectl get po -o wide查看 Pod 启动成功,Pod 分配的 IP 是10.244.1.129

命令redis-cli -h 10.244.1.129连接到 redis,然后写入一些数据,再发送save命令手动触发 RDB 持久化。

查看宿主机上的/opt/pv/redis/目录,发现 redis 的持久化文件 dump.rdb 已经生成。

删除Pod数据不丢失

最后验证一下,手动删除 Pod,数据是否会丢失。

命令kubectl delete po redis会删除 redis-pod,但是 PV 和 PVC 的状态并不受影响,可见它们的生命周期是独立于 Pod 之外的。

当然,宿主机上的/opt/pv/redis/dump.rdb持久化文件自然也还是保留的。

现在,我们重新启动一个 redis-pod,继续挂载该 PVC,新分配的 IP 是10.244.1.130

再次连接到Redis,发现之前写入的数据还在,Redis 通过 PV 和 PVC 实现数据持久化成功!

删除PVC

先删除 redis-pod,再命令kubectl delete pvc redis-pvc删除 PVC,发现 PV 的状态默认是 Released,已经和 PVC 解绑了,但还未重新使用。默认的回收策略是 Retain,也就是说,PV 的数据还是保留的,等待管理员手动删除。

当然,宿主机上的/opt/pv/redis/dump.rdb持久化文件自然也还是保留的。

尾巴

kubernetes 提供的 Volume 机制满足了 Pod 数据存储的需求,但是 Volume 偏底层,且不便于管理和维护。面对让人眼花缭乱的 Volume 类型和配置,使用者往往无所适从。因此,kubernetes 提供了 PV 和 PVC 抽象,管理员负责创建各种 PV,使用者如果有数据存储的需求,创建 PVC 去申请 PV 即可,而无需关心 PV 底层是怎么实现的。有了 PVC,使用者彻底从存储卷的细节中解放出来。

另外,PV 和 PVC 有独立于 Pod 之外的生命周期,这使得 PVC 可以被不同的 Pod 重复挂载,PV 也可以配置单独的回收策略,以服务下一个 PVC。

http://www.xdnf.cn/news/1111645.html

相关文章:

  • 13. G1垃圾回收器
  • os.loadavg()详解
  • Python 训练营打卡 Day 59-经典时序预测模型3
  • Java 大视界 -- Java 大数据机器学习模型在电商用户复购行为预测与客户关系维护中的应用(343)
  • IDEA中一个服务创建多个实例
  • 【C/C++】迈出编译第一步——预处理
  • [案例八] NX二次开发长圆孔的实现(支持实体)
  • TensorFlow2 study notes[2]
  • 【Linux网络】IP 协议详解:结构、地址与交付机制全面解析
  • 算法第三十一天:贪心算法part05(第八章)
  • Qt 多线程编程:单例任务队列的设计与实现
  • 【数据结构初阶】--顺序表(二)
  • 【读书笔记】《C++ Software Design》第一章《The Art of Software Design》
  • 【一起来学AI大模型】RAG系统组件:检索器(LangChain)
  • Python 实战:构建可扩展的命令行插件引擎
  • 试用了10款翻译软件后,我只推荐这一款!完全免费还超好用
  • 挖矿病毒判断与处理 - 入门
  • DBeaver连接MySQL8.0报错Public Key Retrieval is not allowed
  • Redis集群会有写操作丢失吗?为什么?
  • 1. 好的设计原则
  • C++法则21:避免将#include放在命名空间内部。
  • 箭头函数(Arrow Functions)和普通函数(Regular Functions)
  • 【JVM|类加载】第三天
  • 《汇编语言:基于X86处理器》第7章 整数运算(3)
  • AI:机器人未来的形态是什么?
  • 商业智能(BI)系统深度解析
  • 希尔排序和选择排序及计数排序的简单介绍
  • 【学习笔记】Nginx常用安全配置
  • QWidget的属性
  • 华为业务变革项目IPD基本知识