一个恢复CSI挂载信息的解决方法
一个恢复CSI挂载信息的解决方法
问题描述
之前有做过一个华为OBS 的CSI插件,其基本运作原理如下图所示。CSI插件Pod挂载了主机的/var/lib/kubelet/pods目录,当创建挂载Pvc的业务Pod时,CSI插件会启动一个s3fs进程,该进程用于远程连接s3服务,将bucket(也即Pvc)挂载到/var/lib/kubelet/pods中的对应Pod目录下(一般为/var/lib/kubelet/pods//volumes/kubernetes.io~csi//mount),然后由kubelet挂载到业务Pod中。

该插件有个问题,就是当CSI插件重启之后,会丢失调内部负责远程连接s3服务的s3fs进程,因此会导致业务Pod内部挂载目录失效,访问/var/lib/kubelet/pods//volumes/kubernetes.io~csi//mount目录会出现Transport endpoint is not connected的问题。此时为了让业务Pod能够正常访问,需要重启业务Pod,但这种方式很不优雅。
解决思路
为了解决Transport endpoint is not connected问题,首先需要恢复s3fs进程,但恢复进程依赖几个数据:Pvc的名称、Pod的uid、s3服务的地址以及访问使用的AK/SK等。有两种方式可以保存这类数据:
- 在CSI插件正常运行过程中,将元数据保存到s3服务,其实就是将s3服务作为一个元数据库使用。但这种方式可能存在元数据被误删以及元数据和系统不一致的情况
- 在CSI插件启动后使用client-go动态获取集群中的相关数据
此次采用了第二种方式,执行思路为:
- 获取所有命名空间下的Pvc(
allPvcs) - 从
allPvcs中找到Pvc的metadata.annotations.volume.beta.kubernetes.io/storage-provisioner 为目标storageclass的Pvc(targetPvcs) - 获取挂载了上述
targetPvcs的pod(targetPods) - 找到
targetPods的uid(targetUid) - 拼接挂载路径
/var/lib/kubelet/pods/<targetUid>/volumes/<targetUid>kubernetes.io~csi/<targetPvc-name>/mount - 找到
targetPvcs的spec.storageClassName,进而找出负责该Pvc的storageclass(targetStorageclass) - 在
targetStorageclass的parameters找到相关的信息,最主要的是保存访问s3服务的AK/SK的secret(targetSecret) - 从
targetSecret中找到AK/SK - 执行挂载
上述步骤的主要目的就是找出挂载路径以及s3服务的访问信息。
实施过程
在完成编码之后,经验证发现/var/lib/kubelet/pods/<targetUid>/volumes/<targetUid>kubernetes.io~csi/<targetPvc-name>/mount挂载成功,进入该目录之后可以看到bucket中的内容,但进入业务容器发现,目录并没有成功挂载。
需要提出的一点是,由于CSI插件是被异常重启的,导致挂载失效,并没有执行标准的Unmounting 流程(即调用
NodeUnpublishVolume方法),因此在重新挂载之前首先需要umount掉原来的挂载点。
业务容器没有挂载成功的原因是整个恢复流程并没有触发kubelet执行umount/mount来将pvc重新挂载到业务容器。解决方式与CSI插件的/var/lib/kubelet/pods/<targetUid>/volumes/<targetUid>kubernetes.io~csi/<targetPvc-name>/mount一样,执行umount在mount即可。但这么做首先要知道Pod映射到主机上的挂载路径,这样就比较麻烦了,因为pod映射到主机上的路径与使用的CRI相关,如果朝这一方向下去,难度比较大,在CSI Volume Plugins in Kubernetes Design Doc中也提过,正常情况下是由kubelet执行的:
- The volume manager component of kubelet, notices a mounted CSI volume, referenced by a pod that has been deleted or terminated, so it calls the in-tree CSI volume plugin’s
UnmountDevicemethod which is a no-op and returns immediately.- Next kubelet calls the in-tree CSI volume plugin’s unmount (teardown) method, which causes the in-tree volume plugin to issue a
NodeUnpublishVolumecall via the registered unix domain socket to the local CSI driver. If this call fails from any reason, kubelet re-tries the call periodically.- Upon successful completion of the
NodeUnpublishVolumecall the specified path is unmounted from the pod container.
那么怎么才能让容器重新挂载成功呢?
只要重新触发kubelet的挂载动作即可,可以采用livenessProbe来触发该动作,方式如下:
apiVersion: v1
kind: Pod
metadata:
name: csi-s3-test-nginx
namespace: default
spec:
containers:
- name: csi-s3-test-nginx
image: nginx
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 5
exec:
command:
- ls
- /var/lib/www/html
volumeMounts:
- mountPath: /var/lib/www/html
name: webroot
- mountPath: /var/lib/www/html2
name: webroot2
volumes:
- name: webroot
persistentVolumeClaim:
claimName: csi-s3-pvc
readOnly: false
- name: webroot2
persistentVolumeClaim:
claimName: csi-s3-pvc2
readOnly: false
如果使用这种方式的话,还需要执行之前恢复s3fs进程的操作吗?答案是需要的,重启只会触发kubelet的动作,但不会触发CSI重新挂载,因此恢复s3fs进程和livenessProbe都是同时需要的。
一个恢复CSI挂载信息的解决方法的更多相关文章
- windows8 8.1 安装完 ubuntu无法挂载 ntfs分区 解决方法
windows8 8.1 安装完 ubuntu无法挂载 ntfs分区 解决方法: 最近安装完发现8.1系统后,ubuntu无法加载以前的ntfs分区了,特别是我添加到了/etc/fstab里面了 导致 ...
- log4j中Spring控制台输出Debug级信息过多解决方法
log4j中Spring控制台输出Debug级信息过多解决方法 >>>>>>>>>>>>>>>>> ...
- ortoiseSVN无法编辑日志信息的解决方法
提交时忘记编写日志,想重新编辑日志信息,弹出错误提示: DAV 请求失败:可能是版本库的 pre-revprop-change 钩子执行失败或者不存在 至少有一个属性变更失败:版本库未改变 设置属性 ...
- UiPath中恢复依赖项失败的解决方法
目录 序言 正文 什么是依赖包? 如何查看项目使用了哪些版本的依赖包? 一.项目内查看 二.查看项目的 JSON 文件 问题根源 解决方法 一.「等」字诀 二.切换网络环境(根治) 三.手动复制依赖包 ...
- nfs文件系统挂载错误及解决方法
挂载nfs时出现如下错误: 原因: 没有安装nfs客户端相关 解决方法: apt-get install nfs-common 参考资料: http://askubuntu.com/questions ...
- win10想说爱你不容易——安装.net3.5也是一个坑(已有完美解决方法)
最终完美解决方法:经过多次波折,终于找到无法正常安装.net3.5的原因了,是因为已删除的用户还有注册表残留导致的,而且这个问题还会影响一个win10更新的安装,导致每天更新失败,撤销更新... 详见 ...
- CentOS编译PHP过程中常见错误信息的解决方法
原文链接:http://www.linuxidc.com/Linux/2014-05/102327.htm ********************************************** ...
- vue.js常见的报错信息及其解决方法的记录
1.Vue packages version mismatch 翻译:vue包版本匹配错误 报错样例: 报错原因:通常出现于一些依赖库的更新或者安装新的依赖库之后(可以认为npm update已经成为 ...
- 入坑Intel OpenVINO:记录一个示例出错的原因和解决方法
今天试用OpenVINO的例子,在过程中发现了一些其他人没有经历的坑特别记录一下. 出错时候:执行Intel OpenVINO示例的是时候,出错的提示代码: 用于 .NET Framework 的 M ...
随机推荐
- 【Python】Python基础知识【第一版】
变量 print("-------------输出语句-------------"); message="Hello Python world"; print( ...
- DOM节点详解
@ 目录 学习总结 1. 什么是 DOM 2. HTMLDOM 3. 元素获取 元素获取方式: 元素节点的属性操作 4. Node 对象的属性和方法 常用属性 常用方法 5. 事件处理 事件驱动编程 ...
- input禁止输入空格 以及 input各种输入限制
1.禁止输入空格 方法1: oninput="value=value.replace(/\s+/g,'')" 在 ios中 用手机原生键盘 输入 会出现bug, 就是 ...
- Taro时间选择器+地址选择器
时间地址选择器 https://www.manzj.net/topic/5c3c2123cd01b8af5bce4373
- 利用css3渐变效果实现圆环旋转效果
* { margin: 0; padding: 0; } .stage { width: 200px; height: 130px; margin: 100px auto; position: rel ...
- OllyDbg---寄存器
寄存器 寄存器的概念和作用 寄存器是CPU内部的高速存储单元,访问速度比常规内存快很多. 处理器在执行程序时,需要一个助手,当执行一条指令时,比如将两个内存单元中存放的内容相加,处理器需要先把其中一个 ...
- python---运算符和编码
格式化输出 在输出数据时,会有用户需要输入的信息被输出,没办法预先知道,这就需要使用格式化输出.先在相应位置放置一个占位符,再把字符串里的占位符与外部的变量做个映射关系. name = input(& ...
- Spring配置文件-Bean实例化的三种方式
1.无参构造方法实例化(详见我的博客) 2.工厂静态方法实例化 创建StaticFactory类 public class StaticFactory { public static UserDao ...
- mysql4与mysql5的区别_MySQL 4.1/5.0/5.1/5.5/5.6各版本的主要区别
MySQL 4.1/5.0/5.1/5.5/5.6各版本的主要区别 一.5.0 增加了Stored procedures.Views.Cursors.Triggers.XA transactions的 ...
- Spring基于注解自动装配
前面我们介绍Spring IoC装载的时候,使用XML配置这种方法来装配Bean,这种方法可以很直观的看到每个Bean的依赖,但缺点也很明显:写起来非常繁琐,每增加一个组件,就必须把新的Bean配置到 ...