写点什么

深入浅出聊聊 Kubernetes 存储(二):搞定持久化储存

  • 2020-04-22
  • 本文字数:4765 字

    阅读完需:约 16 分钟

深入浅出聊聊Kubernetes存储(二):搞定持久化储存

回顾

在本系列文章的上一篇中,我们讲到了PV,PVC,Storage Class以及Provisioner


简单回顾一下:


  1. PV 在最一开始是设计成了一个需要管理员预先分配的存储块。引入 Storage Class 和 Provisioner 之后,用户可以动态地供应 PV。

  2. PVC 是对 PV 的请求,当和 Storage Class 一起使用时,它将触发与相匹配 PV 的动态供应。

  3. PV 和 PVC 总是一一对应的。

  4. Provisioner 是给用户提供 PV 的插件。它可以把管理员从为持久化创建工作负载的繁重角色中解脱出来。

  5. Storage Class 是 PV 的分类器。相同的 Storage Class 中的 PV 可以共享一些属性。在大多数情况下,Storage Class 和 Provisioner 一起使用时,可以把它当作具有预定义属性的 Provisioner。因此,当用户请求它时,它能够用这些预定义的属性动态地提供 PV。


不过上述这些只是在 Kubernetes 中使用持久化存储的其中一种方法而已

Volume

在前一篇文章中,我们提到 Kubernetes 中还有一个卷(Volume)的概念。为了把 Volume 和持久卷(Persistent Volume)区分开,大家有时会称它为 In-line Volume 或者 Ephemeral Volume。


这里我们引用 Volume 的定义:


Kubernetes Volume…有一个显式的生命周期——这和包含它的 pod 的生命周期相同。因此,Volume 的生命周期比在 pod 中运行的任何容器都长,并且在容器重启的时候会保存数据。当然,当 Pod 终止时,Volume 也将终止。更重要的是,Kubernetes 支持多种类型的 Volume,一个 pod 中也可以同时使用任何数量的 Volume。

在其核心部分,Volume 只是一个目录,可能其中包含了一些数据,这些数据可由 pod 中的容器访问。这些目录是如何产生的、支持它的介质、以及它的内容都是由所使用的特定 volume 的类型决定的。


Volume 一个重要属性是,它与所属的 pod 具有相同的生命周期。如果 pod 消失了,它也会消失。这与 Persistent Volume 不同,因为 Persistent Volume 将继续存在于系统中,直到用户删除它。Volume 还可以在同一个 pod 中的容器间共享数据,不过这不是主要的用例,因为通常情况下用户只会在每个 pod 中使用一个容器。


因此,这更可以把 Volume 看作是 pod 的属性而不是一个独立的对象。正如它的定义所说,Volume 表示 pod 中的目录,而 Volume 的类型定义了目录中的内容。例如,Config Map Volume 类型将会在 Volume 目录中从 API 服务器创建配置文件;PVC Volume 类型将从目录中相应的 PV 里挂在文件系统等等。实际上,Volume 几乎是在 pod 中本地使用存储的唯一方法。


Volume、Persistent Volume 和持久卷声明(Persistent Volume Claim)之间很容易弄混淆。假设有一个数据流,它是这样 PV->PVC->Volume。PV 包含了真实数据,绑定到 PVC 上,最终变成 pod 中的 Volume。


然而,除了 PVC,Volume 还可以由 Kubernetes 直接支持的各种类型的存储库支持,从这个意义上来说,Volume 的定义也挺令人困惑的。


我们需要知道的事,我们已经有了 Persistent Volume,它支持不同类型的存储解决方案。我们还有 Provisioner,它支持类似(并不完全相同)的解决方案。而且我们还有不同类型的 Volume。


那么,它们到底有什么不同呢?如何在它们之间选择?

持久化数据的多种方式

以 AWS EBS 为例。让我们来细数 Kubernetes 中的持久化数据方式吧。

Volume 方式

awsElasticBlockStore 是一个 Volume 类型。


你可以创建一个 Pod,定义一个 awsElasticBlockStore 类型的 volume,设置好 volumeID,接着使用 pod 中存在的 EBS volume。


该 EBS volume 在直接和 Volume 使用前必须已经存在。

PV 方式

AWSElasticBlockStore 还是一个 PV 类型。


