本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 的容器存储接口(CSI)进入 Beta 阶段
Kubernetes 的容器存储接口 (CSI) 实现在 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 版。已将VolumeAttributes
字段添加到 KubernetesCSIPersistentVolumeSource
对象(在 Alpha 版本中,此字段通过注释传递)。 - 节点授权器已更新,以限制 kubelet 对
VolumeAttachment
对象的访问。 - Kubernetes
CSIPersistentVolumeSource
对象和 CSI 外部供应器已修改,以允许将秘密传递给 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 存储原语来使用它:`PersistentVolumeClaims`、`PersistentVolumes` 和 `StorageClasses`。
CSI 是 Kubernetes v1.10 中的 Beta 功能。尽管默认启用,但它可能需要以下标志
- API 服务器二进制文件和 kubelet 二进制文件
--allow-privileged=true
- 大多数 CSI 插件将需要双向挂载传播,这只能为特权 Pod 启用。特权 Pod 仅在设置此标志为 true 的集群上允许(这在某些环境(如 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 外部供应器保留参数键 csiProvisionerSecretName
和 csiProvisionerSecretNamespace
。如果指定,它将获取秘密并在预配期间将其传递给 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 被标记为“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 插件的相应操作(`ControllerPublishVolume`、`NodeStageVolume`、`NodePublishVolume` 等),以确保指定的卷被附加、挂载并可供 Pod 中的容器使用。
如何编写 CSI 驱动程序?
Kubernetes 上的 CSI 卷驱动程序部署必须满足一些最低要求。
最低要求文档还概述了在 Kubernetes 上部署任意容器化 CSI 驱动程序的建议机制。存储提供商可以使用此机制来简化在 Kubernetes 上部署容器化 CSI 兼容卷驱动程序。
作为建议部署过程的一部分,Kubernetes 团队提供以下 sidecar(辅助)容器
- 外部附加器 (external-attacher)
- 监视 Kubernetes
VolumeAttachment
对象并触发针对 CSI 端点的ControllerPublish
和ControllerUnpublish
操作
- 监视 Kubernetes
- 外部供应器 (external-provisioner)
- 监视 Kubernetes
PersistentVolumeClaim
对象,并触发针对 CSI 端点的CreateVolume
和DeleteVolume
操作
- 监视 Kubernetes
- 驱动程序注册器
- 向 kubelet 注册 CSI 驱动程序(将来),并将驱动程序的自定义
NodeId
(通过对 CSI 端点执行GetNodeID
调用获取)添加到 Kubernetes Node API 对象的注释中
- 向 kubelet 注册 CSI 驱动程序(将来),并将驱动程序的自定义
- 存活探测
- 可包含在 CSI 插件 Pod 中,以启用 Kubernetes 存活探测 机制
存储供应商可以使用这些组件为其插件构建 Kubernetes 部署,同时使其 CSI 驱动程序完全不了解 Kubernetes。
在哪里可以找到 CSI 驱动程序?
CSI 驱动程序由第三方开发和维护。您可以找到一些示例和生产 CSI 驱动程序的非详尽列表。
FlexVolumes 怎么样?
正如Alpha 版本博客文章中所述,FlexVolume 插件是早期尝试使 Kubernetes 卷插件系统可扩展的方法。尽管它使第三方存储供应商能够编写“树外”驱动程序,但由于它是一个基于 exec 的 API,FlexVolumes 要求将第三方驱动程序二进制文件(或脚本)复制到每个节点(在某些情况下,还有主节点)机器根文件系统上的一个特殊插件目录中。这需要集群管理员对每个节点的主机文件系统具有写访问权限,并且需要一些外部机制来确保如果驱动程序文件被删除,它会被重新创建,仅仅是为了部署一个卷插件。
除了部署困难之外,Flex 也未能解决插件依赖性问题:卷插件往往有许多外部要求(例如,对挂载和文件系统工具的要求)。这些依赖项被假定在底层主机操作系统上可用,但事实往往并非如此。
CSI 解决了这些问题,它不仅使存储插件能够在树外开发,而且能够容器化并通过标准 Kubernetes 原语进行部署。
如果您仍然对树内卷、CSI 和 Flex 之间的区别有疑问,请参阅卷插件 FAQ。
树内卷插件会怎么样?
一旦 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 存储通信渠道与团队分享反馈。
我如何参与?
这个项目,和所有 Kubernetes 项目一样,是许多来自不同背景的贡献者共同努力的结果。
除了自 Alpha 版本以来一直致力于 Kubernetes CSI 实现的贡献者之外
- Bradley Childs (childsb)
- Chakravarthy Nelluri (chakri-nelluri)
- Jan Šafránek (jsafrane)
- Luis Pabón (lpabon)
- Saad Ali (saad-ali)
- Vladimir Vivien (vladimirvivien)
我们非常感谢本季度为帮助项目达到 Beta 阶段而站出来的新贡献者
- David Zhu (davidz627)
- Edison Xiang (edisonxiang)
- Felipe Musse (musse)
- Lin Ml (mlmhl)
- Lin Youchong (linyouchong)
- Pietro Menna (pietromenna)
- Serguei Bezverkhi (sbezverk)
- Xing Yang (xing-yang)
- Yuquan Ren (NickrenREN)
如果您有兴趣参与 CSI 或 Kubernetes 存储系统任何部分的设计和开发,请加入 Kubernetes 存储特别兴趣小组 (SIG)。我们正在迅速发展,并始终欢迎新的贡献者。