使用 Device Mapper來改變Docker容器的大小

來源:互聯網
上載者:User

標籤:des   http   io   ar   os   使用   sp   檔案   資料   

 Jérôme Petazzoni ( Docker 佈道師)譯者:Mark Shao ( EMC 中國進階工程師)

如果在 CentOS 、 REHL 、 Fedor 或者其他預設沒有 AUFS 支援的 Linux 發行版上使用 Docker ,你可能需要用到 Device Mapper 的儲存外掛程式。將這個外掛程式設定為預設,它會把你所有的容器儲存到一個 100G 的簡短檔案中,並且限制每個容器最大為 10GB 。這篇文章將展示如何突破這個限制,並且把容器的儲存移動到一個指定的分區或者 LVM 卷中。

它的工作原理

要真正理解我們要做的事情,首先來瞭解 Device Mapper 外掛程式的工作原理。

它是基於 Device Mapper 的“精簡目標”的特性。它實際上是目標塊裝置的快照,之所以被稱為“精簡”是因為它允許精簡配置。精簡配置意味著你有一個(希望很大)可用儲存塊的池,接著你可以從那個池中建立任意大小的塊裝置(虛擬磁碟,如有需要);在你實際讀寫後,這些儲存塊將會被標記為已使用(或者從池中拿走)。

這意味著你是可以超額使用這個池,比如在一個 100GB 的池裡面建立幾千個 10GB 的卷,甚至可能是一個 100TB 的卷在一個 1GB 的池裡面。只要你的實際讀寫的塊的容量不大於池的大小,你怎麼做都 OK 。

除此之外,精簡目標的方式是可以做快照的。這表明無論何時,你都可以建立一個存在的卷的淺拷貝。在使用者看來,就像你有兩個一樣的卷,它們可以獨立地各自修改。即使你做了一個完整的拷貝,除了在時間上它是瞬間發生的(即使是很大的卷),它們不會兩次重複使用儲存。額外的儲存只有當其中任何一卷有變化的時候才會發生,然後精簡目標會從池裡面分配一個儲存快。

從本質上來看,“精簡目標”實際上使用了兩個存放裝置:一個(大)的是儲存塊池自己,還有一個小的儲存了一些中繼資料。這些中繼資料中包括了卷、快照、以及每個卷的塊或者快照同儲存池中塊的映射資訊。

當 Docker 使用 Device Mapper 儲存外掛程式的時候,它會在 /var/lib/docker/devicemapper/devicemapper/data 和/var/lib/docker/devicemapper/devicemapper/metadata 下建立兩個檔案(如果它們不存在)來儲存對應的儲存池和相關的中繼資料。這非常方便,你不需要做任何安裝部署的工作(你不需要額外的分區來儲存 Docker 容器,或者建立 LVM 或其他類似的東西)。然而它也有兩個缺點:

- 儲存池會有一個預設 100GB 的容量

- 它將會被疏鬆檔案所支援。從磁碟的使用效率的觀點來看,這還不錯的(就像在精簡池中的卷,它一開始是小的,只有當實際需要寫的時候才會使用磁碟的儲存塊)。但是從效能的角度來看就不那麼好了,因為 VFS 增加了一些額外的負擔,特別是"第一次寫的時候"。

在瞭解如何調整容器的大小之前,我們來試試看如何給池增加更多空間。

我們需要一個更大的池

警告 : 下面的操作會刪除你所有的容器和鏡像,確保你已經把之前的資料做了備份!