所以你可以创建一个 PV,用它来表示 EBS volume(假设你有这样的权限),然后创建一个和它绑定的 PVC 卷。最后,令 PVC 作为 volume,然后就可以在 pod 中使用它了。


和 Volume 方法类似,EBS volume 在创建 PV 之前就必须存在。

Provisioner 方式

kubernetes.io/aws-ebs 是一个 Kubernetes 中用于 EBS 的内置 Provisioner。


你可以用 Provisioner kubernetes.io/aws-ebs 来创建一个 Storage Class,通过 Storage Class 创建 PVC。Kubernetes 会自动为你创建相对应的 PV。接下来指定 PVC 为 volume 就可以在 pod 中使用了。


在本用例中,你不需要在使用使用之前创建 EBS,EBS Provisioner 会为你创建的。

第三方方式

上面列出的都是 Kubernetes 内置选项,如果你不太满意的话,其实还有一些使用 Flexvolume driver 格式的第三方 EBS 实现,它们可以帮助你和 Kubernetes 连接起来。


如果 Flexvolume 不适合你,还可以使用具备同样功能的 CSI drivers(为什么这么说?稍后会对此进行详细介绍)

VolumeClaimTemplate 方式

如果你在使用 StatefulSet,那么恭喜你!你现在有额外多了一种使用工作负载中 EBS 的方式——VolumeClaimTemple。


VolumeClaimTemple 是 StatefulSet 规范属性,它为 StatefulSet 所创建的 Pod 提供了创建匹配 PV 和 PVC 的方式。这些 PVC 将通过 Storage Class 创建,这样当 StatefulSet 扩展时就可以自动创建它们。当 StatefulSet 缩小时,多余的 PV/PVCs 会保留在系统中。因此,当 StatefulSet 再一次扩展时,它们会再次作用于 Kubernetes 创建的新 pods 中。稍后我们会详细讲 StatefulSet。


举个例子说明,假设你用 replica 3 创建了一个名为 www 的 StatefulSet,并用它创建了名为 data 的 VolumeClaimTemplate。Kubernetes 会创建 3 个 pods,分别起名 www-0、www-1、www-2。Kubernetes 还会创建 PVC,其中 www-data-0 用于 pod www-0,www-data-1 给 www-1,www-data-2 给 www-2。如果你把 StatefulSet 扩展到 5,Kubernetes 就会分别创建 www-3、www-data-3、www-4、www-data-4。如果接着将 StatefulSet 降为 1,www-1 到 www-4 全都会删除,而 www-data-1 到 www-data-4 会保留在系统中。因此当你决定再次扩展到 5 的时候,pod www-1 到 www-4 又回被创建出来,而 PVC www-data-1 仍然会服务于 Pod www-1,www-data-2 对应 www-2,以此类推。这是因为 StatefulSet 中 pod 的身份在是 stable 的。使用 StatefulSet 时,名称和关系都是可以预测的。


VolumeClaimTemple 对于像 EBS 和 Longhorn 这样的块存储解决方案非常重要。因为这些解决方案本质上是 ReadWriteOnce,你不能在 Pod 之间共享它们。如果你有不止一个运行了持久化数据的 pod,那么就无法顺利地进行部署。因此,VolumeClaimTemplate 的出现为块存储解决方案提供了一种水平扩展 Kubernetes 工作负载的方式。

如何在 Volume、Persistent Volume 和 Provisioner 之间做出选择

正如你所看到的,现在有了内置的 Volume 类型、PV 类型、Provisioner 类型、以及使用 Flexvolume 和/或 CSI 的外部插件。让人比较头大的是,它们之间提供的功能基本相同,不过也有略微的区别。


我认为,至少应该有一个准则来确定如何在它们之间选择。


但是我并没有找到。


所以我翻遍了代码和文档,画出了下面的比较表格,以及对我来说最有意义的准则,从 Volume、Persistent Volume 和 Provisioner 几个方面进行对比。



这里我只涉及到 Kubernetes 中 in-tree 所支持的,除此之外一些官方的 out-of-tree 的 Provisioners:


https://github.com/kubernetes-incubator/external-storage


