本文已过时一年以上。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes 的容器存储接口 (CSI) 进入 Beta 版

Kubernetes Logo CSI Logo

容器存储接口(CSI)的 Kubernetes 实现现在在 Kubernetes v1.10 中处于 beta 阶段。CSI 在 Kubernetes v1.9 中以 alpha 形式引入

Kubernetes 的功能通常以 alpha 形式引入,并在后续的 Kubernetes 版本中移至 beta(最终移至稳定/GA)。此过程使 Kubernetes 开发人员能够获得反馈、发现和修复问题、迭代设计并交付高质量的生产级功能。

为什么要在 Kubernetes 中引入容器存储接口?

尽管 Kubernetes 已经提供了一个强大的卷插件系统,可以轻松使用不同类型的块和文件存储,但添加对新卷插件的支持一直具有挑战性。由于卷插件目前是“树内”的——卷插件是核心 Kubernetes 代码的一部分,并与核心 Kubernetes 二进制文件一起发布——希望向 Kubernetes 添加对其存储系统支持(甚至修复现有卷插件中的错误)的供应商必须与 Kubernetes 发布过程保持一致。

通过采用容器存储接口,Kubernetes 卷层变得真正可扩展。现在,第三方存储开发人员可以编写和部署卷插件,从而在 Kubernetes 中公开新的存储系统,而无需接触核心 Kubernetes 代码。这将为支持 Kubernetes 用户有状态容器化工作负载的存储提供更多选择。

Beta 版本的新特性是什么?

随着升级到 beta 版本,CSI 现在在标准的 Kubernetes 部署中默认启用,而不是选择加入。

Kubernetes 中 CSI 的实现移至 beta 版本也意味着

  • Kubernetes 与 CSI 规范的 v0.2 版本兼容(而不是 v0.1 版本)
    • CSI 规范的 v0.1 和 v0.2 版本之间存在重大更改,因此现有的 CSI 驱动程序必须更新为与 0.2 版本兼容,才能与 Kubernetes 1.10.0+ 一起使用。
  • 挂载传播是一种允许容器和主机之间双向挂载的功能(容器化 CSI 驱动程序的要求),也已移至 beta 版本。
  • Kubernetes VolumeAttachment 对象在 v1.9 中以 storage v1alpha1 组引入,已添加到 storage v1beta1 组。
  • Kubernetes CSIPersistentVolumeSource 对象已升级到 beta 版本。Kubernetes CSIPersistentVolumeSource 对象添加了一个 VolumeAttributes 字段(在 alpha 版本中,这是通过注解传递的)。
  • 节点授权器已更新,以限制 kubelet 对 VolumeAttachment 对象的访问。
  • Kubernetes CSIPersistentVolumeSource 对象和 CSI external-provisioner 已修改为允许将密钥传递给 CSI 卷插件。
  • Kubernetes CSIPersistentVolumeSource 已修改为允许传入文件系统类型(以前始终假定为 ext4)。
  • 在 CSI 规范中添加了一个新的可选调用 NodeStageVolume,并且 Kubernetes CSI 卷插件已修改为在 MountDevice 期间调用 NodeStageVolume(在 alpha 版本中,此步骤是无操作)。

如何在 Kubernetes 集群上部署 CSI 驱动程序?

CSI 插件作者必须提供他们自己的说明,以指导如何在 Kubernetes 上部署他们的插件。

Kubernetes-CSI 实现团队创建了一个示例 hostpath CSI 驱动程序。该示例粗略地说明了 CSI 驱动程序的部署过程。但是,生产驱动程序将通过 DaemonSet 部署节点组件,并通过 StatefulSet 部署控制器组件,而不是单个 pod(例如,请参阅 GCE PD 驱动程序的部署文件)。

如何在我的 Kubernetes pod 中使用 CSI 卷?

假设 CSI 存储插件已部署在您的集群上,您可以通过熟悉的 Kubernetes 存储原语(PersistentVolumeClaimsPersistentVolumesStorageClasses)使用它。

