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

Kubernetes 的容器存储接口 (CSI) GA

Kubernetes Logo CSI Logo

Kubernetes 对 容器存储接口 (CSI) 的实现已在 Kubernetes v1.13 版本中升级为 GA(正式发布)。对 CSI 的支持在 Kubernetes v1.9 版本中 作为 alpha 版本引入,并在 Kubernetes v1.10 版本中升级为 beta 版本

GA 里程碑表明 Kubernetes 用户可以依赖该功能及其 API,而不必担心未来出现向后不兼容的更改导致回归。GA 功能受 Kubernetes 弃用策略的保护。

为什么使用 CSI?

尽管在 CSI 之前,Kubernetes 提供了一个强大的卷插件系统,但向 Kubernetes 添加对新卷插件的支持具有挑战性:卷插件是“内置”的,这意味着它们的代码是核心 Kubernetes 代码的一部分,并且与核心 Kubernetes 二进制文件一起发布——希望为他们的存储系统添加对 Kubernetes 支持的供应商(甚至修复现有卷插件中的错误)不得不与 Kubernetes 发布流程保持一致。此外,第三方存储代码在核心 Kubernetes 二进制文件中导致了可靠性和安全性问题,并且该代码对于 Kubernetes 维护人员来说通常难以(在某些情况下不可能)进行测试和维护。

CSI 被开发为一种标准,用于将任意块和文件存储系统暴露给容器编排系统 (CO)(如 Kubernetes)上的容器化工作负载。随着容器存储接口的采用,Kubernetes 卷层变得真正可扩展。使用 CSI,第三方存储提供商可以编写和部署插件,在 Kubernetes 中公开新的存储系统,而无需触及核心 Kubernetes 代码。这为 Kubernetes 用户提供了更多存储选择,并使系统更加安全可靠。

有什么新功能?

随着升级为 GA,Kubernetes 对 CSI 的实现引入了以下更改

  • Kubernetes 现在兼容 CSI 规范 v1.0v0.3(而不是 CSI 规范 v0.2)。
    • CSI 规范 v0.3.0 和 v1.0.0 之间存在重大更改,但 Kubernetes v1.13 支持这两个版本,因此任何一个版本都可以与 Kubernetes v1.13 一起使用。
    • 请注意,随着 CSI 1.0 API 的发布,对使用 CSI API 的 0.3 及更早版本的 CSI 驱动程序的支持已被弃用,并计划在 Kubernetes v1.15 中删除。
    • CSI 规范 v0.2 和 v0.3 之间没有重大更改,因此 v0.2 驱动程序也应该与 Kubernetes v1.10.0+ 一起使用。
    • CSI 规范 v0.1 和 v0.2 之间存在重大更改,因此实现 CSI 0.1 的非常旧的驱动程序必须更新为至少与 0.2 兼容,然后才能与 Kubernetes v1.10.0+ 一起使用。
  • Kubernetes VolumeAttachment 对象(在 v1.9 中在 storage v1alpha1 组中引入,并在 v1.10 中添加到 v1beta1 组)已在 v1.13 中添加到 storage v1 组。
  • Kubernetes CSIPersistentVolumeSource 卷类型已升级为 GA。
  • Kubelet 设备插件注册机制(即 kubelet 发现新 CSI 驱动程序的方式)已在 Kubernetes v1.13 中升级为 GA。

如何部署 CSI 驱动程序?

有兴趣了解如何在 Kubernetes 上部署或管理现有 CSI 驱动程序的 Kubernetes 用户应查看 CSI 驱动程序的作者提供的文档。

如何使用 CSI 卷?

假设 CSI 存储插件已部署在 Kubernetes 集群上,用户可以通过熟悉的 Kubernetes 存储 API 对象使用 CSI 卷:PersistentVolumeClaimsPersistentVolumesStorageClasses。 此处记录

尽管 Kubernetes 对 CSI 的实现是 Kubernetes v1.13 中的 GA 功能,但它可能需要以下标志

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

动态配置

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

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

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

GA 的新功能,CSI external-provisioner (v1.0.1+) 保留了以 csi.storage.k8s.io/ 为前缀的参数键。如果键与一组已知的键不对应,则值将被简单地忽略(而不会传递给 CSI 驱动程序)。CSI external-provisioner v1.0.1 也支持较旧的 secret 参数键(csiProvisionerSecretNamecsiProvisionerSecretNamespace 等),但这些参数键已被弃用,可能会在 CSI external-provisioner 的未来版本中删除。

动态配置由 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 调用传递给 CSI 插件 csi-driver.example.com。作为响应,外部卷插件会配置一个新卷,然后自动创建一个 PersistentVolume 对象来表示新卷。然后,Kubernetes 将新的 PersistentVolume 对象绑定到 PersistentVolumeClaim,使其可以使用。

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

预配置卷

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

apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-manually-created-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  csi:
    driver: csi-driver.example.com
    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 驱动程序。一般来说,CSI 驱动程序应该与以下 sidecar(辅助)容器一起部署在 Kubernetes 上

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

CSI 驱动程序列表

CSI 驱动程序由第三方开发和维护。您可以在此处找到非最终的 CSI 驱动程序列表。

内置卷插件呢?

有一个计划将大多数持久的远程内置卷插件迁移到 CSI。有关更多详细信息,请参阅设计文档

GA 的限制

CSI 的 GA 实现具有以下限制

  • 临时本地卷必须创建 PVC(不支持 CSI 卷的 pod 内联引用)。

接下来是什么?

  • 致力于将 Kubernetes CSI 仍处于 alpha 阶段的功能迁移到 beta 版
    • 原始块卷
    • 拓扑意识(Kubernetes 了解和影响 CSI 卷配置位置(区域、地区等)的能力)。
    • 依赖于 CSI CRD 的功能(例如,“跳过附加”和“挂载时的 Pod 信息”)。
    • 卷快照
  • 致力于完成对本地临时卷的支持。
  • 致力于将远程持久化的 in-tree 卷插件迁移到 CSI。

如何参与?

Kubernetes Slack 频道 wg-csi 和 Google 群组 kubernetes-sig-storage-wg-csi,以及任何标准的 SIG 存储沟通渠道 都是联系 SIG Storage 团队的好途径。

这个项目,和所有的 Kubernetes 项目一样,是许多来自不同背景的贡献者共同努力的成果。我们非常感谢本季度挺身而出帮助项目达到 GA 的新贡献者。

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