4.2 Kubernetes存储基元
Kubernetes提供了多个开箱即用的基元来支持工作负载存储。这些基元提供了我们将利用的结构块,以提供复杂的存储解决方案。在本节中,我们将以向容器分配快速预配置的存储为例,介绍PersistentVolume、PersistentVolumeClaim和StorageClass。
4.2.1 持久卷和声明
卷和声明(claim)是Kubernetes中存储的基础。这些都是通过PersistentVolume(https://oreil.ly/7_OAz)和PersistentVolumeClaim(https://oreil.ly/PKtAr)API暴露出来的。PersistentVolume资源代表Kubernetes已知的存储卷。让我们假设一个管理员已经准备好了一个节点,以提供主机上30Gi的快速存储。我们还假设管理员已经把这个存储放在了/mnt/fast-disk/pod-0。为了在Kubernetes中表示这个卷,管理员可以创建一个PersistentVolume对象:
此卷中的可用存储量。用来确定声明是否可以绑定到这个卷。
指定此卷是一个块设备(https://oreil.ly/mrHwE)还是文件系统。
指定此卷的访问模式。包括ReadWriteOnce、ReadMany和ReadWriteMany。
将此卷与存储类关联。用于对这个卷的最终声明进行配对。
指明此卷应与哪个节点相关联。
正如你所看到的,PersistentVolume包含了围绕卷的实现的细节。为了提供更多的抽象层,引入了一个PersistentVolumeClaim,它根据请求绑定到一个适当的卷。最常见的是,这将由应用团队定义,添加到命名空间,并从Pod中引用。
检查是否有一个local-storage类的卷,且其访问模式为ReadWriteOnce。
绑定到一个存储量大于等于30Gi的卷。
宣布这个Pod是PersistentVolumeClaim的消费者。
基于PersistentVolume的nodeAffinity设置,Pod将被自动安排在有此卷的主机上。开发者不需要进行额外的配置。
这个过程展示了一个手动的流程,管理员可以将这个存储提供给开发者。我们把这称为静态配置。通过适当的自动化,这可能是将主机上的快速磁盘暴露给Pod的一种可行的方式。例如,Local Persistence Volume Static Provisioner(https://oreil.ly/YiQ0G)可以被部署到集群中,以检测预先分配的存储,并自动将其暴露为PersistentVolume。它还提供了一些生命周期管理功能,如在销毁PersistentVolumeClaim时删除数据。
虽然这里有多种方法可以实现本地存储,但其中有些方法可能会导致一些错误的实践,例如允许开发人员使用hostPath(https://oreil.ly/PAU8Y)而不是预先提供一个本地存储。hostPath使你能够在主机上指定一个路径来绑定,而不必使用PersistentVolume和PersistentVolumeClaim。但是,这可能是一个巨大的安全风险,因为它使开发人员能够绑定到主机上的目录,这可能对主机和其他Pod产生负面影响。如果你希望为开发人员提供一个可以承受Pod重新启动但不能承受Pod被删除或移动到另一个节点的临时存储,那么可以使用emptyDir(https://oreil.ly/mPwBg)。它将在Kube管理的文件系统中分配存储,这对Pod来说是透明的。
4.2.2 存储类
在许多环境中,期望节点提前准备好磁盘和卷是不现实的。通常这些情况需要动态配置,其中卷可以根据我们的要求来提供。为了使用这种模式,我们可以向开发人员提供存储的类别。这些是使用StorageClass(https://oreil.ly/MoG_T)API定义的。假设你的集群在AWS中运行,你想为Pod动态提供EBS卷,可以添加以下StorageClass:
可以通过声明引用的StorageClass的名称。
将此StorageClass设置为默认值。如果申领没有指定类别,将使用这个类别。
使用aws-ebs供应器来创建基于声明的卷。
服务商特定的配置,用于描述如何配置卷。
你可以通过提供多个StorageClass来为开发人员提供多种存储选项。这包括在一个集群中支持一个以上的服务商。例如,与VMware vSAN一起运行Ceph。另外,你还可以通过同一个服务商提供不同级别的存储,例如在便宜的存储和昂贵存储内进行选择。然而,Kubernetes缺乏细粒度的控制来限制开发人员可以请求的存储类。该控制能力可以实现为验证许可控制,这将在第8章中讨论。
Kubernetes提供了各种各样的服务商扩展,包括AWS EBS、Glusterfs、GCE PD、Ceph RBD等。以前,这些存储服务商需要在Kubernetes核心项目中实现它们的逻辑。然后,代码会在相关的Kubernetes控制平面组件中被使用。
这种模式有几个弊端。一个弊端是存储服务商不能被管理。服务商的所有变化都需要与Kubernetes的版本相联系。另外,每个Kubernetes部署都有不必要的代码。例如,运行AWS的集群仍然有与GCE PD交互的提供商代码。但我们很快就发现,将这些服务商的集成插件化,并废除原来的代码是很有价值的。FlexVolume驱动程序(https:// oreil.ly/YnnCq)是一个插件化实施规范,最初旨在解决这个问题。然而,FlexVolume已经进入维护模式,它将用于支持我们要讨论的下一个主题:容器存储接口。