Kubernetes(K8s)_16_CSI
- CSI
- CSI实现
- CSI接口
- CSI插件
CSI
CSI(Container Storage Interface): 实现容器存储的规范
- 本质:
Dynamic Provisioning
、Attach
/Detach
、Mount
/Unmount
等功能的抽象 - CSI功能通过3个
gRPC
暴露服务: IdentityServer、ControllerServer、NodeServer - CSI的实现仅暴露服务, 调用由部署时选择的插件代理(kubelet通过Socket调用服务)
如: CSI架构
CSI实现
CSI实现: CSI功能实现并与组件拼装
- CSI进程需包含3个
gRPC
, 但其部署形式不相同 - CSI功能实现后, 需选择对应的插件进行调用(外部才可使用)
如: CSI注册流程(注册成功后为每个节点创建个CSINode
)
- kubelet通过
fsnotify
监听/var/lib/kubelet/plugins_registry
插件目录 node-driver-registrar
配置节点的CSI运行环境- 根据参数获取CSI的Socket文件, 并调用
GetPluginInfo
方法获取CSI的插件信息 - 插件目录下创建名为
<CSIName>-reg.sock
的Socket
- 根据参数获取CSI的Socket文件, 并调用
- kubelet监听到插件目录下Socket文件创建, 完成CSI注册
- 将监听到新建的Socket信息存储内存中的
desiredStateOfWorld
- 由
Reconciler
协程周期性完成CSI注册(周期性启动)- 每次启动对比
actualStateOfWorld
和desiredStateOfWorld
以获取需处理的CSI - 调用需注册的
node-driver-registrar
的GetInfo
方法获取CSI元数据相关信息 - 基于元数据信息调用CSI的
NodeGetInfo
方法获取节点相关信息 - 根据获取信息通过API Server更新节点的Annotations
- 成功更新节点信息后通过API Server创建/更新
CSINode
- 调用
node-driver-registrar
的NotifyRegistrationStatus
方法通知注册结果
- 每次启动对比
- 将监听到新建的Socket信息存储内存中的
// 注册完成后Reconciler
协程同样周期性对比状态以获取需处理事件(向期望状态收敛)
CSI接口
IdentityServer: 提供插件信息(名称和功能等元数据)
- 与
node-driver-registrar
插件以DaemonSet形式部署在相同Pod内
// https://github1s.com/container-storage-interface/spec/blob/master/lib/go/csi/csi.pb.go#L6251-L6256// IdentityServer
type IdentityServer interface {GetPluginInfo(context.Context, *GetPluginInfoRequest) (*GetPluginInfoResponse, error)GetPluginCapabilities(context.Context, *GetPluginCapabilitiesRequest) (*GetPluginCapabilitiesResponse, error)Probe(context.Context, *ProbeRequest) (*ProbeResponse, error)
}
ControllerServer: 卷的事件处理(集群级别)
- 与
external-XXX
插件以选举Deployment或副本数为1的StatefulSet形式部署在相同Pod内 - 属于有状态服务, 但与部署节点无关
// https://github1s.com/container-storage-interface/spec/blob/master/lib/go/csi/csi.pb.go#L6505-L6521// ControllerServer CSI对应的Controller需实现的API
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)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)ControllerGetVolume(context.Context, *ControllerGetVolumeRequest) (*ControllerGetVolumeResponse, error)ControllerModifyVolume(context.Context, *ControllerModifyVolumeRequest) (*ControllerModifyVolumeResponse, error)
}
NodeServer: 节点存储功能
- 与
node-driver-registrar
插件以DaemonSet形式部署在相同Pod内
// https://github1s.com/container-storage-interface/spec/blob/master/lib/go/csi/csi.pb.go#L7165-L7175// NodeServer 节点存储服务需实现的API
type NodeServer interface {NodeStageVolume(context.Context, *NodeStageVolumeRequest) (*NodeStageVolumeResponse, error)NodeUnstageVolume(context.Context, *NodeUnstageVolumeRequest) (*NodeUnstageVolumeResponse, error)NodePublishVolume(context.Context, *NodePublishVolumeRequest) (*NodePublishVolumeResponse, error)NodeUnpublishVolume(context.Context, *NodeUnpublishVolumeRequest) (*NodeUnpublishVolumeResponse, error)NodeGetVolumeStats(context.Context, *NodeGetVolumeStatsRequest) (*NodeGetVolumeStatsResponse, error)NodeExpandVolume(context.Context, *NodeExpandVolumeRequest) (*NodeExpandVolumeResponse, error)NodeGetCapabilities(context.Context, *NodeGetCapabilitiesRequest) (*NodeGetCapabilitiesResponse, error)NodeGetInfo(context.Context, *NodeGetInfoRequest) (*NodeGetInfoResponse, error)
}
CSI插件
Kubernetes社区维护的常用插件
插件 | 说明 |
---|---|
node-driver-registrar | 注册CSI |
external-provisioner | 调用CSI实现Dynamic Provisioner |
external-attacher | 调用CSI实现Attach /Detach |
external-snapshotter | 调用CSI实现快照 |
external-resizer | 调用CSI实现扩容 |
external-health-monitor | 卷的健康检查 |
- 插件均以
SideCar
形式与CSI部署在相同Pod内 node-driver-registrar
是必需组件, 其他扩展插件可视功能需求选择- 扩展插件通过调用CSI实现功能时, 均是调用CSI中的
ControllerServer