深入理解k8s中的容器存储接口(CSI)

CSI出现的原因

K8s原生支持一些存储类型的PV,像iSCSI、NFS等。但这种方式让K8s代码与三方存储厂商代码紧密相连,带来不少麻烦。比如更改存储代码就得更新K8s组件,成本高;存储代码的bug还会影响K8s稳定性;K8s社区维护和测试负担重,而且存储插件特权高,存在安全隐患。CSI的出现,就是为了解决这些问题,把三方存储代码和K8s代码分开,让存储厂商开发插件更轻松。

CSI核心流程分三步

  1. Provision/Delete(创盘/删盘) :用户创建PVC,K8s根据PVC和StorageClass,让External Provisioner调用CSI插件创盘,之后创建PV并绑定PVC。删盘时,External Provisioner根据PVC回收策略,调用CSI插件删盘并删除PV。

  2. Attach/Detach(挂接/摘除) :Pod调度到节点后,AD控制器创建VolumeAttachment对象,External Attacher调用CSI插件挂接存储卷,完成后更新状态。Pod删除时,AD控制器删除VolumeAttachment对象,External Attacher调用插件摘除存储卷。

  3. Mount/Unmount(挂载/卸载) :Kubelet发现使用CSI类型PV的Pod调度到本节点,等待VolumeAttachment状态就绪,调用CSI插件挂载。Pod删除时,Kubelet调用插件卸载。

CSI Sidecar组件

为使 K8s 适配 CSI 标准,社区将与 K8s 相关的存储流程逻辑放在了 CSI Sidecar 组件中。

  1. Node Driver Registrar:负责把外部CSI插件注册到Kubelet,让Kubelet能调用插件函数。
  2. External Provisioner:创建或删除存储卷和PV资源。
  3. External Attacher:实现存储卷的挂接和摘除。
  4. External Resizer:监控PVC,满足条件时调用CSI插件扩容存储卷。
  5. livenessprobe:通过暴露端口检查CSI插件是否正常运行。

CSI接口

三方存储厂商需实现 CSI 插件的三大接口:IdentityServerControllerServerNodeServer

  1. IdentityServer:认证插件身份信息,提供插件名称、版本等。
go 复制代码
// IdentityServer is the server API for Identity service.
type IdentityServer interface {
    // 获取CSI插件的信息,比如名称、版本号
    GetPluginInfo(context.Context, *GetPluginInfoRequest) (*GetPluginInfoResponse, error)
    // 获取CSI插件提供的能力,比如是否提供ControllerService能力
    GetPluginCapabilities(context.Context, *GetPluginCapabilitiesRequest) (*GetPluginCapabilitiesResponse, error)
    // 获取CSI插件健康状况
    Probe(context.Context, *ProbeRequest) (*ProbeResponse, error)
}
  1. ControllerServer:处理存储卷的创建、删除、挂接、摘除、扩容等操作。
go 复制代码
// ControllerServer is the server API for Controller service.
type ControllerServer interface {
    // 创建存储卷
    CreateVolume(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error)
    // 删除存储卷
    DeleteVolume(context.Context, *DeleteVolumeRequest) (*DeleteVolumeResponse, error)
    // 挂接存储卷到特定节点
    ControllerPublishVolume(context.Context, *ControllerPublishVolumeRequest) (*ControllerPublishVolumeResponse, error)
    // 从特定节点摘除存储卷
    ControllerUnpublishVolume(context.Context, *ControllerUnpublishVolumeRequest) (*ControllerUnpublishVolumeResponse, error)
    // 验证存储卷能力是否满足要求,比如是否支持跨节点多读多写
    ValidateVolumeCapabilities(context.Context, *ValidateVolumeCapabilitiesRequest) (*ValidateVolumeCapabilitiesResponse, error)
    // 列举全部存储卷信息
    ListVolumes(context.Context, *ListVolumesRequest) (*ListVolumesResponse, error)
    // 获取存储资源池可用空间大小
    GetCapacity(context.Context, *GetCapacityRequest) (*GetCapacityResponse, error)
    // 获取ControllerServer支持功能点,比如是否支持快照能力
    ControllerGetCapabilities(context.Context, *ControllerGetCapabilitiesRequest) (*ControllerGetCapabilitiesResponse, error)
    // 创建快照
    CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error)
    // 删除快照
    DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error)
    // 获取所有快照信息
    ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error)
    // 扩容存储卷
    ControllerExpandVolume(context.Context, *ControllerExpandVolumeRequest) (*ControllerExpandVolumeResponse, error)
}
  1. NodeServer:负责存储卷在节点上的挂载、卸载、获取容量信息等。
