存储
在k8s中有Volume、PV、PVC、StorageClass等众多与存储有关的概念,那么这些都是用来做什么的呢?为什么需要这么多的概念呢?本文将一一介绍它们。
Volume
Pod里面的数据是不持久的,当Pod被删掉后,Pod里面的数据也就不复存在,所以我们使用Volume来持久化Pod里面的数据。
常用的Volume的类型有HostPath
、EmptyDir
、NFS
、RBD
等等。以RBD为例,我们可以先在Ceph中创建一个RBD块:
然后在Pod中就可以使用这个RBD块,这样,即使Pod被删或者Pod所在的主机挂掉,保存在RBD中的数据也不会丢,可以用它立马起一个新的容器。
PV与PVC
在上面《Volume》中,我们可以先在ceph集群中创建一个RBD块,然后在Pod直接使用这个块。但是直接使用Volume会有一些问题,我们考虑如下一个场景:
当一个k8s集群有多个租户,每个租户以命名空间相互隔离,每个租户想创建一个Mysql服务,并且想让数据持久化;如果使用Volume,那么此时k8s管理员先要在Ceph中创建若干RBD块,然后再告诉每个租户,你应该使用哪个Volume。
这种方式第一个问题就是,租户都知道了ceph集群的连接信息,要是删除了其他租户的RBD块怎么办?甚至删了ceph的所有数据怎么办?
假设租户都很好,不会做坏事,那按照这种方式,如果有一百个或一千个租户,管理员要创建一千个volume,然后分配下去,管理员还得记住哪一个volume分配给了哪一个租户,显然,这一种方法落地太难。
所以,k8s提出了PV与PVC的概念。对于上面的场景,k8s集群管理员可以先批量在ceph集群中建好RBD块(假设RBD块命名为image-1 to image-N
),然后在k8s集群中批量创建PV,每个PV对应Ceph中的一个RBD块,如下:
由于PV是集群级别的资源(无命名空间),所以k8s集群管理员可以配置权限让租户无法看到这些PV,那么租户也就无法知道Ceph集群的信息。
如果租户A要持久化数据,首先需要创建如下一个PVC:
该PVC“说”自已需要一个存储为1Gi
的PV,当创建好该PVC后,kube-controller-manager就会为该PVC寻找一个满足它的PV进行绑定(所谓绑定就是把PVC的spec.volumeName
设置为PV的名字,把PV的spec.claimRef
设置为PVC的相关内容)。当一个PV被某个PVC绑定后,便不能再被其他的PVC绑定。
然后,租户就可以在Pod中使用这个PVC:
通过PV与PVC,满足了租户持久化数据的需求,也防止了租户看到后端存储的敏感信息。
StorageClass与PV的动态供给
在上面的《PV与PVC》中,我们讲到kubernetes的管理员需要提前批量创建PV,使用者在使用时就只需要创建PVC,然后由kubernetes去匹配一个PV。这个操作还是有些复杂,kubernetes提供了一种PV的动态供给机制:StorageClass
StorageClass的核心功能就是:当使用者创建一个PVC时,kubernetes自动为该PVC创建一个PV并进行绑定。
接下来,我们给一个具体的例子,来介绍StorageClass,这里以RBD为例。(实践的全过程见下一节《RBD实践》)
首先,准备好一个Ceph集群然后在kubernetes集群中创建provisioner
为rbd
的StorageClass:
然后我们创建一个storageClassName
为rbd
的PVC
创建好该PVC之后,kubernetes便会自动创建一个PV与该PVC进行绑定
本文小结
至此,我们已经介绍完了为什么k8s中要引入Volume、PV与PVC、StorageClass这么多的概念。关于它们更为详细的介绍,请继续阅读后面的文章。
Last updated
Was this helpful?