CSI 是 Kubernetes v1.10 中的一个 beta 功能。尽管默认启用,但可能需要以下标志

  • API 服务器二进制文件和 kubelet 二进制文件
    • --allow-privileged=true
      • 大多数 CSI 插件将需要双向挂载传播,这只能为特权 pod 启用。只有在将此标志设置为 true 的集群上才允许特权 pod(在某些环境(如 GCE、GKE 和 kubeadm)中,这是默认设置)。

动态配置

您可以通过创建一个指向 CSI 插件的 StorageClass 来启用对支持动态配置的 CSI 存储插件的卷的自动创建/删除。

例如,以下 StorageClass 允许名为 "com.example.csi-driver" 的 CSI 卷插件动态创建 “fast-storage” 卷。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: fast-storage
provisioner: com.example.csi-driver
parameters:
  type: pd-ssd
  csiProvisionerSecretName: mysecret
  csiProvisionerSecretNamespace: mynamespace

beta 版本的新功能是,默认的 CSI external-provisioner 保留了参数键 csiProvisionerSecretNamecsiProvisionerSecretNamespace。如果指定,它会获取密钥并在配置期间将其传递给 CSI 驱动程序。

动态配置由 PersistentVolumeClaim 对象的创建触发。例如,以下 PersistentVolumeClaim 使用上面的 StorageClass 触发动态配置。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-request-for-storage
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: fast-storage

当调用卷配置时,参数类型:pd-ssd 和任何引用的密钥将通过 CreateVolume 调用传递给 CSI 插件 com.example.csi-driver。作为响应,外部卷插件将配置一个新卷,然后自动创建一个 PersistentVolume 对象来表示该新卷。然后,Kubernetes 将新的 PersistentVolume 对象绑定到 PersistentVolumeClaim,使其准备好使用。

如果将 fast-storage StorageClass 标记为“默认”,则无需在 PersistentVolumeClaim 中包含 storageClassName,它将默认使用。

预配置的卷

您始终可以通过手动创建一个 PersistentVolume 对象来表示现有卷,从而在 Kubernetes 中公开预先存在的卷。例如,以下 PersistentVolume 公开了属于名为 “com.example.csi-driver” 的 CSI 存储插件的名为 “existingVolumeName” 的卷。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-manually-created-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  csi:
    driver: com.example.csi-driver
    volumeHandle: existingVolumeName
    readOnly: false
    fsType: ext4
    volumeAttributes:
      foo: bar
    controllerPublishSecretRef:
      name: mysecret1
      namespace: mynamespace
    nodeStageSecretRef:
      name: mysecret2
      namespace: mynamespace
    nodePublishSecretRef
      name: mysecret3
      namespace: mynamespace

附加和挂载

您可以在任何 pod 或 pod 模板中引用绑定到 CSI 卷的 PersistentVolumeClaim

kind: Pod
apiVersion: v1
metadata:
  name: my-pod
spec:
  containers:
    - name: my-frontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: my-csi-volume
  volumes:
    - name: my-csi-volume
      persistentVolumeClaim:
        claimName: my-request-for-storage

当调度引用 CSI 卷的 pod 时,Kubernetes 将针对外部 CSI 插件触发适当的操作(ControllerPublishVolumeNodeStageVolumeNodePublishVolume 等),以确保指定的卷已附加、挂载并且可以由 pod 中的容器使用。

有关更多详细信息,请参阅 CSI 实现设计文档文档

如何编写 CSI 驱动程序?

Kubernetes 上的 CSI 卷驱动程序部署必须满足一些最低要求

最低要求文档还概述了在 Kubernetes 上部署任意容器化 CSI 驱动程序的建议机制。存储提供商可以使用此机制来简化在 Kubernetes 上部署容器化 CSI 兼容卷驱动程序的过程。

