Pod挂载Volume失败问题分析
Kubernetes環境偶爾出現StatefulSet中的Pod被刪除,新啟動的Pod(還是調度到原有節點)掛載volume失敗的問題,如下圖,經過一番定位分析,也讓我們對于Kubernetes系統復雜程度有了新的認知。
在分析此問題之前,作為相關背景知識,先簡單介紹對于Kubernetes存儲系統的理解。
|? 存儲系統簡析
存儲也是Kubernetes中比較重要而復雜的系統,功能比較龐大,涉及到不同組件中,不同控制器的協作,如下圖。
1、從卷的生命周期來講,卷被Pod使用或者卷被回收,會依賴順序嚴格的幾個階段
卷被Pod使用:
-
provision,卷分配成功
-
attach,卷掛載在對應worker node
-
mount,卷掛載為文件系統并且映射給對應Pod
卷被回收:
-
umount,卷已經和對應worker node解除映射,且已經從文件系統umount
-
detach,卷已經從worker node卸載
-
recycle,卷被回收
2、從Kubernetes存儲系統來講,卷生命周期管理的職責,又分散于不同的控制器中
-
pv controller,負責創建和回收卷
-
attach detach controller,負責掛載和卸載卷
-
volume manager,負責mount和umount卷
比如attach detach controller和volume manager中,各自都會有desiredStateOfWorld(緩存期望狀態)和actualStateOfWorld(緩存實際狀態)緩存,并且由各自的syncLoopFunc不斷對比兩個緩存的差異,并進行調整,下文中會介紹。
for?{desired?:=?getDesiredState();current?:=?getCurrentState();makeChanges(desired,?current); }
結合以上三個維度,Kubernetes需要保證卷的管理功能分布在不同控制器的前提下保證卷生命周期順序的正確性。以Pod使用卷為例,看Kubernetes是如何做到這一點?
|? Pod啟動流程
假設scheduler已經完成worker node選擇,確定調度的節點,此時啟動Pod前,需要先完成卷映射到Pod路徑中,結合前面的分析,整個過程如下:
1、卷分配,pvc綁定pv,由pv controller負責完成,結合相關代碼1[1]。
此時pvc綁定pv。
2、attach detach controlle,如果pod分配到worker node,并且對應卷已經創建,則將卷掛載到對應worker node,并且給worker node資源增加volume已經掛載對應卷的狀態信息,結合相關代碼2[2]和代碼3[3]。
此時對應node資源狀態中增加volume信息。
[root@10-10-88-152?~]#?kubectl?get?nodes?10-10-88-113?-o?yaml? apiVersion:?v1 kind:?Node .... volumesAttached: -?devicePath:?csi-add9fc778d9593d01818d65ccde7013e87327d9f675b47df42a34b860c581711 name:?kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-4faa18f5bbbd11e8-1365 -?devicePath:?csi-5dd249387138238e8e2209eb471450a072dd6543adde7a6769c8461943c789ca name:?kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-4fa9b764bbbd11e8-1366 -?devicePath:?csi-bc9b81e32d84e8890d17568964c1e01af97b0c175e0b73d4bf30bba54e3f1a1e name:?kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-4fa94533bbbd11e8-1364 volumesInUse: -?kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-4fa94533bbbd11e8-1364 -?kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-4fa9b764bbbd11e8-1366 -?kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-4faa18f5bbbd11e8-1365
Pod分配到本worker node后,獲取Pod需要的volume,通過對比node狀態中的volumesAttached,確認volume是否已經attach到node節點,如果attach到node節點則將自身actualStateOfWorld中的volume狀態設置成attached,對應代碼4[4]、代碼5[5]。
-
先掛載到node中全局路徑,比如/var/lib/kubelet/plugins/kubernetes.io/csi/pv/pvc-3ecd68c7b7d211e8/globalmount。
-
映射到Pod對應路徑,比如/var/lib/kubelet/pods/49a5fede-b811-11e8-844f-fa7378845e00/volumes/kubernetes.io~csi/pvc-3ecd68c7b7d211e8/mount。
-
actualStateOfWorld中設置volume為掛載成功狀態。
4、pod controller確認卷已經映射成功,啟動Pod,此處不詳細展開。
| Pod被刪除的過程
pod controller watch到pod處于被刪除狀態,執行killPod操作,刪除Pod,此處不詳細展開。
volume manager獲取到Pod被刪除的信息,會執行如下幾步,相關代碼5[5]。
-
將Pod從desiredStateOfWorld的緩存信息中清除。
-
actualStateOfWorld中已經掛載的卷和desiredStateOfWorld發現Pod不應該掛載,執行UmountVolume操作,將Pod和卷映射關系解除,并將Pod從actualStateOfWorld的卷信息中剔除。
-
此時如果實際狀態中卷沒有關聯任何Pod,則說明卷需要可以完全與節點分離,則先執行UnmountDevice將卷的globalpath umount掉,等到下次reconcile時執行MarkVolumeAsDetached將卷完全從實際狀態中刪除掉。
attach detach controller發現掛載到node節點的volume沒有被Pod使用,執行detach操作,將卷從node節點detach,此時卷完全處于集群中未被使用的狀態,此處不詳細展開。
總結為Kubernetes存儲系統的特點:
-
不同組件通過資源狀態協作,attach detach controller需要PVC綁定PV的狀態,volume manager需要node status中volume attached狀態。
-
組件通過reconcile方式達到期望狀態,并且狀態可能需要多次reconcile中完成,如Pod清除掉后,volume最終和node分離。
|? 問題
理解了存儲系統的整體過程之后,回到問題,StatefulSet中Pod被刪除會發生什么?
首先,對于StatefulSet的了解,Pod被刪除,StatefulSet controller應該會很快創建Pod,在我們的場景中,Pod還是調度到先前節點中啟動。結合對存儲的理解,可能的場景:
場景一:delete Pod,感知順序為volume manager(umount)->statefulset->scheduler->volume manager(mount)。
volume manager發現Pod被刪除,執行umount
StatefulSet發現Pod被刪除,馬上創建Pod
scheduler發現Pod進行調度
volume manager發現原有volume需要綁定Pod,執行mount
volume manager發現Pod被刪除,執行umount/unmountDevice/MarkVolumeAsDelete(通過幾次reconcile)
attach detach controller發現volume在node節點未被使用,執行detach
scheduler發現Pod進行調度
attach detach controller發現volume需要attach,執行attach
volume manager掛載
場景三:delete Pod,感知順序為statefulset->volume manager(umount/deviceUmount)->scheduler->volume manager(mount)。
StatefulSet發現Pod被刪除,馬上創建Pod
volume manager發現Pod被刪除,執行umount/deviceUmount(通過幾次reconcile),注意此時devicePath和deviceMountPath都為空
scheduler發現Pod進行調度
volume manager發現原有volume需要綁定Pod,執行mount而此時devicePath和deviceMountPath都為空,問題出現
Sep? 14 19 : 28 : 33 10 -10 -40 -16 kubelet:?I0914? 19 : 28 : 33.174310 1953 operation_generator. go : 1168 ]?Controller?attach?succeeded? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "49a5fede-b811-11e8-844f-fa7378845e00" )?device?path:? "csi-eb93736e654600786d95eaffa7cd5d616f11a90bdc109e0df575e8646c250eb2"
Sep? 14 19 : 28 : 33 10 -10 -40 -16 kubelet:?I0914? 19 : 28 : 33.273344 1953 operation_generator. go : 486 ]?MountVolume.WaitForAttach?entering? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "49a5fede-b811-11e8-844f-fa7378845e00" )?DevicePath? "csi-eb93736e654600786d95eaffa7cd5d616f11a90bdc109e0df575e8646c250eb2"
Sep? 14 19 : 28 : 33 10 -10 -40 -16 kubelet:?I0914? 19 : 28 : 33.318275 1953 operation_generator. go : 495 ]?MountVolume.WaitForAttach?succeeded? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "49a5fede-b811-11e8-844f-fa7378845e00" )?DevicePath? "csi-eb93736e654600786d95eaffa7cd5d616f11a90bdc109e0df575e8646c250eb2"
Sep? 14 19 : 28 : 33 10 -10 -40 -16 kubelet:?I0914? 19 : 28 : 33.319345 1953 operation_generator. go : 514 ]?MountVolume.MountDevice?succeeded? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "49a5fede-b811-11e8-844f-fa7378845e00" )?device?mount?path? "/var/lib/kubelet/plugins/kubernetes.io/csi/pv/pvc-3ecd68c7b7d211e8/globalmount"
Sep? 14 19 : 29 : 12 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 12.826916 1953 operation_generator. go : 486 ]?MountVolume.WaitForAttach?entering? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "67f223dc-b811-11e8-844f-fa7378845e00" )?DevicePath? "csi-eb93736e654600786d95eaffa7cd5d616f11a90bdc109e0df575e8646c250eb2"
Sep? 14 19 : 29 : 14 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 14.465225 1953 operation_generator. go : 495 ]?MountVolume.WaitForAttach?succeeded? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "67f223dc-b811-11e8-844f-fa7378845e00" )?DevicePath? "csi-eb93736e654600786d95eaffa7cd5d616f11a90bdc109e0df575e8646c250eb2"
Sep? 14 19 : 29 : 14 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 14.466483 1953 operation_generator. go : 514 ]?MountVolume.MountDevice?succeeded? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "67f223dc-b811-11e8-844f-fa7378845e00" )?device?mount?path? "/var/lib/kubelet/plugins/kubernetes.io/csi/pv/pvc-3ecd68c7b7d211e8/globalmount"
Sep? 14 19 : 29 : 15 10 -10 -40 -16 kubelet:?W0914? 19 : 29 : 15.491424 1953 csi_mounter. go : 354 ]?kubernetes.io/csi:?skipping?mount?dir?removal,?path?does?not?exist?[/ var /lib/kubelet/pods/ 49 a5fede-b811 -11e8 -844f -fa7378845e00/volumes/kubernetes.io~csi/pvc -3 ecd68c7b7d211e8/mount]
Sep? 14 19 : 29 : 15 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 15.491450 1953 operation_generator. go : 686 ]?UnmountVolume.TearDown?succeeded? for volume? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" (OuterVolumeSpecName:? "data" )?pod? "49a5fede-b811-11e8-844f-fa7378845e00" (UID:? "49a5fede-b811-11e8-844f-fa7378845e00" ).?InnerVolumeSpecName? "pvc-3ecd68c7b7d211e8" .?PluginName? "kubernetes.io/csi" ,?VolumeGidValue? ""
Sep? 14 19 : 29 : 44 10 -10 -40 -16 kubelet:?W0914? 19 : 29 : 44.896387 1953 csi_mounter. go : 354 ]?kubernetes.io/csi:?skipping?mount?dir?removal,?path?does?not?exist?[/ var /lib/kubelet/pods/ 67f 223dc-b811 -11e8 -844f -fa7378845e00/volumes/kubernetes.io~csi/pvc -3 ecd68c7b7d211e8/mount]
Sep? 14 19 : 29 : 44 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 44.896403 1953 operation_generator. go : 686 ]?UnmountVolume.TearDown?succeeded? for volume? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" (OuterVolumeSpecName:? "data" )?pod? "67f223dc-b811-11e8-844f-fa7378845e00" (UID:? "67f223dc-b811-11e8-844f-fa7378845e00" ).?InnerVolumeSpecName? "pvc-3ecd68c7b7d211e8" .?PluginName? "kubernetes.io/csi" ,?VolumeGidValue? ""
Sep? 14 19 : 29 : 44 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 44.917540 1953 reconciler. go : 278 ]?operationExecutor.UnmountDevice?started? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?on?node? "10-10-40-16"
Sep? 14 19 : 29 : 44 10 -10 -40 -16 kubelet:?W0914? 19 : 29 : 44.919231 1953 mount_linux. go : 179 ]?could?not?determine?device? for path:? "/var/lib/kubelet/plugins/kubernetes.io/csi/pv/pvc-3ecd68c7b7d211e8/globalmount"
Sep? 14 19 : 29 : 45 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 45.609605 1953 operation_generator. go : 760 ]?UnmountDevice?succeeded? for volume? "pvc-3ecd68c7b7d211e8" %!(EXTRA? string =UnmountDevice?succeeded? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?on?node? "10-10-40-16" )
Sep? 14 19 : 29 : 45 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 45.624963 1953 operation_generator. go : 486 ]?MountVolume.WaitForAttach?entering? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "77b8caf7-b811-11e8-844f-fa7378845e00" )?DevicePath? ""
Sep? 14 19 : 29 : 46 10 -10 -40 -16 kubelet:?E0914? 19 : 29 : 46.006612 1953 nestedpendingoperations. go : 267 ]?Operation? for "\"kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338\"" failed.?No?retries?permitted?until? 2018 -09 -14 19 : 29 : 46.506583596 + 0800 CST?m=+ 105572.978439381 (durationBeforeRetry? 500 ms).?Error:? "MountVolume.WaitForAttach?failed?for?volume?\"pvc-3ecd68c7b7d211e8\"?(UniqueName:?\"kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338\")?pod?\"yoooo-416ea0-0\"?(UID:?\"77b8caf7-b811-11e8-844f-fa7378845e00\")?:?resource?name?may?not?be?empty"
Sep? 14 19 : 29 : 46 10 -10 -40 -16 kubelet:?I0914? 19 : 29 : 46.533962 1953 operation_generator. go : 486 ]?MountVolume.WaitForAttach?entering? for volume? "pvc-3ecd68c7b7d211e8" (UniqueName:? "kubernetes.io/csi/csi-qcfsplugin^csi-qcfs-volume-3ecd68c7b7d211e8-338" )?pod? "yoooo-416ea0-0" (UID:? "77b8caf7-b811-11e8-844f-fa7378845e00" )?DevicePath? ""
WaitForAttach有兩個階段:
-
Sep 14 19:29:14以及之前DevicePath非空
-
Sep 14 19:29:45以及之后DevicePath為空
通過日志發現Sep 14 19:29:14到Sep 14 19:29:45有一段日志信息比較關鍵,分析如下:
Sep 14?19 :29 :14 ……? MountVolume .MountDevice ……
Sep 14?19 :29 :15 …..? UnmountVolume .TearDown ……
Sep 14?19 :29 :44 ……? UnmountVolume .TearDown ……
Sep 14?19 :29 :44 ……? operationExecutor .UnmountDevice ……
Sep 14?19 :29 :44 ……? could not determine device for path ….
在步驟4中,有設置相關函數的:
其中比較關鍵的函數SetVolumeGloballyMounted:
|? 總結
Kubernetes之所以在當前成為容器編排領域的事實標準,原因很多,但是對我們來講基于聲明式API的編程范式是我們依賴Kubernetes的重要原因,當然在其解決的問題規模下復雜程度也不言而喻,總之,一句話,沒有銀彈。
相關鏈接:
https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/controller/volume/persistentvolume/pv_controller.go#L301
https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/controller/volume/attachdetach/populator/desired_state_of_world_populator.go#L88
https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/controller/volume/attachdetach/reconciler/reconciler.go#L251
https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go#L152
https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/kubelet/volumemanager/reconciler/reconciler.go#L160
https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/kubelet/volumemanager/reconciler/reconciler.go#L238
來自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/28218939/viewspace-2217186/,如需轉載,請注明出處,否則將追究法律責任。
轉載于:http://blog.itpub.net/28218939/viewspace-2217186/
總結
以上是生活随笔為你收集整理的Pod挂载Volume失败问题分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图表背后的秘密 | 技术指标讲解:布林带
- 下一篇: psp模拟器完美字库_安卓PSP模拟器评