go 复制代码
// ControllerServer is the server API for Controller service.
type ControllerServer interface {
    // 创建存储卷
    CreateVolume(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error)
    // 删除存储卷
    DeleteVolume(context.Context, *DeleteVolumeRequest) (*DeleteVolumeResponse, error)
    // 挂接存储卷到特定节点
    ControllerPublishVolume(context.Context, *ControllerPublishVolumeRequest) (*ControllerPublishVolumeResponse, error)
    // 从特定节点摘除存储卷
    ControllerUnpublishVolume(context.Context, *ControllerUnpublishVolumeRequest) (*ControllerUnpublishVolumeResponse, error)
    // 验证存储卷能力是否满足要求,比如是否支持跨节点多读多写
    ValidateVolumeCapabilities(context.Context, *ValidateVolumeCapabilitiesRequest) (*ValidateVolumeCapabilitiesResponse, error)
    // 列举全部存储卷信息
    ListVolumes(context.Context, *ListVolumesRequest) (*ListVolumesResponse, error)
    // 获取存储资源池可用空间大小
    GetCapacity(context.Context, *GetCapacityRequest) (*GetCapacityResponse, error)
    // 获取ControllerServer支持功能点,比如是否支持快照能力
    ControllerGetCapabilities(context.Context, *ControllerGetCapabilitiesRequest) (*ControllerGetCapabilitiesResponse, error)
    // 创建快照
    CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error)
    // 删除快照
    DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error)
    // 获取所有快照信息
    ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error)
    // 扩容存储卷
    ControllerExpandVolume(context.Context, *ControllerExpandVolumeRequest) (*ControllerExpandVolumeResponse, error)
}

K8s CSI API对象

K8s 为支持 CSI 标准,包含如下 API 对象:

  1. CSINode:判断CSI插件是否注册成功,关联K8s节点和三方存储节点,显示卷拓扑信息。
yaml 复制代码
apiVersion: storage.k8s.io/v1beta1
kind: CSINode
metadata:
  name: node-10.212.101.210
spec:
  drivers:
  - name: yodaplugin.csi.alibabacloud.com
    nodeID: node-10.212.101.210
    topologyKeys:
    - kubernetes.io/hostname
  - name: pangu.csi.alibabacloud.com
    nodeID: a5441fd9013042ee8104a674e4a9666a
    topologyKeys:
    - topology.pangu.csi.alibabacloud.com/zone
  1. CSIDriver:方便发现外部CSI插件,自定义K8s行为。
yaml 复制代码
apiVersion: storage.k8s.io/v1beta1
kind: CSIDriver
metadata:
  name: pangu.csi.alibabacloud.com
spec:
    # 插件是否支持卷挂接(VolumeAttach)
  attachRequired: true
  # Mount阶段是否CSI插件需要Pod信息
  podInfoOnMount: true
  # 指定CSI支持的卷模式
  volumeLifecycleModes:
  - Persistent
  1. VolumeAttachment:记录存储卷挂接/摘除和节点信息。
yaml 复制代码
apiVersion: storage.k8s.io/v1
kind: VolumeAttachment
metadata:
  annotations:
    csi.alpha.kubernetes.io/node-id: 21481ae252a2457f9abcb86a3d02ba05
  finalizers:
  - external-attacher/pangu-csi-alibabacloud-com
  name: csi-0996e5e9459e1ccc1b3a7aba07df4ef7301c8e283d99eabc1b69626b119ce750
spec:
  attacher: pangu.csi.alibabacloud.com
  nodeName: node-10.212.101.241
  source:
    persistentVolumeName: pangu-39aa24e7-8877-11eb-b02f-021234350de1
status:
  attached: true

CSI支持特性

  1. 拓扑支持:依据节点拓扑挂载存储卷,提升数据访问效率。
  2. 存储卷扩容:用户修改PVC存储请求字段就能扩容,不过只能扩容不能缩容。
  3. 单节点卷数量限制:限制单个节点挂载存储卷的数量。
  4. 存储卷监控:存储商实现相关接口,Kubelet获取存储卷容量、使用量等指标。
  5. Secret:通过Secret处理存储过程中的私密数据。
  6. 块设备:三方存储厂商实现特定接口,K8s提供工具包支持块设备使用。
  7. 卷快照/卷克隆能力:可对存储卷进行快照和克隆,用于数据备份、恢复和快速创建新卷。

好了完结撒花!

相关推荐
June bug2 小时前
【软考中级·软件评测师】下午题·面向对象测试之架构考点全析:分层、分布式、微内核与事件驱动
经验分享·分布式·职场和发展·架构·学习方法·测试·软考
阿波罗.20123 小时前
Zookeeper 客户端 .net访问框架 ZookeeperNetEx项目开发编译
分布式·zookeeper
Bug退退退1234 小时前
RabbitMQ 工作模式
java·分布式·rabbitmq
weixin_438335404 小时前
分布式锁实现方式:基于Redis的分布式锁实现(Spring Boot + Redis)
数据库·redis·分布式
cui_win7 小时前
【基础】Golang语言开发环境搭建(Linux主机)
linux·golang·运维开发
斯普信专业组9 小时前
K8s环境下基于Nginx WebDAV与TLS/SSL的文件上传下载部署指南
nginx·kubernetes·ssl
危险、9 小时前
RabbitMQ 通过HTTP API删除队列命令
分布式·http·rabbitmq
周某某~9 小时前
windows安装RabbitMQ
分布式·rabbitmq
叹一曲当时只道是寻常10 小时前
Softhub软件下载站实战开发(十):实现图片视频上传下载接口
golang·go·音视频
Bug退退退12310 小时前
RabbitMQ 高级特性之消息确认
java·分布式·rabbitmq