CentOS系統故障 | 一樁"血案"引起的容器存儲驅動比較

寫在前面:html

因爲紅帽在Linux界的影響力,相信不少朋友在測試和生產系統用的是RedHat或者CentOS系統,此次我在CentOS系統上遇到了一個頗有意思的故障,經過此次故障的緣由分析及解決,特地寫了這篇文章分享給你們。git

 

咱們在CentOS上部署了一套Docker系統,運行了一段時間後,忽然發現全部容器運行異常,同時宿主機內核報磁盤I/O錯誤:github

 

看到問題的第一反映是查看磁盤狀態和空間使用狀況,發現系統的根目錄已經用完:docker

咱們知道,Docker默認的存儲目錄是在/var/lib/docker/下,同時咱們也知道,能夠經過使用-g, --graph=」/var/lib/docker」 參數修改Docker 默認存放路徑。知道了問題後,咱們能夠經過掛載一個大硬盤到系統,並將Docker的目錄更改成新掛載到硬盤上:服務器

我將Docker的存儲目錄設置到剛纔新增長的/data目錄下,可是原來的鏡像和容器都找不到了,由於路徑改了。原來的鏡像是在/var/lib/docker/devicemapper/devicemapper/{data,metadata},轉移文件後繼續運行Docker服務,這樣咱們就有了一個300G的大房子給Docker們用了。app

 

你們覺得事情到了這裏就完結了麼?其實我也想,可是我順便折騰了一下,因而又發生了接下來的事情。說我手賤也好,瞎折騰也罷,導入一堆容器鏡像和運行一堆容器後,系統又光榮告訴我全部的容器根目錄所有變成了只讀,宿主機內核一樣報磁盤I/O錯誤,一開始我覺得data目錄又被寫滿了,可是用df –Th命令查看後,發現目錄還有不少空間:性能

可是殘酷的現實是,只用了不到一半的空間後,全部的容器就所有出現異常了,這是我祭出了經典三板斧:重啓容器,重啓Docker服務,重啓服務器。然並卵,容器仍是運行異常。經過在網上爬了一堆資料,在http://jpetazzo.github.io/2014/01/29/docker-device-mapper-resize/上查到,CentOS默認用的是Device Mapper做爲容器的存儲驅動的,你們能夠用dockers info命令查看,Docker服務啓動時默認會在/var/lib/docker/devicemapper/devicemapper/目錄建立一個100G(因爲1000和1024換算的關係,系統實際顯示的是107.4G,其餘數字亦同)的data文件,而後啓動的容器的全部變動的數據所有保存到這個data文件中;也就是說當容器內產生的相關data數據超過100G後容器就再也沒有多餘的空間可用,從而致使全部容器的根目錄變爲只讀!同時它會限制每一個容器最大爲 10GB。太坑爹了有木有,給了大房子只能用100G!測試

爲了找到根本緣由,咱們須要瞭解Device Mapper存儲驅動的原理: Device Mapper存儲驅動是以精簡配置的方式運行的,它其實是目標塊設備的快照。網站

Docker啓動時會設置一個100G的sparse文件( /var/lib/docker/devicemapper/devicemapper/data,元數據爲/var/lib/docker/devicemapper/devicemapper/metadata ),並將其做爲Device Mapper的存儲池,而全部容器都從該存儲池中分配默認10G的存儲空間使用,以下圖所示:spa

當有實際讀寫後,這些存儲塊將在存儲池中被標記爲已使用(或者從池中拿走)。當實際讀寫的塊容量大於池的容量時,容器的運行空間不足,因此報I/O錯誤。

 

Device Mapper存儲驅動很是方便,你不須要作任何安裝部署即可以使用:如建立額外的分區來存儲 Docker 容器,或者創建LVM。然而它也有兩個缺點:

• 存儲池會有一個默認 100GB 的容量,知足不了大存儲的需求。

• 它將會被稀疏文件所支持(精簡配置,一開始基本不佔用空間,只有當實際須要寫的時候纔會使用磁盤的存儲塊)但性能較差。

 

針對這些問題,有兩個解決方案:

1. 使用更大的文件/磁盤/邏輯卷建立data文件:

2. 經過Docker啓動參數的--storage-opt選項來限制每一個容器初始化的磁盤大小,如-storage-opt dm.basesize=80G 這樣每一個容器啓動後,根目錄的總空間就是80G。

 

可是我總以爲這樣的解決方式不夠優雅,須要多步操做才能知足需求,同時,容器的空間仍是被限制的,只是限制的大小變化而已。那有沒有更好的辦法呢? 讓咱們繼續來爬資料,在Docker的官方網站上:

(https://docs.docker.com/engine/reference/commandline/dockerd/)

Docker在存儲驅動方面支持 AUFS、Device Mapper、Btrfs、ZFS、 Overlay 、Overlay2等多址方式,現因爲AUFS並未併入內核,目前只有Ubuntu系統上可以使用aufs做爲docker的存儲引擎,而在CentOS系統上默認使用Device Mapper,可是幸運的是,在Linux內核3.18.0以上的版本,是能夠原生支持Overlay驅動方式的,Overlayfs跟AUFS很像,可是性能比AUFS好,有更好的內存利用。

 

Docker經過-s參數選擇存儲驅動, 經過-s=overlay,咱們將存儲驅動器設置爲Overlay方式,再重啓Docker應用。

你們能夠看到,如今Docker已是使用了OverlayFS(這裏你們要注意,若是系統有存儲的鏡像和運行的容器,更改存儲驅動後將都不可用,請先行備份)。

 

經過修改成OverlayFS,Device Mapper的存儲池容量限制及單個容器運行最大空間限制通通沒有了,同時Overlay的讀寫性能也好於Device Mapper,只需經過-s=overlay一個參數便可優雅的使用更好的文件系統來運行容器。

 

至此,容器運行時I/O錯誤的緣由已經完美解決,但願這篇文章能幫到在使用過程當中遇到相同問題的朋友。

相關文章
相關標籤/搜索