可以看到,Volume、Persistent Volume 以及 Provisioner 在一些细微的地方还是不一样的。


  1. Volume 支持大部分的 volume 插件。

  2. A.它是连接 PVC 和 pod 的唯一方法

  3. B.它也是唯一一个支持 Config Map、Secret、Downward API 以及 Projected 的。这些所有都与 Kubernetes API 服务器密切相关。

  4. C.它还是唯一一个支持 EmptyDir 的,EmptyDir 可以自动给 pod 分配和清理临时 volume。(注:早在 2015 年,Clayton Coleman 就提出了一个关于支持 EmptyDir 的问题。这对于需要持久化储存但只有本地卷可用的工作负载,这非常有用。可是这一观点并没有得到太多的关注。没有 scheduler 的支持,这一目标在当时很难做到。而现在,在 2018 年,Kubernetes v1.11 版本的 Local Volume 已经加入 scheduler 和 PV 的节点亲和支持(node affinity support),但是仍然没有 EmptyDir PV。而且 Local Volume 特性并不是我所期望的那样,因为它并不具备在节点上使用新目录创建新卷的能力。因此,我编写了 Local Path Provisioner,它利用 scheduler 和 PV 节点亲和更改,为工作负载提供动态的 Host Path type PV。)

  5. PV 支持的插件是 Provisioner 支持的超集,因为 Provisioner 需要在工作负载使用它之前创建 PV。但是,还有一些 PV 支持而 Provisioner 不支持的插件,比如 Local Volume(正在进行修改中)。

  6. 还有两种类型 Volume 是不支持的。他们是两个最新的特性:CSI 和 Local Volume,现在还有一些正在进行的工作,会在之后把它们用于 Volume。

在 Volume、Persistent Volume 和 Provisioner 之间选择的准则

那么用户到底应该选择哪种方式呢?


在我看来,用户们应该坚持一个原则:


在条件允许的情况下,选择 Provisioner 而不是 Persistent Volume,接着再是 Volume。


