我在安裝 proxmox 4.2 時, 檔案系統選用 zfs, 裝好之後想要在 ubuntu lxc 容器裡面跑 docker。 沒想到這是一個棘手的組合, 在過去這幾個月裡, 燒掉了我好幾個週末跟半個年假 (所以我貼文的頻率很低)。 這篇文章是給 linux 熟手看的 -- 筆記的成份多於教學的成份; 只在 proxmox host 底下測試, 並且省略很多解釋及較單純的細節。
[2018/9/23 在 proxmox 4.4 裡, 這已經不再是 「棘手的組合」, 已經變得簡單很多。 詳見 「幫 proxmox 的 lxc 擴充硬碟」。]
[2020/01/11 Linus Torvalds建議不要使用ZFS (考量法律與 Oracle 興訟的習性)]
一、 快放棄前的心得
灌在 zfs 上面的 host 可以跑 docker [ 官網、 問答] 也可以跑 lxc (proxmox 4.* 就是這樣); 在 lxc 裡面也可以跑 docker 。 (詳第三節)
但是當這三件事情疊在一起時... 撞牆碰壁很多次之後, 終於發現: 若要在 zfs 的 host 裡面的 lxc 裡面跑 docker, 就必須把一個完整的 file system 類型的 zfs dataset 掛在 lxc 的 /var/lib/docker 。 所以必須想辦法把 host 上的某一個 zfs file system 分享給 lxc。 如果是分享普通的目錄, 設定 lxc.mount.entry 就可以了: 問題是我們要分享的東西, 不是普通的目錄, 而是一個 zfs file system。 到最後看到 這一串討論 終於死心了: 因為 zfs 是整體管理的, 所以不可能只把 zfs pool 裡面的一個 dataset 切給容器去管理。 Bye Bye, 玩完了!
其實為了做正事, 早在一兩個月前我就用 kvm 另外架了一部 archlinux, 在上面直接跑 docker, 早就不打算再跟它纆鬥了。 只是不時會手癢再試、 再失敗。
都已經開始寫失敗文, 就在絕望放棄之際,
在一個失眠的夜裡突然想到:
在 (proxmox host 的) zfs pool 裡面建一個
volume, 把它切割、
格式化成 ext4, 再把它分享給 lxc, 那麼 docker
看到的就是單純的 ext4 了, 這樣可以嗎?
總之在這個三角關係裡面,
就是要有一方被矇在鼓裡、 不知道事實的真相,
這樣才玩得下去啊 :-)
二、 底層環境設定
- 我在安裝 proxmox 4.2-2/725d76f0 時選用 zfs。
- 創建 container 時, 採用的 template 是 ubuntu-16.04-standard_16.04-1_amd64.tar.gz 。 以下假設這部 lxc 的名稱/代號為 $LXC。
建議暫時先不急著在 $LXC 裡面安裝 docker。
三、 脫掉脫掉, 安全防護通通脫掉
想要在 lxc 裡面跑 docker, 就必須把 host (大房東) 的一些權限開放給 lxc (二房東)。 如果 「能動」 的考量勝過 「安全防護」, 那麼 這個 github issue 是我所找到最簡單清楚可行的經驗分享。 [更正過!] 在 $LXC 的設定檔 (proxmox: /etc/pve/lxc/$LXC.conf ; 其他一般狀況: /var/lib/lxc/$HOST/config ) 的最後面加上這幾句:
lxc.aa_profile = unconfined lxc.cgroup.devices.allow = a lxc.cap.drop = lxc.hook.mount = lxc.hook.post-stop =
其中後面兩句的目的是要取消 /usr/share/lxc/config/common.conf.d/00-lxcfs.conf 的效果。
如何檢查確認: 待補。
對, 叫 apparmor 大門大開不是個好主意; 不過 如何除錯 apparmor 太囉嗦了, 先求能動; 安全等以後再來傷腦筋吧。 反正我的 IP 不夠用, 我的這一部 $LXC 躲在 NAT 後面, 所以暫時先隨便沒關係啦 :-)
如果不涉及 zfs, 而是在一般 (例如採用 ext4) 的 host 上, 據說這樣也就夠了。
四、 建立一個 ext4
在 zfs 裡面建一個 volume 類型的 dataset、 切割、 格式化成 ext4、 寫入 fstab、 掛載起來:
zfs create -V 8G rpool/data/docker-payload # 更正: 建議不要切分割, # 直接在整個 volume 上面製作檔案系統, # 這樣將來若有必要才能夠直接 resize 擴大容量 mkfs -t ext4 /dev/rpool/data/docker-payload mkdir /mnt/docker-payload echo '/dev/rpool/data/docker-payload /mnt/docker-payload ext4 defaults 0 0' >> /etc/fstab mount -a
五、 把這個額外的 ext4 檔案系統也配給 $LXC
照著 1、 2 設定, 也就是在 $LXC 的設定檔最後面加上這兩句:
lxc.mount.entry = /mnt/docker-payload var/lib/docker none bind 0 0 lxc.logfile = /root/lxc-start.log
改完後, 要在 proxmox host 底下事先手動掛載 /mnt/docker-payload、 在 $LXC 的目錄裡面建一個 var/lib/docker 子目錄, 然後重新啟動 $LXC、 進入 $LXC, 檢查有沒有多一個 file system 可用。 注意:
- var/lib/docker 要用相對路徑!
- 這裡我卡了好久; 如果出錯, 一定要 設定 lxc.logfile 才看得到錯誤訊息。
- 如果看到你設定的路徑出現在錯誤訊息裡這一串 /usr/lib/x86_64-linux-gnu/lxc/rootfs/ 的後面, 而不是在你的 lxc 容器的 rootfs 底下, 不必困惑, 那只是因為 這是 pivot 之前的路徑。
- 在 $LXC 裡面看到的應該是類似 /dev/zd64 這樣的裝置才對; 如果看到類似 rpool/ROOT/pve-1 (你的 zfs 的主要 pool!) 那就錯了 -- 可能在啟動 $LXC 之前, 在 host 裡忘記掛載 /mnt/docker-payload?
六、 安裝 docker
- 在 proxmox host 上, 如果
lsmod | grep aufs
沒有東西, 就要先modprobe aufs
並且在echo aufs >> /etc/modules
- 在 $LXC 裡面安裝 docker 之前, 預先建立
設定檔:
echo '{ "storage-driver": "aufs" }' > /etc/docker/daemon.json
因為平常 docker 會自動偵測; 但現在我們的 $LXC 的 root fs 類型是 zfs, 而 /var/lib/docker 卻是 ext4, 所以如果沒告訴它, 它會猜錯, 然後失敗。 - 在 $LXC 裡面 安裝 docker。 我不敢去動 host 的 kernel, 所以省略 linux-image-extra-*。 反正 proxmox 應該早就已經幫我們把虛擬環境需要的東西都準備好了吧? 後面我照著 Set up the repository 的 Docker CE 做。
因為 ubuntu
遇到服務類的套件會一直做到啟動成功才算安裝成功;
但是整個預備設定過程想要一步到位恐怕不太容易。
一旦 (或是像我一樣...不斷) 出錯, docker
套件就進入卡卡無法安裝無法移除的狀態。
我最近才學會這個用法: 可以用
apt-get purge docker.io
把它砍掉, 然後就可以重裝一次、
再改設定、 一試再試試不成, 再試一下...
望著 docker run hello-world
完美的輸出, 有一種打敗魔王的快感...
老師假如用ZFS切成volume再格式化成ext4這樣在效能是會不會有影響?當然ZFS上的snapshot真的好好用喔!!我之前用ZFS切出volume給DRBD當區塊裝置又在上面用LVM 好像最後的速度好像會受限於LVM??
回覆刪除哇 你的 zfs 應該玩得比我多很多吧。 有你自己寫的或別人寫的教學文可以分享一下嗎? 對啊, 越多層在做相同的事, 效率自然就越低囉。 這裡是為了避免讓 docker 看到 zfs 不得不多加一層 ext4。 至於你的狀況, 如果沒有要用 drbd 那就連 lvm 也可以省下來了。 所以換作我的話, 會搜尋 zfs high availability 看能不能只補上原始 zfs 欠缺的功能就好。
回覆刪除http://acidrop.biz/wp/?p=559 我是proxmox 3.4剛出來就馬上用上它的cluster架構!現在到出到4.4了!我原本有效能上的問題,後來改程式去了!效能問題也就解了~只是我有試單純zfs pool效能真的有比較快!DRBD我還不想放棄可是9以後可能要收費了!打算用ZFS Remote Replication去取代!FB上也有滿多人用 PVE的https://www.facebook.com/groups/pve.tw/
回覆刪除