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

栏目: 编程工具 · 发布时间: 7年前

内容简介:回 顾在本系列文章的上一篇中,我们讲到了PV,PVC,Storage Class以及Provisioner简单回顾一下:

回 顾

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

简单回顾一下:

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

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

PV和PVC总是一一对应的。

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

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中的容器访问。这些目录是如何产生的、支持它的介质、以及它的内容都是由所使用的特定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存储(二):搞定持久化存储

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

https://github.com/kubernetes- ... orage

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

  1. Volume支持大部分的volume插件。
    A.它是连接PVC和pod的唯一方法
    B.它也是唯一一个支持Config Map、Secret、Downward API以及Projected的。这些所有都与Kubernetes API服务器密切相关。
    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。)
  2. PV支持的插件是Provisioner支持的超集,因为Provisioner需要在工作负载使用它之前创建PV。但是,还有一些PV支持而Provisioner不支持的插件,比如Local Volume(正在进行修改中)。
  3. 还有两种类型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,因为它绑定到一个特定的节点,并且节点之间它是同构的。

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

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

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

这个准则背后的原理很简单。在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的粉丝,而且这不是存储子系统的问题。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Algorithms to Live By

Algorithms to Live By

Brian Christian、Tom Griffiths / Henry Holt and Co. / 2016-4-19 / USD 30.00

A fascinating exploration of how insights from computer algorithms can be applied to our everyday lives, helping to solve common decision-making problems and illuminate the workings of the human mind ......一起来看看 《Algorithms to Live By》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具