K8s (3) CSI and Volume

CSI

Container Storage Interface (CSI)是一项规定存储供应商如何来提供存储服务作为Plugin,可以同时被多个Container Orchestration (CO)系统接受的接口标准。

目前接受CSI的CO有K8s,Mesos,Cloudfoundary。CSI的标准和Protobuf接口代码位于github的这里

生成的plugin可以灵活部署。分为controller plugin和node plugin两部分。既可以分别部署在master和普通node上,也可以单独部署controller plugin和node plugin。其中controller plugin是用来做管理的比如创建/删除,attach/detach。node plugin是运行在每个节点上的,特别是在使用storage的节点上必须安装。

headless plugin.
"headless"这个词用在Computer science的context是指缺少一部分,特别是图像显示的部分。比如命令行的mode。参见

这里用headless的意思是master node上就不安装插件了,完全是在node节点上运行,controller和node plugin可以分开来运行,也可以合一来运行,也可以单单运行node plugin。因为没有master,所以没有了。无头指挥。

Spec里的状态机如下。

Controller.createVolume() => CREATED => Controller.publishVolume() => NODE_READY => Node.stageVolume() => VOL_READY => Node.publishVolume() => PUBLISHED

首先是Controller把Volume的状态改变成对某些节点available。然后是node接收,把这个Volume变成在本节点可使用。

API interface

CO ------------ gRPC ---------- plugin (Indentity service, controller service, and node service)

service Identity {
  rpc GetPluginInfo(GetPluginInfoRequest)
    returns (GetPluginInfoResponse) {}

  rpc GetPluginCapabilities(GetPluginCapabilitiesRequest)
    returns (GetPluginCapabilitiesResponse) {}    // 这里会拿到feature,比如是否支持online volume expansion,是否VOLUME被cluster内的所有节点

  rpc Probe (ProbeRequest)
    returns (ProbeResponse) {}  // 类似于Ping,report初始化是否ready
}

service Controller {
  rpc CreateVolume (CreateVolumeRequest)  // 提出各种需求比如,capacity,topology, etc
    returns (CreateVolumeResponse) {} // 返回创建的volume

  rpc DeleteVolume (DeleteVolumeRequest)
    returns (DeleteVolumeResponse) {}

  rpc ControllerPublishVolume (ControllerPublishVolumeRequest)
    returns (ControllerPublishVolumeResponse) {}   // 使这个Volume在指定node上available

  rpc ControllerUnpublishVolume (ControllerUnpublishVolumeRequest)
    returns (ControllerUnpublishVolumeResponse) {}

  rpc ValidateVolumeCapabilities (ValidateVolumeCapabilitiesRequest)
    returns (ValidateVolumeCapabilitiesResponse) {}

  rpc ListVolumes (ListVolumesRequest)
    returns (ListVolumesResponse) {}  // 返回volume entries

  rpc GetCapacity (GetCapacityRequest)
    returns (GetCapacityResponse) {}

  rpc ControllerGetCapabilities (ControllerGetCapabilitiesRequest)
    returns (ControllerGetCapabilitiesResponse) {}

  rpc CreateSnapshot (CreateSnapshotRequest)
    returns (CreateSnapshotResponse) {} // 打快照,返回快照信息

  rpc DeleteSnapshot (DeleteSnapshotRequest)
    returns (DeleteSnapshotResponse) {}

  rpc ListSnapshots (ListSnapshotsRequest)
    returns (ListSnapshotsResponse) {}

  rpc ControllerExpandVolume (ControllerExpandVolumeRequest)
    returns (ControllerExpandVolumeResponse) {}
}

service Node {
  rpc NodeStageVolume (NodeStageVolumeRequest) // 提供Volume要被stage的path
    returns (NodeStageVolumeResponse) {}

  rpc NodeUnstageVolume (NodeUnstageVolumeRequest)
    returns (NodeUnstageVolumeResponse) {}

  rpc NodePublishVolume (NodePublishVolumeRequest)  // 当负载需要使用volume的时候,CO会call它。access mode会决定是不是多个NODE共享volume
    returns (NodePublishVolumeResponse) {}

  rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest)
    returns (NodeUnpublishVolumeResponse) {}

  rpc NodeGetVolumeStats (NodeGetVolumeStatsRequest)
    returns (NodeGetVolumeStatsResponse) {}


  rpc NodeExpandVolume(NodeExpandVolumeRequest)
    returns (NodeExpandVolumeResponse) {}


  rpc NodeGetCapabilities (NodeGetCapabilitiesRequest)
    returns (NodeGetCapabilitiesResponse) {}

  rpc NodeGetInfo (NodeGetInfoRequest)
    returns (NodeGetInfoResponse) {}
}

可以看到这里功能分层还是比较明显的。分controller和node实现了上面说的状态机。

Volume and PV/PV claim

Volume

K8s支持不同TYPE的Volume,比如FC,Iscsi,cephfs,nfs,azureDisk,azureFile。
所以包含了FS和BLOCK。

也有基于公司的,portworxVolume,scaleIO,storageos

特殊的几个:csi 前面刚刚提到的, downwardAPI (expose metadata via a file interface),persistentVolumeClaim

Volume的生命周期和POD一样。定义 POD的时候可以定义Volume。

注意K8s利用Volume概念克服了Container crash的问题。Volume的生命周期与Container不同。

PV/PV Claim

PV是独立于POD生命周期之外的存储资源,是K8s集群的系统资源,所以称之为Persistent。PVC是使用这些资源的请求。

PV可以在使用PVC的时候被动态provisioned,就像malloc。PVC需要指定StorageClass, which consists of

通过定义下面几项,StorageClass具体定义了某种存储,就是declare一个StorageClass Object

  • matadata.name // 这个是KEY
  • provisioner
  • parameters.type

一个K8s官方的例子

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
mountOptions:
  - debug
volumeBindingMode: Immediate

PVC需要声明使用者的意图,所以需要引用已经定义好的StorageClass Object。

PVC:

  • spec.resources.requests.storage // 需要多大 capacity, 比如10Gi
  • spec.storageClassName // 什么样的存储

前面说的每个TYPE都要提供自己的StorageClass说明,才能被PVC使用。

PV也类似,但是直接定义卷

  • spec.capacity.storage

CSI综合使用

就像上面Kubernetes官方文档显示的定义一个provisioner for AWS的EBS卷一样。要使用CSI, type CSI也要定义自己的StorageClass。

与Docker Volume的不同

Docker把K8s里面的TYPE,叫做DRIVER。根据这篇文章, K8s先搞出Volume这个概念。

比如REX-ray就是Container的DRIVER概念。是Docker的一个plugin。REX-Ray是Vendor neutral的。

Docker/Docker Swarm的Volume概念比K8s要简单,没有生命周期的管理,没有动态分配。也许我不知道而已。

如果你两套机制都用的话,可以用K8s的declare来overwrite Docker definition。见Stackoverflow文章

你可能感兴趣的:(introduction)