一个恢复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/<pod-uuid>/volumes/<pod-uuid>kubernetes.io~csi/<pvc-name>/mount),然后由kubelet挂载到业务Pod中。

该插件有个问题,就是当CSI插件重启之后,会丢失掉内部负责远程连接s3服务的s3fs进程,因此会导致业务Pod内部挂载目录失效,访问/var/lib/kubelet/pods/<pod-uuid>/volumes/<pod-uuid>kubernetes.io~csi/<pvc-name>/mount目录会出现Transport endpoint is not connected的问题。此时为了让业务Pod能够正常访问,需要重启业务Pod,但这种方式很不优雅。

解决思路

为了解决Transport endpoint is not connected问题,首先需要恢复s3fs进程,但恢复进程依赖几个数据:Pvc的名称、Pod的uid、s3服务的地址以及访问使用的AK/SK等。有两种方式可以保存这类数据:

  1. 在CSI插件正常运行过程中,将元数据保存到s3服务,其实就是将s3服务作为一个元数据库使用。但这种方式可能存在元数据被误删以及元数据和系统不一致的情况
  2. 在CSI插件启动后使用client-go动态获取集群中的相关数据

此次采用了第二种方式,执行思路为:

  1. 获取所有命名空间下的Pvc(allPvcs)
  2. allPvcs中找到Pvc的metadata.annotations.volume.beta.kubernetes.io/storage-provisioner 为目标storageclass的Pvc(targetPvcs)
  3. 获取挂载了上述targetPvcs的pod(targetPods)
  4. 找到targetPods的uid(targetUid)
  5. 拼接挂载路径/var/lib/kubelet/pods/<targetUid>/volumes/<targetUid>kubernetes.io~csi/<targetPvc-name>/mount
  6. 找到targetPvcsspec.storageClassName,进而找出负责该Pvc的storageclass(targetStorageclass)
  7. targetStorageclassparameters找到相关的信息,最主要的是保存访问s3服务的AK/SK的secret(targetSecret)
  8. targetSecret中找到AK/SK
  9. 执行挂载

上述步骤的主要目的就是找出挂载路径以及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一样,执行umountmount即可。但这么做首先要知道Pod映射到主机上的挂载路径,这样就比较麻烦了,因为pod映射到主机上的路径与使用的CRI相关,如果朝这一方向下去,难度比较大,在CSI Volume Plugins in Kubernetes Design Doc中也提过,正常情况下是由kubelet执行的:


  1. 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 UnmountDevice method which is a no-op and returns immediately.
  2. Next kubelet calls the in-tree CSI volume plugin’s unmount (teardown) method, which causes the in-tree volume plugin to issue a NodeUnpublishVolume call via the registered unix domain socket to the local CSI driver. If this call fails from any reason, kubelet re-tries the call periodically.
  3. Upon successful completion of the NodeUnpublishVolume call 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都是同时需要的。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
1月前
|
缓存 网络协议 测试技术
NFS挂载信息如何调整?
NFS挂载信息如何调整?
77 3
|
4月前
|
存储 Kubernetes API
在K8S中,PVC创建和挂载失败原因有哪些?
在K8S中,PVC创建和挂载失败原因有哪些?
|
1月前
|
Linux
如何查看当前的NFS挂载信息?
如何查看当前的NFS挂载信息?
209 2
|
2月前
|
Kubernetes Docker Perl
k8s常见故障--yaml文件检查没有问题 pod起不来(一直处于创建中)
k8s常见故障--yaml文件检查没有问题 pod起不来(一直处于创建中)
127 1
|
2月前
|
Kubernetes Linux 容器
解决删除快照后启动虚拟机显示指定的文件不是虚拟磁盘 打不开磁盘“路径”或它所依赖的某个快照磁盘。 模块“disk”启动失败。 未能启动虚拟
解决删除快照后启动虚拟机显示指定的文件不是虚拟磁盘 打不开磁盘“路径”或它所依赖的某个快照磁盘。 模块“disk”启动失败。 未能启动虚拟
205 0
|
弹性计算 Linux
快照创建的磁盘挂载提示文件系统错误
快照创建的磁盘挂载提示文件系统错误
|
调度 Perl
挂载数据盘当kubelet目录后,kubelet无法执行CSI的UmountDevice操作
当挂载数据盘,并通过shared bind mount 分别挂载到kubelet和containerd目录后,kubelet无法执行CSI的UmountDevice操作
|
网络协议 安全
NFS系统挂载配置解析
NFS系统挂载配置解析
213 0
KUBERNETES05_NFS坏境搭建、PV、PVC挂载目录、ConfigMap挂载文件、Secret挂载敏感信息(二)
KUBERNETES05_NFS坏境搭建、PV、PVC挂载目录、ConfigMap挂载文件、Secret挂载敏感信息(二)
241 0
KUBERNETES05_NFS坏境搭建、PV、PVC挂载目录、ConfigMap挂载文件、Secret挂载敏感信息(二)
|
Kubernetes Docker Perl
KUBERNETES05_NFS坏境搭建、PV、PVC挂载目录、ConfigMap挂载文件、Secret挂载敏感信息(一)
KUBERNETES05_NFS坏境搭建、PV、PVC挂载目录、ConfigMap挂载文件、Secret挂载敏感信息(一)
306 0
KUBERNETES05_NFS坏境搭建、PV、PVC挂载目录、ConfigMap挂载文件、Secret挂载敏感信息(一)