我们在 Kubernetes 中为 Yandex.Cloud 开发 CSI 驱动程序的经验

我们在 Kubernetes 中为 Yandex.Cloud 开发 CSI 驱动程序的经验

我们很高兴地宣布,Flant 正在扩大其对 Kubernetes 开源工具的贡献,发布了 CSI 驱动程序的 alpha 版本 Yandex.Cloud(容器存储接口)。

但在继续讨论实现细节之前,让我们回答一下为什么在 Yandex 已经有服务的情况下还需要这样做的问题 Kubernetes 托管服务.

介绍

这是为什么?

在我们公司内部,从一开始在生产中使用 Kubernetes 开始(即现在已经好几年了),我们一直在开发自己的工具(deckhouse),顺便说一句,我们还计划很快将其作为开源项目提供。 在它的帮助下,我们统一配置和配置我们所有的集群,目前已经有 100 多个集群,分布在各种硬件配置和所有可用的云服务中。

使用 Deckhouse 的集群拥有操作所需的所有组件:平衡器、使用方便的图表、指标和警报进行监控、通过外部提供商进行用户身份验证以访问所有仪表板等等。 在托管解决方案中安装这样的“启动”集群是没有意义的,因为这通常要么是不可能的,要么会导致需要禁用一半的组件。

NB: 这是我们的经验,而且很具体。 我们绝不建议每个人都应该自行部署 Kubernetes 集群,而不是使用现成的解决方案。 顺便说一句,我们没有从 Yandex 操作 Kubernetes 的实际经验,因此在本文中我们不会对此服务进行任何评估。

它是什么以及为谁而存在?

因此,我们已经讨论了 Kubernetes 中的现代存储方法: CSI 是如何运作的? и 社区是如何诞生的 到这种方法。

目前,许多大型云服务提供商都开发了将其云盘用作 Kubernetes 中的持久卷的驱动。 如果供应商没有这样的驱动程序,但所有必要的功能都是通过 API 提供的,那么没有什么可以阻止您自己实现驱动程序。 Yandex.Cloud 就是这样。

我们以 DigitalOcean 云的 CSI 驱动程序 和一些想法 GCP 驱动程序,因为与这些云(Google 和 Yandex)的 API 的交互有许多相似之处。 特别是,API 和 GCP而你 Yandex的 返回一个对象 Operation 跟踪长时间运行的操作的状态(例如,创建新磁盘)。 要与 Yandex.Cloud API 交互,请使用 Yandex.Cloud Go SDK.

所做工作的结果 发布在 GitHub 上 对于那些出于某种原因在 Yandex.Cloud 虚拟机(但不是现成的托管集群)上使用自己的 Kubernetes 安装并希望通过 CSI 使用(订购)磁盘的人来说可能很有用。

履行

主要特点

目前该驱动支持以下功能:

  • 根据集群中节点的拓扑对集群所有Zone中的磁盘进行排序;
  • 取出先前订购的光盘;
  • 离线调整磁盘大小 (Yandex.Cloud 不支持 增加安装到虚拟机的磁盘)。 有关如何修改驱动程序以尽可能轻松地调整大小的信息,请参阅下文。

未来,我们计划实现对创建和删除磁盘快照的支持。

主要困难及克服方法

Yandex.Cloud API 缺乏实时增加磁盘的能力是一个限制,使 PV(持久卷)的调整大小操作变得复杂:在这种情况下,需要停止使用该磁盘的应用程序 pod,这可能会导致应用程序停机。

根据 CSI规范,如果 CSI 控制器报告它只能“离线”调整磁盘大小(VolumeExpansion.OFFLINE),那么增加磁盘的过程应该是这样的:

如果插件只有 VolumeExpansion.OFFLINE 扩展能力和卷当前已在节点上发布或可用 ControllerExpandVolume 必须仅在以下任一之后调用:

  • 该插件有控制器 PUBLISH_UNPUBLISH_VOLUME 能力和 ControllerUnpublishVolume 已经调用成功。

要不然

  • 该插件没有控制器 PUBLISH_UNPUBLISH_VOLUME 能力,插件有节点 STAGE_UNSTAGE_VOLUME 能力,以及 NodeUnstageVolume 已成功完成。