記住上面說過的,當資料和元類資訊檔不存在的時候 Docker 會建立它們,所以解決方案非常簡單:在啟動它們之前,在 Docker 裡建立這些檔案!

  1. 停止 Docker 守護進程,因為我們將要重新設定我們的儲存外掛程式,如果我們在啟動並執行時候移除檔案,那麼糟糕的事情就將發生。

  2. 擦去 /var/lib/docker 。 警告:正如前面提到的,這個操作會把你所有的容器和鏡像都刪除掉。

  3. 建立儲存目錄: mkdir -p /var/lib/docker/devicemapper/devicemapper

  4. 建立你的池: dd if=/dev/zero of=/var/lib/docker/devicemapper/devicemapper/data bs=1G count=0 seek=250 ,建立一個 250G 的疏鬆檔案。如果你指定 bs=1G count=250(不使用 seek 選項),那麼它會建立一個普通檔案(而不是一個疏鬆檔案)。

  5. 重啟 Docker 守護進程。提示:在預設情況下,如果你有 AUFS 的支援, Docker 會使用它;所以如果你要強制使用 Device Mapper 的外掛程式,需要在啟動 Docker 的命令中增加 -s devicemapper 的選項。

  6. 使用 docker info 來檢查 Data Space Total 的值是否正確。

我們需要一個更快的池

警告 :下面的操作也會刪除你所有的容器和鏡像。確保把你重要的鏡像儲存在 registry 中,儲存你容器裡面的重要資料。

要獲得一個更快速的池,最簡單的辦法就是使用一個真實的裝置而不是一個基於檔案的迴圈裝置。過程幾乎一樣。假設你有一個完全空的硬碟, /dev/sdb,你想把它完全用於容器的儲存,你可以這樣做:

  1. 停止 Docker 守護進程

  2. 移除 /var/lib/docker (似曾相識,對嗎?)

  3. 建立一個儲存目錄: mkdir -p /var/lib/docker/devicemapper/devicemapper

  4. 在目錄下建立一個資料軟連結,指向裝置: ln -s /dev/sdb /var/lib/docker/devicemapper/devicemapper/data

  5. 重啟 Docker

  6. 使用 docker info 來檢查 Data Space Total 的值是否正確

使用 RAID 和 LVM

如果你希望合并多塊相似的磁碟,可以使用 RADID10 軟體,這個會通過連結到 /dev/md 而實現。另外一個非常好的選擇是把你的磁碟(或者RAID磁碟陣列)放到 LVM 的物理卷中,並且建立兩個邏輯卷:一個是資料,一個是中繼資料。對於中繼資料池的最佳的大小我沒有什麼特別的建議,不過占資料池的 1% 看起來不錯。

就像前面一樣,停止 Docker ,移除它的資料目錄,然後建立一個指向 /dev/mapper 裝置的符號連結,然後重啟 Docker 。

如果你需要更多關於 LVM 的知識,請看這裡 LVM howto 。

擴容容器

預設來說,如果你使用 Device Mapper 的儲存外掛程式,所有的鏡像和容器是從一個初始 10G 的檔案系統中建立的。讓我們來看看如何從一個更大的檔案系統中建立一個容器。

首先,我們用 Ubuntu 的鏡像來建立我們的容器。我們不需要在這個容器裡運行任何東西,只需要這個檔案(或者關聯的檔案系統)存在。為了示範,我們會在這個容器裡運行 df ,來看一下根檔案系統的大小。

$ docker run -d ubuntu df -h /4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603

由於需要修改 Device Mapper 管理中的一些卷的資訊,我們現在用 root 的身份來運行一些命令。所有以#開頭的命令都必須以 root 身份來執行。只要能訪問 Docker 的 Socket 服務,你也可以用普通使用者的身份來執行其他的命令(以$開頭)。

讓我們看一下 /dev/mapper ,那裡應該有一個對應容器檔案系統的符號連結,以 docker-X:Y-Z- 開頭:

# ls -l /dev/mapper/docker-*-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603lrwxrwxrwx 1 root root 7 Jan 31 21:04 /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603 -> ../dm-8

注意記住那個全名,我們未來會用到。

首先讓我們來看一下當前卷的資訊表:

# dmsetup table docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda36030 20971520 thin 254:0 7

第二個數字是裝置的大小,表示有多少個 512-bytes 的扇區. 這個值略高於 10GB 的大小。

