从容器里umount 一个/dev/rbd设备

本文探讨了Docker默认挂载方式MountFlags=slave导致的Kubernetes状态集迁移失败问题,特别是在从一个节点迁移到另一个节点时,由于节点监控工具Node-Exporter无法同步主机上的挂载信息变化,导致StatefulSet迁移失败。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:

  (1) 我们的平台docker默认的挂载方式是MountFlags=slave, 该挂载方式的一个特性是:一旦某个container的以这种方式挂载后启动后,则host节点的信息变动,不会再同步到container里

        (2) 因为节点监控数据采集工具node-exporter, 需要挂载host节点的根目录,若以MountFlags=slave的方式挂载,会导致节点上的mount信息变动,不会同步到node-exporter.

  (3) 其中一个影响是一个statefulset若从节点node-1迁移到node-2,会先umount 该statefulset在node-1上的rbd设备,并mount到node-2上.但结果会报错:

  Warning  FailedMount            25m (x34 over 1h)  kubelet, node-2  Unable to mount volumes for pod "fluentd-0_openstack(b4179bc4-3776-11ea-862b-246e965469a8)": timeout expired waiting for volumes to attach/mount for pod "openstack"/"fluentd-0". list of unattached/unmounted volumes=[storage]

  初步判断是MountFlags=slave的挂载方式问题,即host节点上umount了该rbd设备,但node-exporter的container里的mount信息还在.所以,只需要在该container里umount掉该rbd设备,若该statefulset能够起来,这说明需要修docker默认的挂载方式.

方法:

以下例子中,我们把根目录挂载prometheus-polling-exporter中,statefulset的pod是fluentd, 从节点node-1迁移到node-2

(1) 查看node-1节点没有被mount的rbd设备,即rbd14在host上已经处于umount状态

[root@node-1 ~]# lsblk | grep rbd14
rbd14                                                                                        237:0    0   500G  0 disk 

(2) 进入prometheus-polling-exporter的pod中,查看rbd14状态,还处于mount状态,即host和container不同步

()[root@node-1 /]# mount | grep rbd14
/dev/rbd14 on /host/var/lib/kubelet/plugins/kubernetes.io/rbd/rbd/rbd-image-kubernetes-dynamic-pvc-144d567d-1aaa-11ea-a40d-0a580ae80250 type ext4 (rw,relatime,stripe=1024,data=ordered)

(3) node-1的message信息里报错

Jan 15 17:13:05 node-1 kubelet: E0115 17:13:05.330855   18003 nestedpendingoperations.go:263] Operation for "\"kubernetes.io/rbd/rbd:kubernetes-dynamic-pvc-144d567d-1aaa-11ea-a40d-0a580ae80250\"" failed. No retries permitted until 2020-01-15 17:15:07.330793288 +0800 CST m=+196440.172890846 (durationBeforeRetry 2m2s). Error: "UnmountDevice failed for volume \"pvc-b54ea292-1aa5-11ea-ae82-246e96549cb8\" (UniqueName: \"kubernetes.io/rbd/rbd:kubernetes-dynamic-pvc-144d567d-1aaa-11ea-a40d-0a580ae80250\") on node \"node-1\" : rbd: failed to unmap device /dev/rbd14, error exit status 16, rbd output: rbd: sysfs write failed\nrbd: unmap failed: (16) Device or resource busy\n"

(4) 查看node-1节点上prometheus-polling-exporter的进程号,进程号是40567

[root@node-1 ~]# ps -ef | grep prometheus-polling-exporter
root     40567 40485  0 17:04 ?        00:00:01 prometheus-polling-exporter
root     46498  8212  0 18:28 pts/44   00:00:00 grep --color=auto prometheus-polling-exporter

(5) 通过nsenter命令进入该进程

[root@node-1 ~]# nsenter -t 40567 -m -p
()[root@node-1 /]# 

(6) 查看rbd14的mount信息,并umount,然后t退出

()[root@node-1 /]# mount | grep rbd14
/dev/rbd14 on /host/var/lib/kubelet/plugins/kubernetes.io/rbd/rbd/rbd-image-kubernetes-dynamic-pvc-144d567d-1aaa-11ea-a40d-0a580ae80250 type ext4 (rw,relatime,stripe=1024,data=ordered)
()[root@node-1 /]# umount /host/var/lib/kubelet/plugins/kubernetes.io/rbd/rbd/rbd-image-kubernetes-dynamic-pvc-144d567d-1aaa-11ea-a40d-0a580ae80250
()[root@node-1 /]# exit
logout

(7) 在node-1节点上执行rbd unmap操作

[root@node-1 ~]# rbd unmap /dev/rbd14

flunentd即可正常umount/mount pvc并起来.

### 如何正确卸载 `/dev/sda` 设备 在 Linux 中,要正确卸载 `/dev/sda` 设备及其分区,需要注意以下几点: #### 1. **确认设备是否已挂载** 首先需要检查 `/dev/sda` 的各分区是否已被挂载。可以通过 `df -hT` 命令查看当前系统中所有已挂载的文件系统以及它们对应的挂载点[^3]。 如果发现 `/dev/sda1`, `/dev/sda2` 等分区已经被挂载,则需要分别执行卸载操作。例如: ```bash df -hT | grep sda ``` #### 2. **逐一分区卸载** 对于每一个挂载的分区,使用 `umount` 命令逐一卸载。假设 `/dev/sda1` 被挂载到了 `/mnt/data`,则可以运行如下命令: ```bash umount /mnt/data ``` 同样地,如果存在其他挂载点(如 `/dev/sda2`),也需要对其单独执行卸载操作[^4]。 #### 3. **处理繁忙状态** 若遇到类似于 “device is busy” 的错误消息,可能是因为某些进程正在访问该设备上的数据。此时可借助 `lsof` 或者 `fuser` 工具来定位占用资源的具体进程,并终止这些进程后再尝试卸载。 使用 `fuser` 查找占用情况: ```bash fuser -mv /mnt/data ``` 终止相关进程后重试卸载: ```bash kill <PID> umount /mnt/data ``` #### 4. **完全移除设备** 当所有的子分区都被成功卸载之后,才能安全地断开整个 `/dev/sda` 设备。注意这指的是物理设备而非逻辑卷或单个分区。对于 USB 类型外接存储来说,在完成以上步骤的基础上可以直接拔掉硬件;而对于内部硬盘或者其他特殊场景下的虚拟磁盘,则需进一步确保无任何后台服务依赖此设备[^5]。 #### 示例脚本 下面提供一段简单的 Bash 脚本来自动化检测并卸载指定路径下的所有关联分区: ```bash #!/bin/bash TARGET="/dev/sda" MOUNTS=$(df --output=target | grep "$TARGET") if [[ ! -z $MOUNTS ]]; then echo "Found mounted partitions:" echo "$MOUNTS" read -p "Do you want to unmount these? (y/n): " choice case "$choice" in y|Y ) for mountpoint in $MOUNTS; do echo "Unmounting $mountpoint..." umount "$mountpoint" done ;; n|N ) exit ;; * ) echo "Invalid input";; esac else echo "No active mounts found on ${TARGET}." fi ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值