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



我们很高兴地宣布,Flant公司将通过发布Yandex.Cloud 的CSI(容器存储接口)驱动程序alpha版本来补充其对Kubernetes开源工具的贡献

但是,在继续实施细节之前,我们将回答一个问题,即当Yandex已经具有Kubernetes托管服务时,为什么根本需要这样做

介绍


为什么是这样?


在我们公司内部,从Kubernetes投入生产的最初阶段(即几年)开始,我们正在开发自己的工具(deckhouse),顺便说一下,我们还计划在不久的将来将其作为开源项目提供。在其帮助下,我们可以统一配置和配置所有集群,目前,在铁的各种配置以及所有可用的云服务中,有超过100个集群。

使用甲板室的集群具有所有必要的工作组件:平衡器,使用方便的图表进行监视,度量和警报,通过外部提供程序进行的用户身份验证以访问所有仪表板,等等。将这样的“集聚式”群集放入托管解决方案中是没有意义的,因为这通常是不可能的,或者将导致需要禁用一半组件。

注意:这是我们的经验,非常具体。我们绝不主张每个人都应该独立参与Kubernetes集群部署,而不是使用现成的解决方案。顺便说一下,我们在使用Yandex操作Kubernetes方面没有实际经验,在本文中我们将不对该服务进行任何评估。

这是什么,给谁的?


因此,我们已经讨论过Kubernetes中的现代存储方法:CSI如何工作以及社区如何采用这种方法。

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

作为开发的基础,我们采用了DigitalOcean云CSI驱动程序以及GCP驱动程序的一些想法,因为这些云(Google和Yandex)与API的交互具有许多相似之处。特别是API和GCPYandex返回一个对象,Operation以跟踪冗长的操作(例如,创建新磁盘)的状态。为了与Yandex.Cloud API进行交互,使用了Yandex.Cloud Go SDK

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

实作


主要特点


当前,驱动程序支持以下功能:

  • 根据集群中节点的拓扑对集群所有区域中的磁盘进行排序;
  • 卸下先前订购的磁盘;
  • 磁盘的脱机大小调整(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规范不能满足以下要求:

  • 在sidecar-container中csi-attacher,应该负责安装之间是否存在必要的间隙,该功能根本无法通过离线调整大小来实现。关于这个的讨论已启动这里
  • 在这种情况下,什么是杂物箱?CSI插件本身不与Kubernetes API交互,而仅响应sidecar容器发送给它的gRPC调用。后者 Kubernetes社区开发

在本例中(CSI插件),增加磁盘的操作如下:

  1. 我们收到一个gRPC呼叫ControllerExpandVolume
  2. 我们正在尝试增加API中的磁盘,但是由于磁盘已安装,因此出现无法执行操作的错误;
  3. 我们将磁盘标识符保存在包含您需要对其执行增加操作的磁盘的映射中。为了简洁起见,我们将此地图称为volumeResizeRequired
  4. 手动删除使用磁盘的Pod。Kubernetes将重新启动它。为了使磁盘没有时间ControllerPublishVolume在尝试进行增加操作之前先进行挂载(),请检查该磁盘是否仍在插入volumeResizeRequired并返回错误。
  5. CSI驱动程序正在尝试重新执行调整大小操作。如果操作成功,则从volumeResizeRequired; 删除磁盘
  6. 因为 缺少磁盘标识符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分钟以上,从而导致相应的容器无法访问。

使我们能够轻松而轻松地减少潜在停机时间的唯一选择是使用我们的外部调整器版本,最大超时限制为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时,必须配置守护程序,以便允许共享安装。

README描述了安装本身的所有必要步骤安装是从清单中在Kubernetes中创建对象。

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

  • 在清单中指示Yandex.Cloud目录目录(folder-id的标识符请参阅文档);
  • 为了与CSI驱动程序中的Yandex.Cloud API交互,使用了一个服务帐户。在“秘密”清单中,您必须将授权密钥传递给服务帐户。该文档介绍了如何创建服务帐户并获取密钥。

通常,请尝试一下如果您遇到任何问题,我们将很高兴收到反馈和问题!

进一步的支持


因此,我们想指出的是,实现此CSI驱动程序并不是出于在Go上编写应用程序的乐趣,而是因为公司内部的迫切需求。似乎不建议支持我们自己的实现,因此,如果Yandex表示兴趣并决定继续支持驱动程序,我们将很乐意将存储库移交给他们使用。

此外,也许Kubernetes托管集群中的Yandex具有自己的CSI驱动程序实现,可以在开源中发布。此开发选项对我们似乎也很有利-社区将能够使用服务提供商而不是第三方公司提供的可靠驱动程序。

聚苯乙烯


另请参阅我们的博客:

Source: https://habr.com/ru/post/undefined/


All Articles