本文发布已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不正确。
本地存储:存储容量跟踪、分布式配置和通用临时卷进入 Beta 版
Kubernetes 中的“通用临时卷”和“存储容量跟踪”功能在 Kubernetes 1.21 中被提升为 Beta 版。结合 CSI 外部配置器中的分布式配置支持,管理节点本地存储的容器存储接口 (CSI) 驱动程序的开发和部署变得更加容易。
这篇博客文章解释了这些驱动程序之前是如何工作的,以及如何使用这些功能来简化驱动程序。
我们正在解决的问题
有一些用于本地存储的驱动程序,例如用于传统磁盘的 TopoLVM 和用于持久内存的 PMEM-CSI。它们工作正常,并且也适用于旧版本的 Kubernetes,但是要做到这一点并不容易。
需要的中心组件
第一个问题是卷的配置:它由 Kubernetes 控制平面处理。某些组件必须对 PersistentVolumeClaims (PVC) 做出反应并创建卷。通常,这由 CSI 外部配置器的中央部署和 CSI 驱动程序组件处理,然后该组件连接到存储底板。但是对于本地存储,没有这样的底板。
TopoLVM 通过使其不同的组件通过 Kubernetes API 服务器进行通信来解决此问题,方法是创建并响应自定义资源。因此,尽管 TopoLVM 基于 CSI,这是一个独立于特定容器编排器的标准,但 TopoLVM 仅在 Kubernetes 上工作。
PMEM-CSI 通过 gRPC 调用创建了自己的存储底板。确保该通信的安全取决于 TLS 证书,这使得驱动程序部署更加复杂。
通知 Pod 调度程序有关容量
下一个问题是调度。当卷独立于 Pod 创建(“立即绑定”)时,CSI 驱动程序必须选择一个节点,而无需了解任何将要使用它的 Pod。然后,拓扑信息会强制这些 Pod 在创建卷的节点上运行。如果其他资源(如 RAM 或 CPU)在那里耗尽,则 Pod 无法启动。可以通过在 StorageClass 中配置卷创建旨在等待第一个使用卷的 Pod (volumeBinding: WaitForFirstConsumer
) 来避免这种情况。在这种模式下,Kubernetes 调度程序会根据其他约束临时选择一个节点,然后要求外部配置器创建一个卷,使其可以在那里使用。如果本地存储已耗尽,则配置器可以要求进行另一轮调度。但是,如果没有关于可用容量的信息,调度程序可能总是选择同一个不合适的节点。
TopoLVM 和 PMEM-CSI 都使用调度程序扩展器解决了这个问题。这有效,但是在部署驱动程序时很难配置,因为 kube-scheduler 和驱动程序之间的通信非常依赖于集群的设置方式。
重新调度
本地存储的常见用例是临时空间。更适合该用例的是为 Pod 创建并与其一起销毁的临时卷,而不是持久卷。支持 CSI 驱动程序临时卷的初始 API(因此称为 “CSI 临时卷”)是为轻量级卷设计的,其中卷创建不太可能失败。卷创建发生在 Pod 被永久调度到节点上之后,这与在将 Pod 调度到节点上之前尝试创建卷的传统配置形成对比。必须修改 CSI 驱动程序以支持“CSI 临时卷”,这已经为 TopoLVM 和 PMEM-CSI 完成。但是,由于 Kubernetes 中该功能的设计,如果节点上的存储容量耗尽,Pod 可能会永久卡住。调度程序扩展器尝试避免这种情况,但不能 100% 可靠。
Kubernetes 1.21 中的增强功能
分布式配置
从 Kubernetes 1.20 发布的 external-provisioner v2.1.0 开始,配置可以由与每个节点上的 CSI 驱动程序一起部署的外部配置器实例处理,然后它们协同配置卷(“分布式配置”)。不再需要中央组件,因此至少在配置方面不再需要节点之间的通信。
存储容量跟踪
调度程序扩展器仍然需要某种方式来了解每个节点上的容量。当 PMEM-CSI 在 v0.9.0 中切换到分布式配置时,这是通过查询本地驱动程序容器公开的指标数据来完成的。但是,对于用户而言,最好完全消除对调度程序扩展器的需求,因为驱动程序部署变得更加简单。存储容量跟踪,在 1.19 中引入并在 Kubernetes 1.21 中提升为 Beta 版,实现了这一点。它的工作原理是在 CSIStorageCapacity
对象中发布有关容量的信息。然后,调度程序本身会使用该信息来过滤掉不合适的节点。由于信息可能不是最新的,Pod 仍然可能会被分配到存储不足的节点,这只是不太可能,一旦信息刷新,Pod 的下一次调度尝试应该会更好。
通用临时卷
因此,CSI 驱动程序仍然需要能够从错误的调度决策中恢复,事实证明,对于“CSI 临时卷”来说,这是不可能实现的。“通用临时卷”,这是在 1.21 中被提升为 Beta 版的另一个功能,没有这个限制。此功能添加了一个控制器,它将创建和管理具有 Pod 生命周期的 PVC,因此正常的恢复机制也适用于它们。现有的存储驱动程序将能够处理这些 PVC,而无需任何新的逻辑来处理此新场景。
已知限制
通用临时卷和存储容量跟踪都会增加 API 服务器的负载。这是否是一个问题很大程度上取决于工作负载的类型,特别是多少个 Pod 有卷以及需要创建和销毁的频率。
没有尝试建模调度决策如何影响存储容量。这是因为效果会因存储系统如何处理存储而有很大差异。其效果是,即使只有足够一个 Pod 的容量,具有未绑定卷的多个 Pod 也可能被分配到同一个节点。调度应该会恢复,但如果调度程序对存储有更多了解,效率会更高。
由于存储容量由正在运行的 CSI 驱动程序发布,并且集群自动伸缩器需要有关尚未创建的节点的信息,因此它目前不会为需要卷的 Pod 扩展集群。有一个关于如何提供该信息的想法,但是该领域还需要更多的工作。
目前不支持分布式快照和调整大小。应该可以调整各自的 Sidecar,并且已经为 external-snapshotter 和 external-resizer 打开了跟踪问题,它们只需要一些志愿者。
对于具有多个卷的 Pod,从错误的调度决策中恢复可能会失败,尤其是当这些卷是节点本地的卷时:如果可以创建一个卷,然后存储不足以容纳另一个卷,则第一个卷将继续存在,并强制调度程序将 Pod 放置在该卷的节点上。有一个关于如何处理此问题的想法,回滚卷的配置,但这还处于头脑风暴的早期阶段,甚至还没有合并的 KEP。目前,最好避免创建具有多个持久卷的 Pod。
启用新功能和后续步骤
随着该功能在 1.21 版本中进入 Beta 版,无需执行其他操作即可启用它。通用临时卷也无需更改 CSI 驱动程序即可工作。有关更多信息,请参阅文档和关于它的上一篇博客文章。API 在 Alpha 版和 Beta 版之间根本没有改变。
对于其他两个功能,外部配置器文档解释了 CSI 驱动程序开发人员必须如何更改其驱动程序的部署方式以支持 存储容量跟踪和分布式配置。这两个功能是独立的,因此仅启用其中一个也是可以的。
如果您正在使用这些新功能,SIG Storage 希望收到您的反馈。可以通过 电子邮件、Slack(频道 #sig-storage
)和 定期 SIG 会议联系我们。您的工作负载描述对于验证设计决策、设置性能测试并最终将这些功能提升到 GA 非常有用。
鸣谢
非常感谢社区成员为这些功能做出了贡献或提供了反馈,包括 SIG Scheduling、SIG Auth 以及当然还有 SIG Storage 的成员!