好啦, 如果需要完整的虛擬化, lxd 當然無法取代 kvm, 畢竟 lxd 只是容器 (container) 技術。 但如果只是想要玩玩不同的 distribution 的命令列, 那麼 lxd 就超合適的。 如 lxc 筆記 所說 (但換個比喻) 如果把 lxc 想成是車子的主體, 那麼 lxd 就是方向盤/排檔桿/剎車/儀表板等等 「使用者介面」。 凡是 「lxc-xxx」 長像的指令 (例如 lxc-ls、 lxc-create) 都屬於底層 lxc 套件, 是修車師傅專用的, 我們駕駛人一般不太去用它。 這篇介紹適用於駕駛人、 長得像 「lxc xxx」 的指令 (例如 lxc ls、 lxc launch)。
Ubuntu 的 lxd 文件 是很好的出發點。 它解釋: 可以說 lxd 是 「輕量級的容器 "hypervisor"」; lxd 跟 lxc 之間的關係, 有點像 libvirt 跟 qemu 之間的關係。 比較特別的是, lxd 提供遠端操作的介面。 再拿我先前的汽車比喻, 修正一下: 想像你一個人在控制室裡同時遙控遠端的十部 (半自動駕駛) 汽車, 每部汽車就是一個當地的 lxc, 而控制室裡的儀表板就是 lxd 的操作介面。 也大推 lxd 主要作者 Stéphane Graber 所寫 一系列文章 的第一篇觀念介紹文。
那麼, 接下來就先照著 ubuntu 文件 (及
Stéphane 系列第三篇) 做一小段吧。
當然, 我們的事業沒那麼龐大; lxc 跟 lxd 其實都只在本機執行。
以 sudo apt install lxd
安裝 lxd 之後,
要先執行一次 sudo lxd init
以初始化系統。
再把你的 user 加入 lxd 群組, 例如我打:
sudo adduser ckhung lxd
登出再登入, 從此以後就不需要用 root 的身份;
凡人 ckhung 就可以用 lxc 指令。
lxc list # 已建立了哪些 containers? (目前沒有) lxc image list # 本地已下載了哪些映像檔? (目前沒有) lxc image list images: # 網路上有哪些映像檔可以下載? 哇~ 好多!
因為每次查詢 (網路連線) 都有點慢, 而且輸出結果有點囉嗦,
所以我喜歡去掉一些欄位、 去掉分隔線、 把結果存檔:
lxc image list images: -c lfds | grep -v '^[+-]*$' >
~/lxc-images.txt
當然, 隔一陣子, 這個資料就會過時, 需要再更新。
打開 ~/lxc-images.txt 看一下, 哇, 除了想當然爾的 debian/ubuntu/fedora/...
還有 kali 跟 openwrt 耶! 那就拿 kali 來作實驗好了:
lxc launch images:kali k1 lxc launch images:kali k2
我們先從伺服器下載名為 「kali」 的映像檔,
以它建立名為 「k1」 的 container, 並且立即啟動。
同樣再以 kali 映像檔建立第二個 container, 名為 「k2」。
這次速度快多了, 因為本地已有映像檔。
用 lxc list
查看, 可以看到已有兩部 containers,
而且都已配有區網 ip 位址;
用 lxc image list
看到本地已有一個映像檔。
用 lxc exec k1 bash
進入 container,
在裡面查一下: cat /etc/os-release
跟 dpkg -l
等等, 並且
apt update
確認一下網路順暢。
如果網路不通, 請參考
How To Set Up a Network Bridge for LXD Containers 。
因為 kali 是高手玩的, 我也不會用 (遮臉) 示範到此為止, 按 ^d 跳出。
如果要執行圖形介面的軟體, 請參考 lxc 筆記 的 X11 forwarding 那一節。 其他可能常用到的指令:
lxc info k1 # 查看 k1 的詳細訊息 lxc stop k1 # k1 關機 lxc start k1 # k1 開機 lxc delete k1 # 砍掉 k1! 起手無回!
再來是分享檔案: lxc config device add k2 share1 disk
source=~ path=/mnt/hosthome
這句話會把 host 裡自己的家目錄 (/home/ckhung) 分享給 k2 這個 container,
成為 k2 裡面的一個名為 share1 的 disk 裝置,
並且自動掛載在 k2 的 /mnt/hosthome (會自動建立) 底下。
從此以後從 k2 裡面的這個目錄就可以
讀取 host 裡的檔案。
如果想要從 k2 裡面 寫入 host 所分享過來的目錄與檔案, 那就必須:
- 在 k2 裡面新增一個用戶, 例如
useradd -u 5971 -m -s /bin/bash snoopy
這裡故意指定奇怪數字作為 uid, 以便下一個指令看得更清楚。 也順便查一下新用戶的 gid:id snoopy
。 - 在 host 裡面指定: 把自己 (凡人 ckhung) 的 uid 與 gid
對應到 k2 裡面的 snoopy:
echo -e "uid $(id -u) 5971\ngid $(id -g) 5971" | lxc config set k2 raw.idmap -
(假設剛才查到的 snoopy 的 gid 跟 uid 一樣) 注意: 雙引號, 不是單引號! 這裡有差。 - (在 host 裡) 假設 id -u 的輸出是 1000 那麼請在
/etc/subuid 最後加一列
root:1000:1
這意思是允許 root 把 uid 1000 這一個用戶映射到 container 裡面的某用戶。 (注意: 原有的另一列 root:很大的數字:65536 不要刪掉!) 同樣地, 根據 id -g 的輸出也如法泡製在 /etc/subgid 最後加一列。 這是因為負責此事的 lxd 服務是以 root 的身份在執行的。 必須systemctl restart lxd
才會生效。 - k2 關機、重開。 重新進入。 在 k2 裡面看到那些 host 所分享過來的檔案與目錄, 擁有人都是 snoopy, 可以寫入!
除錯過程可能會需要查看目前設定: lxc config device show k2
或刪除做錯的設定: lxc config device remove k2 share1
。
以上關於分享檔案, 主要參考
nixCraft 跟
Tribaal 兩篇優質教學文;
這個自問自答 也有一些參考價值。
用 echo 餵給 lxc config 的語法, 從 這個問答 學來。 可以直接編輯設定檔嗎? 根據
這個問答, 設定檔是 .db ;
但我甚至在同一目錄下也找不到設定檔。 (版本問題?)
粗略查看
原始碼, 看來就直接呼叫 newuidmap 跟 newgidmap 而已,
好像並沒有寫入什麼設定檔。
是可以從 /var/log/lxd/某容器/lxc.conf 裡面看到 「某容器」
當初創立時的所有參數設定; 但那只是歷史記錄,
並不反應目前的狀況, 更無法修改它以影響未來。
要查看目前的所有設定, 請用 lxc config show --expanded k2
(
為什麼需要用 --expanded ?)
如果想掀開引擎蓋看看, 請用 root 的身份
(sudo bash) 進到 /var/lib/lxd 底下逛逛。
在 /var/lib/lxd/storage-pools/default/containers/
底下會看到 k1 跟 k2 兩部 containers 的目錄,
包含各自的系統根目錄 (rootfs)。
在那裡下 du -s *
可以查看每部 container 佔用多少空間。
至於映像檔, 則是下載到 /var/lib/lxd/images/ 底下。
kali linux 映像檔的一些設定檔放在 7be3...1d33 裡面,
可以用 tar tJf 7be3...1d33
查看。
(要解壓縮的話用 tar xJf ... )。
而 7be3...1d33.rootfs 則是一個 squashfs 壓縮的唯讀檔案系統。
十六進位數字 7be3...1d33 是 kali linux 映像檔的 id,
它就像是身份證字號一樣, 當初是這樣產生的:
cat 7be3* | sha256sum
(兩個檔串在一起的 sha256sum)
而 lxc image list
所秀的 fingerprint 就是這個 id 的一小部分。
想要再多學一些 lxd 指令的話, 可以參考 Useful LXD commands 及 LXD cheat sheet for beginners 。 不過我覺得進不同版本的 linux 裡面探索才更好玩啊~
先前遺漏了~ 在 /etc/subuid 及 /etc/subgid 裡面新增 root:1000:1 (之類的) 那一句很重要!
回覆刪除