本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 的容器存储接口(CSI)GA
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 被开发为一种标准,用于将任意块和文件存储系统暴露给 Kubernetes 等容器编排系统 (CO) 上的容器化工作负载。随着容器存储接口的采用,Kubernetes 卷层变得真正可扩展。使用 CSI,第三方存储提供商可以编写和部署插件,在 Kubernetes 中暴露新的存储系统,而无需触及 Kubernetes 核心代码。这为 Kubernetes 用户提供了更多存储选项,并使系统更安全可靠。
有什么新内容?
随着提升至 GA,CSI 的 Kubernetes 实现引入了以下更改:
- Kubernetes 现在兼容 CSI 规范 v1.0 和 v0.3(而不是 CSI 规范 v0.2)。
- CSI 规范 v0.3.0 和 v1.0.0 之间存在不兼容的更改,但 Kubernetes v1.13 支持这两个版本,因此任一版本都将与 Kubernetes v1.13 配合使用。
- 请注意,随着 CSI 1.0 API 的发布,对使用 CSI 0.3 及更早版本的 CSI API 的 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 卷:PersistentVolumeClaims
、PersistentVolumes
和 StorageClasses
。文档在此处。
尽管 CSI 的 Kubernetes 实现是 Kubernetes v1.13 中的 GA 功能,但它可能需要以下标志
- API 服务器二进制文件和 kubelet 二进制文件
--allow-privileged=true
- 大多数 CSI 插件将需要双向挂载传播,这只能为特权 Pod 启用。特权 Pod 仅在设置此标志为 true 的集群上才允许(在某些环境(如 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 外部供应器 (v1.0.1+) 保留以 csi.storage.k8s.io/
为前缀的参数键。如果这些键不对应一组已知的键,则这些值将被简单地忽略(并且不传递给 CSI 驱动程序)。旧的秘密参数键(csiProvisionerSecretName
、csiProvisionerSecretNamespace
等)也受 CSI 外部供应器 v1.0.1 支持,但已弃用,并可能在 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 插件 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 插件的适当操作(ControllerPublishVolume
、NodeStageVolume
、NodePublishVolume
等),以确保指定的卷已附加、挂载并可供 Pod 中的容器使用。
如何编写 CSI 驱动程序?
kubernetes-csi 网站详细介绍了如何在 Kubernetes 上开发、部署和测试 CSI 驱动程序。通常,CSI 驱动程序应与以下 sidecar(辅助)容器一起部署在 Kubernetes 上:
- 外部附加器 (external-attacher)
- 监视 Kubernetes
VolumeAttachment
对象,并针对 CSI 端点触发ControllerPublish
和ControllerUnpublish
操作。
- 监视 Kubernetes
- 外部供应器 (external-provisioner)
- 监视 Kubernetes
PersistentVolumeClaim
对象,并针对 CSI 端点触发CreateVolume
和DeleteVolume
操作。
- 监视 Kubernetes
- 节点驱动程序注册器 (node-driver-registrar)
- 使用 Kubelet 设备插件机制向 kubelet 注册 CSI 驱动程序。
- 集群驱动程序注册器 (cluster-driver-registrar) (Alpha)
- 通过创建
CSIDriver
对象向 Kubernetes 集群注册 CSI 驱动程序,该对象允许驱动程序自定义 Kubernetes 如何与其交互。
- 通过创建
- 外部快照器 (external-snapshotter) (Alpha)
- 监视 Kubernetes
VolumeSnapshot
CRD 对象,并针对 CSI 端点触发CreateSnapshot
和DeleteSnapshot
操作。
- 监视 Kubernetes
- 存活探针 (livenessprobe)
- 可包含在 CSI 插件 pod 中,以启用 Kubernetes 存活探针 机制。
存储供应商可以使用这些组件为其插件构建 Kubernetes 部署,同时使其 CSI 驱动程序完全不了解 Kubernetes。
CSI 驱动程序列表
CSI 驱动程序由第三方开发和维护。您可以在此处找到一个非完整 CSI 驱动程序列表。
树内卷插件怎么样?
有一个计划将大多数持久的、远程的树内卷插件迁移到 CSI。有关更多详情,请参阅设计文档。
GA 的局限性
CSI 的 GA 实现有以下限制:
- 临时本地卷必须创建 PVC(不支持 pod 内联引用 CSI 卷)。
下一步是什么?
- 正在努力将仍处于 alpha 状态的 Kubernetes CSI 功能迁移到 beta 状态
- 原始块卷
- 拓扑感知(Kubernetes 理解和影响 CSI 卷配置位置(区域、区域等)的能力)。
- 依赖 CSI CRD 的功能(例如,“跳过附加”和“挂载时 Pod 信息”)。
- 卷快照
- 正在努力完成对本地临时卷的支持。
- 正在努力将远程持久树内卷插件迁移到 CSI。
如何参与?
Kubernetes Slack 频道 wg-csi 和 Google 群组 SIG 存储通信渠道 都是联系 SIG 存储团队的绝佳途径。
与所有 Kubernetes 项目一样,这个项目也是许多来自不同背景的贡献者共同努力的成果。我们非常感谢本季度挺身而出帮助项目达到 GA 的新贡献者:
- Saad Ali (saad-ali)
- Michelle Au (msau42)
- Serguei Bezverkhi (sbezverk)
- Masaki Kimura (mkimuram)
- Patrick Ohly (pohly)
- Luis Pabón (lpabon)
- Jan Šafránek (jsafrane)
- Vladimir Vivien (vladimirvivien)
- Cheng Xing (verult)
- Xing Yang (xing-yang)
- David Zhu (davidz627)
如果您有兴趣参与 CSI 或 Kubernetes 存储系统的任何部分的设计和开发,请加入 Kubernetes 存储特别兴趣小组 (SIG)。我们正在快速发展,并始终欢迎新的贡献者。