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

Kubernetes Container Storage Interface (CSI) 进入 Beta 版

Kubernetes Logo CSI Logo

Kubernetes 对 Container Storage Interface (CSI) 的实现现已在 Kubernetes v1.10 中进入 Beta 版。CSI 是在 Kubernetes v1.9 中作为 Alpha 版引入的。

Kubernetes 特性通常作为 Alpha 版引入,并在后续的 Kubernetes 版本中升级到 Beta 版(最终升级到 Stable/GA 正式发布)。这个过程允许 Kubernetes 开发者获取反馈、发现并修复问题、迭代设计,并交付高质量、生产级的特性。

为什么要在 Kubernetes 中引入 Container Storage Interface?

尽管 Kubernetes 已提供强大的卷插件系统,可以轻松使用不同类型的块存储和文件存储,但增加对新卷插件的支持一直具有挑战性。因为卷插件目前是“树内”(in-tree)的——卷插件是 Kubernetes 核心代码的一部分,并随核心 Kubernetes 二进制文件一起发布——想要为他们的存储系统添加 Kubernetes 支持的供应商(甚至修复现有卷插件中的 bug)必须与 Kubernetes 发布流程保持一致。

随着 Container Storage Interface 的采用,Kubernetes 卷层变得真正可扩展。第三方存储开发者现在可以编写和部署卷插件,在 Kubernetes 中公开新的存储系统,而无需触碰 Kubernetes 核心代码。这将为支持 Kubernetes 用户有状态容器化工作负载的存储带来更多选项。

Beta 版有哪些新特性?

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

Kubernetes CSI 实现升级到 Beta 版也意味着

  • Kubernetes 与 CSI 规范的v0.2 版本兼容(而不是v0.1 版本
    • CSI 规范 v0.1 和 v0.2 之间存在重大变更,因此在使用 Kubernetes 1.10.0+ 之前,必须将现有的 CSI 驱动程序更新为兼容 0.2 版本。
  • 挂载传播(Mount propagation),一个允许容器和主机之间进行双向挂载的特性(容器化 CSI 驱动程序的要求),也已升级到 Beta 版。
  • Kubernetes VolumeAttachment 对象,在 v1.9 中作为 storage v1alpha1 组引入,现已添加到 storage v1beta1 组。
  • Kubernetes CSIPersistentVolumeSource 对象已升级到 Beta 版。在 Kubernetes CSIPersistentVolumeSource 对象中添加了 VolumeAttributes 字段(在 Alpha 版中,此信息通过注解传递)。
  • Node 授权器已更新,以限制 Kubelet 对 VolumeAttachment 对象的访问。
  • Kubernetes CSIPersistentVolumeSource 对象和 CSI external-provisioner 都已修改,以允许将 Secret 传递给 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 server 二进制文件和 kubelet 二进制文件
    • --allow-privileged=true
      • 大多数 CSI 插件需要双向挂载传播,这只能为特权 Pod 启用。特权 Pod 仅在设置了此标志为 true 的集群中允许(在某些环境如 GCE、GKE 和 kubeadm 中这是默认值)。

动态供给

对于支持动态供给的 CSI 存储插件,你可以通过创建指向 CSI 插件的 StorageClass 来启用卷的自动创建/删除。

例如,以下 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。如果指定,它会获取 Secret 并在供给期间将其传递给 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 和任何引用的 Secret 会通过 CreateVolume call 传递给 CSI 插件 com.example.csi-driver。作为响应,外部卷插件会供给一个新卷,然后自动创建一个 PersistentVolume 对象来表示新卷。Kubernetes 随后将新的 PersistentVolume 对象绑定到 PersistentVolumeClaim,使其可以使用。

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

预供给卷

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

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 驱动程序?

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

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

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

  • external-attacher
    • 监控 Kubernetes VolumeAttachment 对象,并针对 CSI 端点触发 ControllerPublishControllerUnpublish 操作
  • external-provisioner
    • 监控 Kubernetes PersistentVolumeClaim 对象,并针对 CSI 端点触发 CreateVolumeDeleteVolume 操作
  • driver-registrar
    • 将 CSI 驱动程序注册到 kubelet(将来实现),并将驱动程序自定义的 NodeId(通过对 CSI 端点调用 GetNodeID 获取)添加到 Kubernetes 节点 API 对象的注解中
  • 存活探针

存储供应商可以使用这些组件为其插件构建 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 驱动程序必须与提供的 external-attacher sidecar 插件一起部署,即使它们不实现 ControllerPublishVolume
  • 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 Storage 通信渠道 与团队分享反馈。

如何参与?

与所有 Kubernetes 项目一样,本项目也是来自不同背景的众多贡献者共同努力的成果。

除了自 alpha 版本以来一直致力于 Kubernetes CSI 实现的贡献者之外

我们非常感谢本季度挺身而出帮助项目达到 beta 阶段的新贡献者

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