容器存储接口 CSI
Container Storage Interface (CSI) 是从 v1.9 引入的容器存储接口,并于 v1.13 版本正式 GA。实际上,CSI 是整个容器生态的标准存储接口,同样适用于 Mesos、Cloud Foundry 等其他的容器集群调度系统。
版本信息
Sidecar 容器版本
external-provisioner
Watch PVC and create PV
v1.0.0
v1.0.1
external-attacher
Operate VolumeAttachment
v1.0.0
v1.0.1
external-snapshotter
Operate VolumeSnapshot
v1.0.0
v1.0.1
node-driver-registrar
Register kubelet plugin
v1.0.0
v1.0.2
livenessprobe
Monitors health of CSI driver
v1.0.0
v1.0.2
原理
类似于 CRI,CSI 也是基于 gRPC 实现。详细的 CSI SPEC 可以参考 这里,它要求插件开发者要实现三个 gRPC 服务:
Identity Service:用于 Kubernetes 与 CSI 插件协调版本信息
Controller Service:用于创建、删除以及管理 Volume 存储卷
Node Service:用于将 Volume 存储卷挂载到指定的目录中以便 Kubelet 创建容器时使用(需要监听在
/var/lib/kubelet/plugins/[SanitizedCSIDriverName]/csi.sock
)
由于 CSI 监听在 unix socket 文件上, kube-controller-manager 并不能直接调用 CSI 插件。为了协调 Volume 生命周期的管理,并方便开发者实现 CSI 插件,Kubernetes 提供了几个 sidecar 容器并推荐使用下述方法来部署 CSI 插件:

