解決K8S中Pod無法正常Mount PVC的問題
今天發現一個Pod一直處于ContainerCreating狀態,通過Describe查看,發現以下錯誤。
- Warning FailedMount 15s kubelet, node-2 MountVolume.WaitForAttach failed for volume "pvc-504feeb6-ae42-45ba-996b-5e8e1039b601" : rbd image kube/kubernetes-dynamic-pvc-bbfd3466-9f2f-11ea-8e91-5a4125e02b87 is still being used
意思就是說該Pod啟動需要掛載PVC,但是這個PVC目前正被使用。可以確定的是除了這個Deployment之外,沒有其他Deployment在使用這個PVC,那這是為什么呢?
我們先來看看如果一個Pod需要掛載卷,在創建Pod的過程中,卷的整個流程如下:(1)第一步是先創建卷 (2)第二步在節點上掛載卷 (3)將卷映射到Pod中
在刪除Pod的時候,卷的卸載過程和上面正好相反。所以初步懷疑是在刪除Pod的時候,原節點由于某些原因從節點上卸載卷失敗,我們來具體排查一下。
1、通過上面Pod的錯誤信息,我們可以獲取到如下有用信息
- rbd image kube/kubernetes-dynamic-pvc-bbfd3466-9f2f-11ea-8e91-5a4125e02b87 is still being used
我們可以從上面的信息獲取到rbd的鏡像信息,拆分如下:
- rbd池:kube
- rbd鏡像:kubernetes-dynamic-pvc-bbfd3466-9f2f-11ea-8e91-5a4125e02b87
2、我們通過ceph命令可以獲取到該鏡像被哪個節點使用,如下:
- # rbd info kube/kubernetes-dynamic-pvc-bbfd3466-9f2f-11ea-8e91-5a4125e02b87
- rbd image 'kubernetes-dynamic-pvc-bbfd3466-9f2f-11ea-8e91-5a4125e02b87':
- size 100 GiB in 25600 objects
- order 22 (4 MiB objects)
- snapshot_count: 0
- id: fb236b8b4567
- block_name_prefix: rbd_data.fb236b8b4567
- format: 2
- features: layering
- op_features:
- flags:
- create_timestamp: Tue May 26 17:03:15 2020
- access_timestamp: Tue May 26 17:03:15 2020
- modify_timestamp: Tue May 26 17:03:15 2020
主要關注block_name_prefix的值。
然后通過以下的命令獲取到具體的節點:
- # rados listwatchers -p kube rbd_header.fb236b8b4567
- watcher=192.168.100.181:0/154937577 client.194364 cookie=18446462598732840971
其中,將從block_name_prefix獲取到的值將rbd_data修改為rbd_header,然后通過以上命令獲取即可。
從上面輸出的信息可以看到這個rbd鏡像被掛載到192.168.100.181主機上,這時候我們需要切換到該主機進行具體的操作。
3、查看具體的文件系統掛載信息
- ls /dev/rbd/kube/kubernetes-dynamic-pvc-bbfd3466-9f2f-11ea-8e91-5a4125e02b87 -l
- lrwxrwxrwx 1 root root 11 7月 27 09:04 /dev/rbd/kube/kubernetes-dynamic-pvc-bbfd3466-9f2f-11ea-8e91-5a4125e02b87 -> ../../rbd4
可以看到這個rbd鏡像被掛載到/dev/rbd4上,我們可以直接通過rbd unmap命令卸載,如下:
- # rbd unmap /dev/rbd4
不過我這里并沒有這么容易,當我在卸載的時候報如下錯誤。
- # rbd unmap /dev/rbd4
- rbd: sysfs write failed
- rbd: unmap failed: (16) Device or resource busy
一看到這個問題,就想到有時候在umount的時候,也會遇到Device busy,所以第一反應是使用lsof,看是否能找到哪個進程占用了,如下:
- # lsof 2>/dev/null | grep rbd4
但是我并沒有找到任何進程,二臉懵逼.....
最后只有瘋狂百度了,找到了兩種解決方式。(1)通過rbd unmap -o force進行強制卸載 (2)通過grep 'rbd4' /proc/*/task/*/mountinfo來查找進程PID
當把這個rbd鏡像從原節點卸載過后,就可以看到Pod可以正常啟動了。
寫在最后
由于我是使用的Deployment來管理的有狀態應用,正常使用StatefulSet不會出現這種問題,那使用Deployment該如何避免這種問題呢?
- 使用ReadWriteMany訪問模式的pvc
- 將maxSurge設置為0,避免在更新過程中產生多余的pod
這兩種方式都有利有弊,具體情況需要使用者去權衡。
本文轉載自微信公眾號「運維開發故事」,可以通過以下二維碼關注。轉載本文請聯系運維開發故事公眾號。