溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

docker volume源碼的示例分析

發(fā)布時(shí)間:2021-12-14 09:47:04 來源:億速云 閱讀:175 作者:小新 欄目:云計(jì)算

小編給大家分享一下docker volume源碼的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

這是在docker v1.10.3版本的使用過程中,使用convoy 作為volume driver,在一次docker volume remove失敗時(shí),使我不得不對docker volume 的源碼做一次分析。

問題現(xiàn)象:創(chuàng)建曾刪除過的volume會失敗,請求無報(bào)錯返回 重現(xiàn)過程:

  • 創(chuàng)建容器,volume使用test5_volume

  • 刪除容器,刪除volume

  • 再次創(chuàng)建同名volume時(shí)失敗

當(dāng)時(shí)有一個Workaround 方案: 通過 convoy 在該宿主機(jī)上創(chuàng)建一個同名的 volume (大小任意),然后再次執(zhí)行 docker volume rm 刪除該 volume ; 接著就可以通過 docker volume create 重新創(chuàng)建 volume 了。 當(dāng)時(shí)考慮是 docker 緩存沒有及時(shí)清理的問題,于是得去分析下相關(guān)代碼。

##docker volume create源碼分析: docker volume源碼的示例分析

看流程圖發(fā)現(xiàn) - create時(shí),會觸發(fā)未注冊driver的重新注冊,只檢查該volume是否在docker daemon緩存中,如果在就不創(chuàng)建。而不會調(diào)用convoy接口去確認(rèn)該volume是否真的存在。如果此時(shí),convoy和docker daemon緩存信息不同步,則create操作不能如愿了。

##docker volume remove源碼分析: docker volume源碼的示例分析

看流程圖發(fā)現(xiàn) - remove時(shí),只會刪除docker daemon緩存中記錄的volume信息,不會同步docker dameon和convoy的volume信息。如果此時(shí)convoy 中volume數(shù)據(jù)和docker daemon 緩存中volume數(shù)據(jù)不一致,也不會得到糾正。

##docker volume list源碼分析: docker volume源碼的示例分析

看流程圖發(fā)現(xiàn) - list時(shí),如果convoy中記錄了某個volume,但docker daemon緩存中沒有該volume,則會將該volume信息從convoy同步到docker daemon。

##問題定位 ###docker volume delete的代碼 docker volume源碼的示例分析 ###docker volume list的代碼 docker volume源碼的示例分析 第一幅圖中可見,每次刪除某個volume的時(shí)候,會先對這個volume的name加鎖,然后vd.Remove(v)函數(shù)調(diào)用convoy刪除這個volume,再清理掉docker的緩存。

第二幅圖中可見,每次調(diào)用list接口時(shí),List會先調(diào)用s.list()函數(shù),該list()函數(shù)并不受鎖單個volume的鎖限制,s.list()函數(shù)中會調(diào)用convoy拿到所有的volume,然后List方法中會for循環(huán)每個volume,先對volume的name加鎖,如果volume在緩存中不存在,則加入到緩存。

我們的這個問題的發(fā)生的原因:s.list()找convoy拿到所有volume是不受鎖的限制的,而且list會for循環(huán)處理所有的volume,時(shí)間比較長,這就導(dǎo)致這樣一種情況:list先拿到convoy的某個volume,然后docker才接到了刪除這個volume的請求,docker刪除convoy的這個volume并把自己的緩存刪掉,然后list中的for循環(huán)才處理到這個volume,發(fā)現(xiàn)緩存中已經(jīng)沒有這個volume了,于是又把這個volume加入到緩存中(s.setNamed(v, "")),這樣就導(dǎo)致緩存convoy端的volume已經(jīng)清除了,但緩存中還有這個volume,兩邊的數(shù)據(jù)不一致了。 此時(shí),docker再次收到創(chuàng)建該同名的volume時(shí),首先查找緩存發(fā)現(xiàn)已經(jīng)存在這個volume了,于是不再創(chuàng)建直接返回成功。之后docker再收到刪除該volume的請求時(shí),docker會調(diào)用convoy刪除,而convoy中已經(jīng)沒有這個volume了,于是向docker返回失敗的信息,因而docker也返回失敗。

##解決方案 當(dāng)我們試圖去解決這個問題的時(shí)候,發(fā)現(xiàn)docker 1.11版本已經(jīng)解決這個問題: bug:https://github.com/docker/docker/issues/21403 patch:https://github.com/docker/docker/commit/f04334ea040500181727c47dc626171e98660cae docker volume源碼的示例分析 解決方法: 在list volume的時(shí)候,如果緩存中不存在這個volume,不再繼續(xù)添加到緩存中,這樣就能避免docker中的數(shù)據(jù)比convoy中的數(shù)據(jù)多。 雖然還是會有數(shù)據(jù)不一致的問題,但只要docker的數(shù)據(jù)比plugin的數(shù)據(jù)少,那么每次請求時(shí)docker就會再次去請求plugin,這種不一致沒有問題。 相反,如果docker中有某個volume的數(shù)據(jù),而convoy中卻沒有該數(shù)據(jù),那么就會產(chǎn)生問題。上圖中添加緩存的那幾行代碼正是導(dǎo)致了docker的數(shù)據(jù)比convoy的數(shù)據(jù)多,問題就產(chǎn)生了。

相信,現(xiàn)在這個階段,大家都在使用的docker版本都比1.10大了。否則,要打上這個patch。

看完了這篇文章,相信你對“docker volume源碼的示例分析”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI