kubernetes CSI

容器存储接口(CSI)是用于将任意块和文件存储系统暴露给诸如Kubernetes之类的容器编排系统(CO)上的容器化工作负载的标准。使用CSI的第三方存储提供商可以编写和部署在Kubernetes中公开新存储系统的插件,而无需接触核心的Kubernetes代码

CSI实现中的组件分为两部分:

  • 各云厂商or开发者自行开发的组件(需要实现CSI Identity,CSI Controller,CSI Node RPC接口)
  • 由k8s官方维护的一系列external组件负责注册CSI driver 或监听k8s对象资源,从而发起csi driver调用,比如(node-driver-registrar,external-attacher,external-provisioner,external-resizer,external-snapshotter,livenessprobe)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# node-driver-registrar
CSI node-driver-registrar是一个sidecar容器,可从CSI driver获取驱动程序信息(使用NodeGetInfo),并使用kubelet插件注册机制在该节点上的kubelet中对其进行注册。

# external-attacher
它是一个sidecar容器,用于监视Kubernetes VolumeAttachment对象并针对驱动程序端点触发CSI ControllerPublish和ControllerUnpublish操作

# external-provisioner
它是一个sidecar容器,用于监视Kubernetes PersistentVolumeClaim对象并针对驱动程序端点触发CSI CreateVolume和DeleteVolume操作。external-attacher还支持快照数据源。如果将快照CRD资源指定为PVC对象上的数据源,则此sidecar容器通过获取SnapshotContent对象获取有关快照的信息,并填充数据源字段,该字段向存储系统指示应使用指定的快照填充新卷

# external-resizer
它是一个sidecar容器,用于监视Kubernetes API服务器上的PersistentVolumeClaim对象的改动,如果用户请求在PersistentVolumeClaim对象上请求更多存储,则会针对CSI端点触发ControllerExpandVolume操作。

# external-snapshotter
它是一个sidecar容器,用于监视Kubernetes API服务器上的VolumeSnapshot和VolumeSnapshotContent CRD对象。创建新的VolumeSnapshot对象(引用与此驱动程序对应的SnapshotClass CRD对象)将导致sidecar容器提供新的快照。该Sidecar侦听指示成功创建VolumeSnapshot的服务,并立即创建VolumeSnapshotContent资源。

# livenessprobe
它是一个sidecar容器,用于监视CSI驱动程序的运行状况,并通过Liveness Probe机制将其报告给Kubernetes。这使Kubernetes能够自动检测驱动程序问题并重新启动Pod以尝试解决问题。

volume从创建到要被使用经过了以下流程:

  • volume创建
  • volume attach到节点
  • volume 被mount到指定目录(这个目录其实就被映射到容器中,由kubelet中的 VolumeManager 调用)

CSI中Capabilities会标识出来此插件提供哪些能力:

  • IdentityServer中的GetPluginCapabilities方法
  • ControllerServer中的ControllerGetCapabilities方法
  • NodeServer中的NodeGetCapabilities

csi-driver-host-path

利用本地存储来实现kubernets CSI接口,核心代码文件在源代码的pkg目录下

hostpat插件的identityserver.go告诉我们插件主要提供了ControllerService的能力,以及volume访问限制的能力
ControllerServer.go主要关注CreateVolume,DeleteVolume,因为是hostpath volume,所以就没有attach的这个过程
在nodeServer.go中就是实现mount,unmount过程了,分别对应NodePublishVolume和NodeUnpublishVolume

运行本地测试

在源代码目录下直接执行make命令 就会在bin目录下创建可执行的静态二进制文件
也可以通过go build -o ./bin/hostpathplugin2 ./cmd/hostpathplugin 命令来直接编译程序

下面通过官方提供的测试CSI接口工具来测试应用(获取CSC工具:GO111MODULE=off go get -u github.com/rexray/gocsi/csc)
遇到不理解或者不符合预期结果的情况下,推荐打断点Debug的方式来观察代码如何处理请求的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 启动服务 
# -V 5 表示level5以下级别的日志都会输出,方便观察应用运行情况
sudo ./hostpathplugin --nodeid l12h1 --endpoint tcp://127.0.0.1:10000 -v 5