详细来说:


  1. 对于 Config Map、Downward API、Secret 或者 Projected,请使用 Volume,因为 PV 不支持它们。

  2. 对于 EmptyDir,直接使用 Volume,或者使用 Host Path 来代替。

  3. 对于 Host Path,通常是直接使用 Volume,因为它绑定到一个特定的节点,并且节点之间它是同构的。

  4. a. 如果你想用异构的 Host Path Volume,它在 Kubernetes v1.11 版之后才能使用,因为之前缺少对 PV 的节点亲和知识,使用 v1.11+版本,你可以使用我的 Local Path Provisioner 创建带有节点亲和的 Host Path PV:

  5. https://github.com/rancher/local-path-provisioner

  6. 对于其他的情况,除非你需要和现有的卷挂钩(这种情况下你应该使用 PV),否则就使用 Provisioner 代替。有些 Provisioner 并不是内置的选项,但是你应该能在此链接(https://github.com/kubernetes-incubator/external-storage)或者供应商的官方仓库中找到它们。


这个准则背后的原理很简单。在 Kubernetes 内部进行操作时,对象(PV)比属性(Volume)更容易管理,而且和手动创建 PV 相比,自动创建 PV 容易得多(Provisioner)。


不过这里有一个例外:如果你喜欢在 Kubernetes 外面进行存储,那么最好使用 Volume,尽管使用这种方式需要用到另一组 API 进行创建/删除。此外,由于缺少 VolumeClaimTemplate,会失去使用 StatefulSet 自动伸缩的能力。我不认为这是多数 Kubernetes 用户会选择的方式。

为什么做同样的事会有这么多选项?

当我开始研究 Kubernetes 存储时,首先想到的就是这个问题。由于缺乏一致性和直观性,Kubernetes 存储看起来就像是事后才想到的。于是我试图研究这些设计决策背后的历史缘由,可是在 2016 之前都毫无收获。


最后,我倾向于相信这些是由于一些早期的设计造成的,这可能是为获取供应商支持的迫切需求,导致安排给 Volume 比原本更多的责任。在我看来,所有复制了 PV 的内置 volume 插件都不应该存在。


在研究历史的过程中,我发现在 2016 初发布的 Kubernetes v1.2 中,dynamic provisioning 就已经成为了 alpha 特性。它需要两个发布版周期变成 beta,在两个周期实现稳定,这都是非常合理的。


SIG Storage(它推动了 Kubernetes 存储开发)还进行了大量的工作, 使用 Provisioner 和 CSI 将 Volume 插件从 tree 中移出来。 我认为这是朝着更加一致、更加精简的系统迈出了一大步。


可另一方面,我也不认为这一大堆 Volume 类型会消失。这像是和硅谷非官方的格言唱反调:快速行动,打破常规。有时候,快速迭代的项目所遗留下来的设计,修改它们实在是太难了。我们只能和它们共处,在它们身边小心工作,不要用错误的方式调用它们。

下一步

本系列的下一节中,我们将讨论扩展 Kubernetes 存储系统的机制,即 Flexvolume 和 CSI。一个小小的提示:你可能注意到了,我并不是 Flexvolume 的粉丝,而且这不是存储子系统的问题。


2020-04-22 18:321248

评论

发布
暂无评论
发现更多内容

Linux Squashfs只读文件系统介绍

不在线第一只蜗牛

数据库 Linux

Cyble被Frost & Sullivan评为全球网络威胁情报市场的创新领导者

财见

InPlant SCADA笔记 事件配置

万里无云万里天

工厂运维 InPlant SCADA

InPlant SCADA笔记 数据库中本地节点创建modbus tcp驱动

万里无云万里天

Modbus Tcp 工厂运维 InPlant SCADA

InPlant SCADA笔记 数据库中添加位号,读取modbustcp设备的值并显示在流程图

万里无云万里天

Modbus Tcp 工厂运维 InPlant SCADA

Apache IoTDB 论文入选数据库国际顶会 ICDE 2024

Apache IoTDB

需求管理:2024年10大最佳工具盘点

爱吃小舅的鱼

需求管理 需求管理工具

InPlant SCADA笔记 配方功能

万里无云万里天

工厂运维 InPlant SCADA

InPlant SCADA笔记 数据库中使用modbustcp在线调试来读取modsim32中的值

万里无云万里天

Modbus Tcp 工厂运维 InPlant SCADA modsim32

IBM 发布《2024年数据泄露成本报告》:企业数据泄露成本创新高,AI和自动化成为"数据保卫战"突破口

财见

InPlant SCADA笔记 数据库管理中位号的批量导出

万里无云万里天

工厂运维 InPlant SCADA

大模型数据分析平台 LangSmith 介绍

心有千千结

LLM #LangChain

常见数据结构与代码实现方案

测吧(北京)科技有限公司

测试

利用爬虫工具爬取网站结构能力

测吧(北京)科技有限公司

测试

管理项目需求:7款工具助力高效运营

爱吃小舅的鱼

需求管理 软件需求管理 需求管理工具

创新管理解决方案:超越Redmine的工具

爱吃小舅的鱼

项目管理

使用 OWASP ZAP 进行安全测试

测吧(北京)科技有限公司

测试

CorelDraw绘制线条工具有哪些 CorelDraw绘制圆角矩形的方法

阿拉灯神丁

学习资料 CorelDraw 矢量图形设计软件 cdr2024安装教程 好用的平面设计软件

【Yarn】Timeline Server UI应用记录名称为null

扬_帆_起_航

Cloudera调查:近90%的企业使用人工智能,但过时的基础设施和员工技能差距阻碍了其充分发挥效益

财见

在已有的流程平台中调用 Jenkins 并获取数据

测吧(北京)科技有限公司

测试

Apache RocketMQ 中文社区全新升级!

Apache RocketMQ

Apache RocketMQ 基础软件 中间件 消息队列

霍尼韦尔:AI在工业领域的应用方兴未艾 不断发现新的应用场景

财见

InPlant SCADA笔记 使用位号分组来管理位号

万里无云万里天

工厂运维 InPlant SCADA

InPlant SCADA笔记 数据标签控件

万里无云万里天

工厂运维 InPlant SCADA

使用 Burp Suite 进行渗透测试

测吧(北京)科技有限公司

测试

Gather 全球化进程迅速 多重利好推动未来发展

股市老人

顶级待办事项工具:哪个适合你的桌面?

爱吃小舅的鱼

待办事项 待办事项管理

InPlant SCADA笔记 历史趋势

万里无云万里天

工厂运维 InPlant SCADA

7个使用大语言模型的最佳情绪分析 API

幂简集成

情绪 API

最佳待办事项App对比:哪款最适合你?

爱吃小舅的鱼

待办事项

深入浅出聊聊Kubernetes存储(二):搞定持久化储存_文化 & 方法_Rancher_InfoQ精选文章