深入剖析 Kubernetes
张磊
Kubernetes 社区资深成员与项目维护者
113629 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 57 讲
再谈开源与社区 (1讲)
结束语 (1讲)
深入剖析 Kubernetes
15
15
1.0x
00:00/00:00
登录|注册

30 | 编写自己的存储插件:FlexVolume与CSI

你好,我是张磊。今天我和你分享的主题是:编写自己的存储插件之 FlexVolume 与 CSI。
在上一篇文章中,我为你详细介绍了 Kubernetes 里的持久化存储体系,讲解了 PV 和 PVC 的具体实现原理,并提到了这样的设计实际上是出于对整个存储体系的可扩展性的考虑。
而在今天这篇文章中,我就和你分享一下如何借助这些机制,来开发自己的存储插件。
在 Kubernetes 中,存储插件的开发有两种方式:FlexVolume 和 CSI。
接下来,我就先为你剖析一下Flexvolume 的原理和使用方法
举个例子,现在我们要编写的是一个使用 NFS 实现的 FlexVolume 插件。
对于一个 FlexVolume 类型的 PV 来说,它的 YAML 文件如下所示:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-flex-nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
flexVolume:
driver: "k8s/nfs"
fsType: "nfs"
options:
server: "10.10.0.25" # 改成你自己的NFS服务器地址
share: "export"
可以看到,这个 PV 定义的 Volume 类型是 flexVolume。并且,我们指定了这个 Volume 的 driver 叫作 k8s/nfs。这个名字很重要,我后面马上会为你解释它的含义。
而 Volume 的 options 字段,则是一个自定义字段。也就是说,它的类型,其实是 map[string]string。所以,你可以在这一部分自由地加上你想要定义的参数。
在我们这个例子里,options 字段指定了 NFS 服务器的地址(server: “10.10.0.25”),以及 NFS 共享目录的名字(share: “export”)。当然,你这里定义的所有参数,后面都会被 FlexVolume 拿到。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入剖析 Kubernetes》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(16)

  • 最新
  • 精选
  • 陆培尔
    老师的课讲得太好了,什么时候开始讲容器网络方面的内容?感觉这一块一直有很多地方搞不明白,service,ingress,lb,跨节点组网等等

    作者回复: 很快

  • 虎虎❤️
    思考题: 1. Register过程: csi 插件应该作为 daemonSet 部署到每个节点(node)。然后插件 container 挂载 hostpath 文件夹,把插件可执行文件放在其中,并启动rpc服务(identity, controller, node)。External component Driver Registrar 利用 kubelet plugin watcher 特性watch指定的文件夹路径来自动检测到这个存储插件。然后通过调用identity rpc服务,获得driver的信息,并完成注册。 2. Provision过程:部署External Provisioner。 Provisioner 将会 watch apiServer 中 PVC 资源的创建,并且PVC 所指定的 storageClass 的 provisioner是我们上面启动的插件。那么,External Provisioner 将会调用 插件的 controller.createVolume() 服务。其主要工作应该是通过阿里云的api 创建网络磁盘,并根据磁盘的信息创建相应的pv。 3. Attach过程:部署External Attacher。Attacher 将会监听 apiServer 中 VolumeAttachment 对象的变化。一旦出现新的VolumeAttachment,Attacher 会调用插件的 controller.ControllerPublish() 服务。其主要工作是调用阿里云的api,把相应的磁盘 attach 到声明使用此 PVC/PV 的 pod 所调度到的 node 上。挂载的目录:/var/lib/kubelet/pods/<Pod ID>/volumes/aliyun~netdisk/<name> 4. Mount过程:mount 不可能在远程的container里完成,所以这个工作需要kubelet来做。kubelet 的 VolumeManagerReconciler 控制循环,检测到需要执行 Mount 操作的时候,通过调用 pkg/volume/csi 包,调用 CSI Node 服务,完成 volume 的 Mount 阶段。具体工作是调用 CRI 启动带有 volume 参数的container,把上阶段准备好的磁盘 mount 到 container指定的目录。
    2
    151
  • ch_ort
    PVC描述的,是Pod想要使用的持久化存储的属性,比如存储的大小、读写权限等 PV描述的,则是一个具体的Volume的属性,比如Volume的类型、挂载目录、远程存储服务器地址等 有两种管理PV的方式: 人工管理(Static Provisioning),自动创建(Dynamic Provisioning)。Dynamic Provisioning机制工作的核心,就在于一个名叫StorageClass的API对象。Kubernetes能够根据用户提交的PVC,找到一个对应的StorageClass了。然后,Kuberentes就会调用该StorageClass声明的存储插件,创建出需要的PV。 需要注意的是,StorageClass并不是专门为了Dynamic Provisioning而设计的。比如,我在PV和PVC里都声明了storageClassName=manual。而我的集群里,实际上并没有一个叫manual的StorageClass对象。这完全没有问题,这个时候Kubernetes进行的是Static Provisioning,但在做绑定决策的时候,它依然会考虑PV和PVC的StorageClass定义。而这么做的好处也很明显:这个PVC和PV的绑定关系,就完全在我自己的掌握之中。 存储插件的开发方式有两种:FlexVolume和CSI FlexVolume: kubelet --> pkg/volume/flexvolume.SetUpAt() --> /usr/libexec/kubernetes/kubelet-plugins/volume/exec/k8s~nfs/nfs mount <mount dir> <json param> FlexVolume的方式,需要手动先创建好PV,由FlexVolume来执行Attach和Mount操作。 相比于 FlexVolume,CSI 的设计思想是把插件的职责从“两阶段处理”,扩展成了 Provision、Attach 和 Mount 三个阶段。其中,Provision 等价于“创建磁盘”,Attach 等价于“挂载磁盘到虚拟机”,Mount 等价于“将该磁盘格式化后,挂载在 Volume 的宿主机目录上”。
    16
  • Geek_5baa01
    Provision:调用阿里云 API Create 云盘 Attach: 调用阿里云 API 挂载云盘到 ECS Mount: 挂载云盘到对应的 pod volume 目录
    10
  • silver
    'test 正是我们前面定义的 PV 的名字',这个是否是typo?PV的名字是pv-flex-nfs?
    10
  • kakj
    java程序员从入门到放弃到再入门到再放弃中
    4
    6
  • leo
    厉害了 新的知识!
    2
  • vincent
    简单说是两阶段: attach + mount 细了说:1、创建卷资源 2、attach节点 3、node上创建设备格式化 4、挂在设备
    1
  • 虎虎❤️
    问题: 1. 既然csi的PV是自己定义的类型,那么volume controller应该不会做这个红娘吧?所以问题是,他们是怎么完成绑定的?绑定后的状态会改变为 bound 吗? 2. 按照我的理解 driver 插件应该安装到每个node上,那么适合使用 daemonSet 去部署插件和 Driver Registerar sidecar。而 External Provisioner/Attacher 则只需要一份部署就可以。为什么文中建议把三个 External components 都部署为sidecar?
    1
  • guolisen
    kubelet为什么会知道 对应的可执行程序叫做nfs(k8s~nfs/nfs)?是在哪里告诉kubelet的?
    归属地:北京
收起评论
显示
设置
留言
16
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部