# 获取Node info
./csc node get-info --endpoint tcp://127.0.0.1:10000
l12h1 0 &csi.Topology{Segments:map[string]string{"topology.hostpath.csi/node":"l12h1"}, XXX_NoUnkeyedLiteral:struct {}{}, XXX_unrecognized:[]uint8(nil), XXX_sizecache:0}

# 查询CSI 插件信息
./csc identity plugin-info --endpoint tcp://127.0.0.1:10000
"hostpath.csi.k8s.io" "dev"

# 创建block volume 容量1M
./csc controller new --endpoint tcp://127.0.0.1:10000 --cap 1,block testVolume --req-bytes 1048576
"4f4a73f5-6136-11eb-8f7f-f079590e27d2" 1048576
# 创建mount volume 容量1M
./csc controller new --endpoint tcp://127.0.0.1:10000 --cap MULTI_NODE_MULTI_WRITER,mount,xfs,uid=500,gid=500 testVolume --req-bytes 1048576
"4f9f8d26-613b-11eb-8f7f-f079590e27d2" 1048576

# 判断存储是否存在
./csc controller validate-volume-capabilities --endpoint tcp://127.0.0.1:10000 --cap 1,block 4f4a73f5-6136-11eb-8f7f-f079590e27d2
"4f4a73f5-6136-11eb-8f7f-f079590e27d2" volume_capabilities:<block:<> access_mode:<mode:SINGLE_NODE_WRITER > >
./csc controller validate-volume-capabilities --endpoint tcp://127.0.0.1:10000 --cap MULTI_NODE_MULTI_WRITER,mount,xfs,uid=500,gid=500 4f9f8d26-613b-11eb-8f7f-f079590e27d2
"4f9f8d26-613b-11eb-8f7f-f079590e27d2" volume_capabilities:<mount:<fs_type:"xfs" mount_flags:"uid=500" mount_flags:"gid=500" > access_mode:<mode:MULTI_NODE_MULTI_WRITER > >

# 挂载volume
./csc node publish --endpoint tcp://127.0.0.1:10000 --cap 1,block --target-path /mnt/hostpath 4f4a73f5-6136-11eb-8f7f-f079590e27d2
4f4a73f5-6136-11eb-8f7f-f079590e27d2
## 到 /mnt/目录下可以看到挂载的设备
brw-rw---- 1 root disk 7, 1 1月 28 14:59 hostpath
# 挂载mount volume
./csc node publish --endpoint tcp://127.0.0.1:10000 --cap MULTI_NODE_MULTI_WRITER,mount,xfs,uid=500,gid=500 --target-path /mnt/hostpath 4f9f8d26-613b-11eb-8f7f-f079590e27d2
## 到 /mnt/目录下可以看到挂载的目录
drwxr-xr-x 2 root root 4.0K 1月 28 16:03 hostpath

# 取消挂载volume
./csc node unpublish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/hostpath 4f4a73f5-6136-11eb-8f7f-f079590e27d2
4f4a73f5-6136-11eb-8f7f-f079590e27d2
./csc node unpublish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/hostpath 4f9f8d26-613b-11eb-8f7f-f079590e27d2
## 到 /mnt/目录下可以看到挂载的设备已经被删除

# 删除volume
./csc controller del --endpoint tcp://127.0.0.1:10000 4f4a73f5-6136-11eb-8f7f-f079590e27d2
4f4a73f5-6136-11eb-8f7f-f079590e27d2
./csc controller del --endpoint tcp://127.0.0.1:10000 4f9f8d26-613b-11eb-8f7f-f079590e27d2
## 到/csi-data-dir目录可以看到4f4a73f5-6136-11eb-8f7f-f079590e27d2 和 4f9f8d26-613b-11eb-8f7f-f079590e27d2已经被删除

csi-driver-nfs

利用NFS存储来实现kubernets CSI接口,核心代码文件在源代码的pkg目录下

csi-driver-iscsi

官方推出的实现CSI接口模板项目

参考

https://mp.weixin.qq.com/s/mya3BfH9yIrkXrdXoSUIRQ