本文发布已超过一年。较旧的文章可能包含过时内容。请检查页面信息自发布以来是否已失效。

介绍 Kubernetes 对 Windows CSI 的 Alpha 支持

CSI Proxy 的 Windows alpha 版本随 Kubernetes 1.18 发布。CSI Proxy 通过允许 Windows 中的容器执行特权存储操作,从而为 Windows 上的 CSI Driver 提供支持。

背景

Kubernetes 的容器存储接口 (CSI) 在 Kubernetes 1.13 版本中达到 GA(普遍可用)。CSI 已成为在 Kubernetes 等容器编排系统 (CO) 上向容器化工作负载暴露块存储和文件存储的标准。它使得第三方存储提供商无需更改 Kubernetes 核心代码即可编写和部署插件。所有新的存储功能都将使用 CSI,因此让 CSI 驱动程序在 Windows 上工作非常重要。

Kubernetes 中的 CSI 驱动程序有两个主要组件:控制器插件 (controller plugin) 和节点插件 (node plugin)。控制器插件通常不需要直接访问主机,可以通过 Kubernetes API 和外部控制平面服务(例如云存储服务)执行所有操作。然而,节点插件需要直接访问主机,以便将块设备和/或文件系统提供给 Kubernetes 的 kubelet。这在以前对于 Windows 上的容器来说是不可能的。随着 CSIProxy 的发布,CSI 驱动程序现在可以在节点上执行存储操作。这反过来使得容器化的 CSI 驱动程序能够在 Windows 上运行。

CSI 对 Windows 集群的支持

CSI 驱动程序(例如 AzureDisk, GCE PD 等)建议部署为容器。CSI 驱动程序的节点插件通常作为 DaemonSet 在集群中的每个工作节点上运行。节点插件容器需要以提升的权限运行才能执行存储相关操作。然而,Windows 当前不支持特权容器。为了解决这个问题,CSIProxy 的作用是让节点插件现在可以作为非特权 Pod 部署,然后使用代理在节点上执行特权存储操作。

节点插件与 CSIProxy 的交互

CSI Proxy 的设计记录在这份 KEP 中。下图描述了 CSI 节点插件与 CSI Proxy 的交互。

CSI Proxy 作为进程直接在每个 Windows 节点的主机上运行,与 kubelet 非常相似。kubelet 中的 CSI 代码与 node driver registrar 组件和 CSI 节点插件进行交互。node driver registrar 是一个由社区维护的 CSI 项目,用于处理特定厂商节点插件的注册。kubelet 在节点插件上发起 CSI gRPC 调用,例如图中所示的 NodeStageVolume/NodePublishVolume。节点插件通过 CSIProxy 进程执行本地主机操作系统存储相关操作,例如创建/枚举存储卷、挂载/卸载等。

CSI Proxy 架构和实现

在 alpha 版本中,CSIProxy 支持以下 API 组

  1. 文件系统 (Filesystem)
  2. 磁盘 (Disk)
  3. 存储卷 (Volume)
  4. SMB

CSI Proxy 通过 Windows 命名管道暴露每个 API 组。通信通过这些管道上的 gRPC 进行。CSI Proxy 项目提供的客户端库使用这些管道与 CSI Proxy API 进行交互。例如,文件系统 API 通过类似 \.\pipe\csi-proxy-filesystem-v1alpha1 的管道暴露,存储卷 API 通过 \.\pipe\csi-proxy-volume-v1alpha1 暴露,依此类推。

从每个 API 组服务,调用被路由到主机 API 层。主机 API 通过 Powershell 或 Go 标准库调用主机 Windows 操作系统。例如,当调用文件系统 API Rmdir 时,API 组服务将解码 grpc 结构 RmdirRequest 并找到要删除的目录,然后调用主机 API 层。这将导致调用 Go 标准库函数 os.Remove 来执行删除操作。

控制流程细节

下图以 CSI 调用 NodeStageVolume 为例,解释了 kubelet、CSI 插件和 CSI Proxy 在供给新存储卷时的交互。节点插件收到 CSI RPC 调用后,会相应地调用 CSIProxy。作为 NodeStageVolume 调用的结果,首先使用 Disk API 调用之一(AzureDisk 驱动程序中的 ListDiskLocations 或 GCE PD 驱动程序中的 GetDiskNumberByName)识别所需的磁盘。如果磁盘未分区,则调用 PartitionDisk (Disk API 组)。随后,调用 Volume API 函数,例如 ListVolumesOnDisk、FormatVolume 和 MountVolume,以执行其余所需操作。在 NodeUnstageVolume、NodePublishVolume、NodeUnpublishedVolume 等情况下也执行类似操作。

当前支持

CSI Proxy 目前已发布 alpha 版本。您可以在 CSIProxy GitHub 仓库中找到更多详细信息。目前有两个云提供商为 Windows 上的 CSI 驱动程序提供 alpha 支持:Azure 和 GCE。

未来规划

Beta 版本的一个主要重点将是基于 Windows 的构建和 CI/CD 设置,以提高代码库的稳定性和质量。另一个方面是直接使用基于 Go 的调用而不是 Powershell 命令,以提高性能。增强可调试性和添加更多测试是团队将关注的其他领域。

如何参与?

与所有 Kubernetes 项目一样,CSI Proxy 项目也是由许多背景各异的贡献者共同努力的成果。如果您有兴趣参与 CSI Proxy 或 Kubernetes 存储系统的任何部分的设计和开发,可以加入 Kubernetes Storage 特别兴趣小组 (SIG)。我们正在快速发展,并且随时欢迎新的贡献者。

对于那些对更多细节感兴趣的人,CSIProxy GitHub 仓库是一个很好的起点。此外,kubernetes slack 上的 #csi-windows 频道可用于讨论 Windows 上的 CSI 相关问题。

致谢

我们非常感谢 Michelle Au 在整个 alpha 发布之旅中提供的指导。我们感谢 Jean Rougé 在初期 CSI Proxy 工作中的贡献。我们感谢 Saad Ali 对本项目的所有指导以及对这篇博客草稿的评审和反馈。我们感谢 Patrick Lang 和 Mark Rossetti 在 Windows 相关问题和细节方面提供的帮助。特别感谢 Andy Zhang 对 Azuredisk 和 Azurefile 工作的评审和指导。非常感谢 Paul Burt 和 Karen Chu 对这篇博客文章的评审和改进建议。

最后但同样重要的是,我们要感谢在项目各个阶段都做出贡献的更广泛的 Kubernetes 社区。