要不然

  • 该插件没有控制器 PUBLISH_UNPUBLISH_VOLUME 能力,也不是节点 STAGE_UNSTAGE_VOLUME 能力,以及 NodeUnpublishVolume 已成功完成。

这本质上意味着您需要在扩展磁盘之前将磁盘与虚拟机分离。

然而,不幸的是 履行 通过 sidecar 的 CSI 规范不满足以下要求:

  • 在边车容器中 csi-attacher,这应该负责安装之间存在所需的间隙,但在离线调整大小中根本没有实现此功能。 对此发起了讨论 这里.
  • 在这种情况下,边车容器到底是什么? CSI 插件本身不与 Kubernetes API 交互,而仅响应 sidecar 容器发送给它的 gRPC 调用。 最新的 正在发展中 由 Kubernetes 社区提供。

在我们的例子(CSI插件)中,增加磁盘的操作如下所示:

  1. 我们收到 gRPC 调用 ControllerExpandVolume;
  2. 我们尝试在 API 中增加磁盘,但收到一条错误,提示由于磁盘已挂载而无法执行该操作;
  3. 我们将磁盘标识符存储在map中,其中包含需要执行增加操作的磁盘。 下面,为了简洁起见,我们将这张地图称为 volumeResizeRequired;
  4. 手动删除正在使用该磁盘的 pod。 Kubernetes 将重新启动它。 使磁盘没有时间挂载(ControllerPublishVolume)在尝试挂载时完成增加操作之前,我们检查给定的磁盘是否仍在 volumeResizeRequired 并返回错误;
  5. CSI 驱动程序尝试重新执行调整大小操作。 如果操作成功,则将磁盘从 volumeResizeRequired;
  6. 因为磁盘 ID 缺失 volumeResizeRequired, ControllerPublishVolume 通过成功,磁盘挂载,pod启动。

一切看起来都很简单,但一如既往地存在陷阱。 扩大磁盘 外部缩放器,如果操作过程中出现错误 使用队列 超时时间呈指数增长,最多 1000 秒:

func DefaultControllerRateLimiter() RateLimiter {
  return NewMaxOfRateLimiter(
  NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
  // 10 qps, 100 bucket size.  This is only for retry speed and its only the overall factor (not per item)
  &BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
  )
}

这可能会定期导致磁盘扩展操作延长 15 分钟以上,从而导致相应的 pod 不可用。

唯一可以轻松无痛地减少潜在停机时间的选择是使用我们的具有最大超时限制的外部调整器版本 5 秒后:

workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)

我们认为没有必要紧急发起讨论并修补外部调整器,因为离线调整磁盘大小是一种回归,很快就会从所有云提供商中消失。

如何开始使用?

Kubernetes 版本 1.15 及更高版本支持该驱动程序。 驾驶员要工作,必须满足以下要求:

  • --allow-privileged 设置为值 true 用于 API 服务器和 kubelet;
  • 包括 --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true 用于 API 服务器和 kubelet;
  • 安装传播(安装传播) 必须在集群上启用。 使用 Docker 时,必须将守护进程配置为允许共享挂载。

安装本身的所有必要步骤 自述文件中描述。 安装涉及从清单在 Kubernetes 中创建对象。

为了使驱动程序正常工作,您需要以下内容:

  • 在清单中指定目录标识符(folder-id) Yandex.Cloud (查看文档);
  • 为了与 Yandex.Cloud API 交互,CSI 驱动程序使用服务帐户。 在清单中,必须传递 Secret 授权密钥 来自服务帐户。 在文档中 描述,如何创建服务帐户并获取密钥。

总而言之 - 尝试,我们很高兴收到反馈和 新问题如果您遇到任何问题!

进一步支持

因此,我们要指出的是,我们实现这个 CSI 驱动程序并不是出于想用 Go 编写应用程序的乐趣,而是因为公司内部的迫切需求。 对我们来说,维护自己的实现似乎并不实际,因此,如果 Yandex 表现出兴趣并决定继续支持该驱动程序,我们将很乐意将存储库转移给他们。

此外,Yandex 可能在其托管 Kubernetes 集群中拥有自己的 CSI 驱动程序实现,该实现可以开源发布。 我们还认为这种开发选项是有利的 - 社区将能够使用来自服务提供商的经过验证的驱动程序,而不是来自第三方公司的驱动程序。

PS

另请阅读我们的博客:

来源: habr.com

添加评论