一、Docker中的Volume和Kubernetes中的Volume
Docker中的Volume
在Docker中创建持久化存储非常简单。早期版本中,用户可以使用-v来创建一个新的未定义大小的匿名空卷或者在主机上的目录中创建绑定挂载。那个时候,虽然可以很容易地通过挂载那些已经被存储供应商挂载在主机上的目录,但没有第三方接口帮助你直接挂载到Docker上。2015年8月,Docker发布了v1.8版本,正式引入了卷插件,允许第三方连接它们的存储解决方案。
Kubernetes中的Volume
Kubernetes中的卷有明确的寿命——与封装它的Pod相同。所以,卷的生命比Pod中的所有容器都长,当这个容器重启时数据仍然得以保存。当然,当Pod不再存在时,卷也将不复存在。
二、持久卷(Persistent Volume)和持久卷声明(Persistent Volume Claim)
Persistent Volume(PV)
是集群中由管理员配置的一块存储。它是集群中的资源,就和节点是集群资源一样。PV是卷插件比如Volumes,但是它的生命周期独立于使用PV的任何pod个体。该API对象捕获实现存储的详细信息,包括NFS、iSCSI或着是云服务商特定的存储系统。
Persistent Volume Claim(PVC)
是用户关于存储的请求。它类似于一个pod,pod消耗节点资源,而PVC消耗PV资源。Pods可以请求特定级别的资源(CPU和内存),而Claim可以请求特定的大小和访问模式(例如,可以一次读/写或者多次只读)。
Kubernetes将基本存储单元分为两个概念。PV是一个存储器,应该由管理员预先分配,而PVC是用户对存储的请求。
也就是说,Kubernetes希望管理员来实现分配各种大小的PV。当用户创建PVC来请求存储时,Kubernetes将尝试用该PVC和预先分配的PV匹配。如果可以找到匹配项,就将PVC绑定到PV,用户就可以开始使用这片预分配的存储区。
PV和PVC总是一一对应的。
三、Storage Class和Provisioner
在2017年3月,随着v1.6版本的发布,Kubernetes引入了动态纳管(dynamic provisioning)、Storage Class和Provisioner的概念。
StorageClass为
管理员提供了描述存储 "class(类)" 的方法。Storage Class可以有不同的容量限制、不同的IOPS或其他Provisioner支持的参数。特定于存储供应商的Provisioner将与Storage Class一起使用,根据Storage Class对象中设置的参数自动分配PV。此外,Provisioner现在能够强制执行用户的报价(quotes)和权限要求。在这种设计中,管理员已经从预测和分配PV的繁琐中摆脱出来,这样的方式更有意义。
Provisioner
是存储分配器,用来决定使用哪个卷插件分配 PV。
四、Volume对比Persistent Volume
为了把Volume和持久卷(Persistent Volume)区分开,大家有时会称它为In-line Volume或者Ephemeral Volume。
Volume一个重要属性是,它与所属的pod具有相同的生命周期。如果pod消失了,它也会消失。这与Persistent Volume不同,因为Persistent Volume将继续存在于系统中,直到用户删除它。
因此,这更可以把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。
五、如何在Volume、Persistent Volume和Provisioner之间做出选择
可以看到,Volume、Persistent Volume以及Provisioner在一些细微的地方还是不一样的。
1、Volume支持大部分的volume插件。
① 它是连接PVC和pod的唯一方法。
② 它也是唯一一个支持Config Map、Secret、Downward API以及Projected的。这些所有都与Kubernetes API服务器密切相关。
③ 它还是唯一一个支持EmptyDir的,EmptyDir可以自动给pod分配和清理临时volume。
2、PV支持的插件是Provisioner支持的超集,因为Provisioner需要在工作负载使用它之前创建PV。
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,因为它绑定到一个特定的节点,并且节点之间它是同构的。
4、对于其他的情况,除非你需要和现有的卷挂钩(这种情况下你应该使用PV),否则就使用Provisioner代替。
这个准则背后的原理很简单。在Kubernetes内部进行操作时,对象(PV)比属性(Volume)更容易管理,而且和手动创建PV相比,自动创建PV容易得多(Provisioner)。