k8s与存储--flexvolume解读

前言

k8s 非常厉害的地方就在于可扩展性,而存储领域,支持flexvolume 和 csi 两种方式来进行扩展。今天主要讲下flexvolume。FlexVolume 是 Kubernetes v1.8+ 支持的一种存储插件扩展方式。类似于 CNI 插件,它需要外部插件将二进制文件放到预先配置的路径中(如 /usr/libexec/kubernetes/kubelet-plugins/volume/exec/),并需要在系统中安装好所有需要的依赖。可以想到,这是一种out-tree的扩展方式,不需要新增加一种存储插件,去更改k8s的源码。

FlexVolume 接口

官方提供了一些接口,在我们实现自定义存储插件的时候,需要实现部分接口,之所以说部分,主要是看自己的需求。比如我在实现动态hostpath(主机路径包含podid)的时候,就只实现了init和mount和unmount三个接口而已。

FlexVolume 的接口包括

  • init:kubelet/kube-controller-manager 初始化存储插件时调用,插件需要返回是否需要要 attach 和 detach 操作
  • attach:将存储卷挂载到 Node 上
  • detach:将存储卷从 Node 上卸载
  • waitforattach: 等待 attach 操作成功(超时时间为 10 分钟)
  • isattached:检查存储卷是否已经挂载
  • mountdevice:将设备挂载到指定目录中以便后续 bind mount 使用
  • unmountdevice:将设备取消挂载
  • mount:将存储卷挂载到指定目录中
  • umount:将存储卷取消挂载

Driver output

Flexvolume希望驱动程序以下列格式回复操作状态

{
    "status": "",
    "message": "",
    "device": ""
    "volumeName": ""
    "attached": 
    "capabilities": 
    {
        "attach": 
    }
}

与kubelet 的关系

前面讲到自定义的存储插件是放到/usr/libexec/kubernetes/kubelet-plugins/volume/exec/下,具体目录是/usr/libexec/kubernetes/kubelet-plugins/volume/exec//
在pod的spec中申明用到了你自定义的插件后,格式为 /,实际上是kubelet 按照接口规范去调用对应插件。
所以需要注意以下几点:

  • 在debug的过程中,FlexVolume的日志需要在kubelet.log中查看
  • 部署方式一般都是daemonset。这样可以保证每台node 都会存在自定义插件。

从k8s1.8 开始支持了动态插件发现,flexvolume支持动态检测驱动程序的功能。系统运行时,可以安装,升级/降级和卸载驱动程序,而不是在系统初始化时要求驱动程序存在或必须重新启动kubelet或控制器管理器。

官方demo

官方提供一些demo,大家可以参考一下。

如何解决kubelet 经常发生找不到flexvolume 的bug

在实战的过程中,我们的经常在使用自定义插件的时候,出现诸如一下报警:

Unable to mount volumes for pod "hermes-devices-push-myd-79f4577cc9-dqx9v_cbs(a0bc2b86-d140-11e9-9a8e-fa163e4660a0)": timeout expired waiting for volumes to attach or mount for pod "cbs"/"hermes-devices-push-myd-79f4577cc9-dqx9v". list of unmounted volumes=[log-dir]. list of unattached volumes=[log-dir default-token-kf6sr shareit-aksk-aws-conf shareit-aksk-huawei-conf]

其中的log-dir 正是用到了我们的自定义插件。

经过查看kubelet日志,发现,kubelet出现了很多 no volume plugin matched 的错误信息。结合k8s的相关issue和分析kubelet代码发现,这其实是kubelet的一个bug。可惜的是,这个bug一直没有被解决。

当然可以每次发生找不到对应插件的时候,重启kubelet即可。

但终究不是长久之计,通过研究代码,其实动态发现插件的机制是通过inotify实现的,监听了/usr/libexec/kubernetes/kubelet-plugins/volume/exec/目录下的文件变化事件,做对应的处理。所以在有时候我们没法去更改kubelet代码的时候,我们可以在实现自定义插件的时候增加定时refresh的功能。比如我们更改一下对应驱动文件的最后访问时间和修改时间。

你可能感兴趣的:(k8s,kubernetes,golang,storage)