我們來計算一下一個 42GB 的卷需要多少扇區,

$ echo $((42*1024*1024*1024/512))88080384

精簡快照目標的一個神奇的特點是它不會限制卷的大小。當你建立它的時候,一個精簡的卷使用0個塊,當你開始往塊裡面寫入的時候,它們會從共用的塊池中進行分配。你可以寫0個塊,或者是10億個塊,這個和精簡快照目標沒關係。檔案系統的大小隻和 Device Mapper 表有關係。

覺得困惑?不要擔心。我們只是需要裝載一個新的表,這個完全和之前的是一樣的,但是有更多的扇區。僅此而已。

舊錶是 0 20971520 thin 254:0 7 。我們會改變第二個數字,要非常小心保持其他的值不變。你的卷可能不是 7 ,所以要使用正確的值!

這樣操作:

# echo 0 88080384 thin 254:0 7 | dmsetup load docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603

現在如果我們再次檢查表的資訊,步驟和前面一樣。首先使用下面的命令啟用新表:

# dmsetup resume docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603

執行完命令後,再次檢查一下表的資訊,發現它會使用新的扇區數量。

我們已經調整了塊裝置的大小,但是我們仍然需要調整檔案系統的大小,我們使用 resize2fs 來操作:

# resize2fs /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603resize2fs 1.42.5 (29-Jul-2012)Filesystem at /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603 is mounted on /var/lib/docker/devicemapper/mnt/4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603; on-line resizing requiredold_desc_blocks = 1, new_desc_blocks = 3The filesystem on /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603 is now 11010048 blocks long

作為一個可選步驟,我們會重啟容器,檢查一下我們的確有了正確大小的空閑空間:

$ docker start 4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603$ docker logs 4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603df: Warning: cannot read table of mounted file systems: No such file or directoryFilesystem      Size  Used Avail Use% Mounted on-               9.8G  164M  9.1G   2% /df: Warning: cannot read table of mounted file systems: No such file or directoryFilesystem      Size  Used Avail Use% Mounted on-                42G  172M   40G   1% /

想把整個過程自動化起來?當然沒問題。

CID=$(docker run -d ubuntu df -h /)DEV=$(basename $(echo /dev/mapper/docker-*-$CID))dmsetup table $DEV | sed "s/0 [0-9]* thin/0 $((42*1024*1024*1024/512)) thin/" | dmsetup load $DEVdmsetup resume $DEVresize2fs /dev/mapper/$DEVdocker start $CIDdocker logs $CID
擴容鏡像

不幸的是,目前的版本的 Docker 不能讓我們很方便地擴容鏡像。你可以把鏡像對應的塊裝置進行擴容,然後從它來建立一個容器,但是新的容器不會有正確的大小。

同樣,如果你提交了一個很大的容器,最後產生的鏡像也不會很大(這是由 Docker 為鏡像準備檔案系統的方法造成的)。

這意味著如果一個容器真的超過了 10GB ,在不使用一些其他的小技巧的情況下,你沒法正確的把它提交為一個鏡像。

總結

Docker 將來肯定會提供一些更好的方法來擴容容器,所需的代碼變動是很小的。管理一個精簡的池和對應的元資訊比較複雜(因為這個需要很多不同的操作流程,以及一個潛在的資料移轉。鑒於移除了所有的東西來構件新的池,也就沒有在本文提及),但是我們今天提到的一些解決方案相信已經對你有所協助。

老樣子,如果你有問題或者評論,馬上在 IRC 上 ping 我( jpetazzo on Freenode ),或是通過 Twitter (@jpetazzo) 和我聯絡。

這篇文章由 Jérôme Petazzoni 發表,點擊 這裡 可閱讀原文。 Mark Shao 翻譯了本文,你可以在 GitHub 上與他交流。The article was contributed by Jérôme Petazzoni , click here to read the original publication. 

使用 Device Mapper來改變Docker容器的大小

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.