您好,登錄后才能下訂單哦!
小編給大家分享一下docker volume源碼的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
這是在docker v1.10.3版本的使用過程中,使用convoy 作為volume driver,在一次docker volume remove失敗時,使我不得不對docker volume 的源碼做一次分析。
問題現象:創建曾刪除過的volume會失敗,請求無報錯返回 重現過程:
創建容器,volume使用test5_volume
刪除容器,刪除volume
再次創建同名volume時失敗
當時有一個Workaround 方案: 通過 convoy 在該宿主機上創建一個同名的 volume (大小任意),然后再次執行 docker volume rm 刪除該 volume ; 接著就可以通過 docker volume create 重新創建 volume 了。 當時考慮是 docker 緩存沒有及時清理的問題,于是得去分析下相關代碼。
##docker volume create源碼分析:
看流程圖發現 - create時,會觸發未注冊driver的重新注冊,只檢查該volume是否在docker daemon緩存中,如果在就不創建。而不會調用convoy接口去確認該volume是否真的存在。如果此時,convoy和docker daemon緩存信息不同步,則create操作不能如愿了。
##docker volume remove源碼分析:
看流程圖發現 - remove時,只會刪除docker daemon緩存中記錄的volume信息,不會同步docker dameon和convoy的volume信息。如果此時convoy 中volume數據和docker daemon 緩存中volume數據不一致,也不會得到糾正。
##docker volume list源碼分析:
看流程圖發現 - list時,如果convoy中記錄了某個volume,但docker daemon緩存中沒有該volume,則會將該volume信息從convoy同步到docker daemon。
##問題定位 ###docker volume delete的代碼 ###docker volume list的代碼 第一幅圖中可見,每次刪除某個volume的時候,會先對這個volume的name加鎖,然后vd.Remove(v)函數調用convoy刪除這個volume,再清理掉docker的緩存。
第二幅圖中可見,每次調用list接口時,List會先調用s.list()函數,該list()函數并不受鎖單個volume的鎖限制,s.list()函數中會調用convoy拿到所有的volume,然后List方法中會for循環每個volume,先對volume的name加鎖,如果volume在緩存中不存在,則加入到緩存。
我們的這個問題的發生的原因:s.list()找convoy拿到所有volume是不受鎖的限制的,而且list會for循環處理所有的volume,時間比較長,這就導致這樣一種情況:list先拿到convoy的某個volume,然后docker才接到了刪除這個volume的請求,docker刪除convoy的這個volume并把自己的緩存刪掉,然后list中的for循環才處理到這個volume,發現緩存中已經沒有這個volume了,于是又把這個volume加入到緩存中(s.setNamed(v, "")),這樣就導致緩存convoy端的volume已經清除了,但緩存中還有這個volume,兩邊的數據不一致了。 此時,docker再次收到創建該同名的volume時,首先查找緩存發現已經存在這個volume了,于是不再創建直接返回成功。之后docker再收到刪除該volume的請求時,docker會調用convoy刪除,而convoy中已經沒有這個volume了,于是向docker返回失敗的信息,因而docker也返回失敗。
##解決方案 當我們試圖去解決這個問題的時候,發現docker 1.11版本已經解決這個問題: bug:https://github.com/docker/docker/issues/21403 patch:https://github.com/docker/docker/commit/f04334ea040500181727c47dc626171e98660cae 解決方法: 在list volume的時候,如果緩存中不存在這個volume,不再繼續添加到緩存中,這樣就能避免docker中的數據比convoy中的數據多。 雖然還是會有數據不一致的問題,但只要docker的數據比plugin的數據少,那么每次請求時docker就會再次去請求plugin,這種不一致沒有問題。 相反,如果docker中有某個volume的數據,而convoy中卻沒有該數據,那么就會產生問題。上圖中添加緩存的那幾行代碼正是導致了docker的數據比convoy的數據多,問題就產生了。
相信,現在這個階段,大家都在使用的docker版本都比1.10大了。否則,要打上這個patch。
看完了這篇文章,相信你對“docker volume源碼的示例分析”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。