作为建议的部署过程的一部分,Kubernetes 团队提供了以下 sidecar(辅助)容器

  • external-attacher
    • 监视 Kubernetes VolumeAttachment 对象,并针对 CSI 端点触发 ControllerPublishControllerUnpublish 操作
  • external-provisioner
    • 监视 Kubernetes PersistentVolumeClaim 对象,并针对 CSI 端点触发 CreateVolumeDeleteVolume 操作
  • driver-registrar
    • 向 kubelet 注册 CSI 驱动程序(将来),并将驱动程序自定义的 NodeId(通过针对 CSI 端点的 GetNodeID 调用检索)添加到 Kubernetes Node API 对象的注解中
  • livenessprobe

存储供应商可以使用这些组件为其插件构建 Kubernetes 部署,同时使其 CSI 驱动程序完全不知道 Kubernetes。

在哪里可以找到 CSI 驱动程序?

CSI 驱动程序由第三方开发和维护。您可以找到一些示例和生产 CSI 驱动程序的非决定性列表。

FlexVolumes 怎么样?

正如alpha 版本博客文章中所述,FlexVolume 插件是早期尝试使 Kubernetes 卷插件系统可扩展的尝试。尽管它使第三方存储供应商能够编写“树外”驱动程序,但由于它是基于 exec 的 API,因此 FlexVolumes 要求将第三方驱动程序二进制文件(或脚本)的文件复制到每个节点(以及在某些情况下为 master)机器的根文件系统上的特殊插件目录中。这要求集群管理员对每个节点的主机文件系统具有写访问权限,并且需要一些外部机制来确保在删除驱动程序文件后重新创建该文件,以便部署卷插件。

除了难以部署之外,Flex 并没有解决插件依赖项的痛点:例如,卷插件往往有很多外部要求(关于挂载和文件系统工具)。这些依赖项假定在底层主机操作系统上可用,但情况并非总是如此。

CSI 通过不仅使存储插件能够进行树外开发,还可以通过标准 Kubernetes 原语进行容器化和部署来解决这些问题。

如果您仍然对树内卷与 CSI 与 Flex 有疑问,请参阅卷插件常见问题解答

树内卷插件会发生什么?

一旦 CSI 达到稳定状态,我们计划将大多数树内卷插件迁移到 CSI。请继续关注 Kubernetes CSI 实现接近稳定状态的更多详细信息。

Beta 版本的限制是什么?

CSI 的 beta 实现具有以下限制

  • 不支持块卷;仅支持文件卷。
  • 即使 CSI 驱动程序没有实现 ControllerPublishVolume,也必须使用提供的 external-attacher sidecar 插件进行部署。
  • CSI 卷不支持拓扑感知,包括共享有关卷配置位置(区域、区域等)的信息,以便 Kubernetes 调度程序做出更明智的调度决策,以及 Kubernetes 调度程序或集群管理员或应用程序开发人员指定应在何处配置卷的能力。
  • driver-registrar 需要修改所有 Kubernetes 节点 API 对象的权限,这可能会导致受损节点获得执行相同操作的能力。

下一步是什么?

根据反馈和采用情况,Kubernetes 团队计划在 1.12 中将 CSI 实现推向 GA。

团队鼓励存储供应商开始开发 CSI 驱动程序,将其部署在 Kubernetes 上,并通过 Kubernetes Slack 频道 wg-csi、Google 群组 kubernetes-sig-storage-wg-csi 或任何标准的 SIG存储沟通渠道 向团队分享反馈。

如何参与?

这个项目,和所有 Kubernetes 项目一样,是来自不同背景的许多贡献者共同努力的成果。

除了自 Alpha 版本以来一直致力于 Kubernetes CSI 实现的贡献者之外,还有:

我们非常感谢本季度挺身而出,帮助该项目达到 Beta 版本的新贡献者:

如果您有兴趣参与 CSI 的设计和开发,或 Kubernetes 存储系统的任何部分,请加入 Kubernetes 存储特别兴趣小组 (SIG)。我们正在迅速发展,并始终欢迎新的贡献者。