该部署方法包括:
StatefuelSet:副本数为 1 保证只有一个实例运行,它包含三个容器
用户实现的 CSI 插件
External Attacher:Kubernetes 提供的 sidecar 容器,它监听 VolumeAttachment 和 PersistentVolume 对象的变化情况,并调用 CSI 插件的 ControllerPublishVolume 和 ControllerUnpublishVolume 等 API 将 Volume 挂载或卸载到指定的 Node 上
External Provisioner:Kubernetes 提供的 sidecar 容器,它监听 PersistentVolumeClaim 对象的变化情况,并调用 CSI 插件的 ControllerPublish 和 ControllerUnpublish 等 API 管理 Volume
Daemonset:将 CSI 插件运行在每个 Node 上,以便 Kubelet 可以调用。它包含 2 个容器
用户实现的 CSI 插件
Driver Registrar:注册 CSI 插件到 kubelet 中,并初始化 NodeId(即给 Node 对象增加一个 Annotation
csi.volume.kubernetes.io/nodeid
)
配置
API Server 配置:
--allow-privileged=true
--feature-gates=CSIPersistentVolume=true,MountPropagation=true
--runtime-config=storage.k8s.io/v1alpha1=true
Controller-manager 配置:
--feature-gates=CSIPersistentVolume=true
Kubelet 配置:
--allow-privileged=true
--feature-gates=CSIPersistentVolume=true,MountPropagation=true
Kubernetes 1.33 新特性:动态 CSI 节点分配计数
从 Kubernetes 1.33 开始,引入了一个 Alpha 特性 MutableCSINodeAllocatableCount
,允许 CSI 驱动程序动态更新节点可以处理的最大卷数量。这解决了静态卷附件限制报告的局限性,提高了 Pod 调度的准确性。
主要功能
动态更新能力:CSI 驱动程序可以实时更新节点的卷附件容量限制
两种更新机制:
周期性更新:CSI 驱动程序可设置间隔时间来刷新节点附件容量
反应式更新:当卷附件失败时触发立即更新
改善调度准确性:防止将 Pod 调度到卷容量不足的节点上
配置要求
需要在以下组件上启用 MutableCSINodeAllocatableCount
特性门控:
# API Server
--feature-gates=MutableCSINodeAllocatableCount=true
# Kubelet
--feature-gates=MutableCSINodeAllocatableCount=true
CSI 驱动程序配置示例
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: example.csi.k8s.io
spec:
# 设置节点分配计数更新周期(秒)
nodeAllocatableUpdatePeriodSeconds: 60
好处
防止 Pod 被调度到卷容量不足的节点
减少 Pod 卡在 "ContainerCreating" 状态的情况
提供更动态和准确的资源分配
改善存储资源的利用效率
注意:这是 Kubernetes v1.33 中的 Alpha 特性。在生产环境中使用前,建议先进行充分测试并向 Kubernetes Storage SIG 提供反馈。
示例
Kubernetes 提供了几个 CSI 示例,包括 NFS、ISCSI、HostPath、Cinder 以及 FlexAdapter 等。在实现 CSI 插件时,这些示例可以用作参考。
v0.0.1 (alpha)
A Container Storage Interface (CSI) Driver for DigitalOcean Block Storage
v0.0.1(alpha)
A Container Storage Interface (CSI) Driver for AWS Elastic Block Storage (EBS)
Alpha
A Container Storage Interface (CSI) Storage Plugin for Google Compute Engine Persistent Disk
Beta
For more information, please visit releases and https://github.com/opensds/nbp/tree/master/csi
v0.2.0 (alpha)
A Container Storage Interface (CSI) Storage Plug-in for NetApp's Trident container storage orchestrator
v0.2.0 (alpha)
Multi-vendor CSI plugin supporting over 80 storage drivers to provide block and mount storage to Container Orchestration systems.
CSI 卷数据填充器
从 Kubernetes v1.33 开始,CSI 驱动程序可以实现卷数据填充器(Volume Populators)功能,支持在卷创建时从自定义数据源填充数据。
实现方式
CSI 驱动程序可以通过以下方式支持卷数据填充器:
传统方式:创建填充 Pod 来处理数据填充任务
插件方式(v1.33 新增):实现插件函数,可选择性地跳过创建填充 Pod
CSI 驱动程序配置
要支持卷数据填充器,CSI 驱动程序需要在 CSIDriver 对象中声明支持的自定义资源类型:
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: example.csi.k8s.io
spec:
# 其他 CSI 驱动程序配置...
# 声明支持的数据源类型
populatorPolicy:
# 支持处理的自定义资源类型
supportedVolumeDataSources:
- apiGroup: backup.example.com
kind: VolumeBackup
- apiGroup: snapshot.example.com
kind: ExternalSnapshot
使用示例
配合 CSI 驱动程序使用卷数据填充器:
# 自定义数据源
apiVersion: backup.example.com/v1
kind: VolumeBackup
metadata:
name: database-backup-v1
namespace: default
spec:
backupURL: "s3://my-bucket/database-backup-20250101.tar.gz"
restorePoint: "2025-01-01T10:00:00Z"
---
# 使用自定义数据源的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: restored-database
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: fast-csi-storage
dataSourceRef:
apiGroup: backup.example.com
kind: VolumeBackup
name: database-backup-v1
CSI 插件实现要点
实现支持卷数据填充器的 CSI 驱动程序时需要注意:
数据源识别:解析 PVC 中的
dataSourceRef
字段填充逻辑:根据自定义资源的规格实现数据填充
状态报告:准确报告填充进度和完成状态
错误处理:处理填充失败的情况并提供清晰的错误信息
与传统数据源的区别
数据源类型
限制于内置类型
支持任意自定义资源
填充逻辑
内置实现
CSI 驱动程序自定义
扩展性
有限
高度可扩展
数据来源
仅 Kubernetes 内部
可从外部系统获取
NFS CSI 示例
下面以 NFS 为例来看一下 CSI 插件的使用方法。
首先需要部署 NFS 插件:
git clone https://github.com/kubernetes-csi/drivers
cd drivers/pkg/nfs
kubectl create -f deploy/kubernetes
然后创建一个使用 NFS 存储卷的容器
kubectl create -f examples/kubernetes/nginx.yaml
该例中已直接创建 PV 的方式使用 NFS
apiVersion: v1
kind: PersistentVolume
metadata:
name: data-nfsplugin
labels:
name: data-nfsplugin
annotations:
csi.volume.kubernetes.io/volume-attributes: '{"server":"10.10.10.10","share":"share"}'
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 100Gi
csi:
driver: csi-nfsplugin
volumeHandle: data-id
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-nfsplugin
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
selector:
matchExpressions:
- key: name
operator: In
values: ["data-nfsplugin"]
也可以用在 StorageClass 中
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: csi-sc-nfsplugin
provisioner: csi-nfsplugin
parameters:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: request-for-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: csi-sc-nfsplugin
参考文档
最后更新于