如果單純只是想要備份還原一兩部 openvz 虛擬機, 「布丁布丁吃什麼?」 有兩篇圖文並茂的詳盡說明: 採用 proxmox 網頁介面、 採用命令列。 但如果你遇到跟我一樣的狀況, 需要幫學生或客戶一口氣建立幾十部 openvz 虛擬機, 那當然就要採用命令列的方式比較快。 本文精簡地重述如何用命令列備份還原, 並且把重點放在 「批次/大量複製」。
一、 備份/搬家/還原
Proxmox 預設把虛擬機的備份檔放在 /var/lib/vz/dump。
所以比方說想要手動備份 499 號虛擬機, 可以這樣下:
vzdump 499 -dumpdir /var/lib/vz/dump -compress lzo
搬家很簡單: 直接把剛剛產生的 /var/lib/vz/dump/vzdump-openvz-499-2015_07_05-15_41_07.tar.lzo 用 scp 指令拷貝到新家的同一目錄, 那麼從新家的網頁介面 (https://...:8006) 也可以看見這個手動產生、 搬過來的備份。 (如果只想在原本的 host node 上面大量複製, 就省略此步驟。)
還原也很簡單: vzrestore
/var/lib/vz/dump/vzdump-openvz-499-2015_07_05-15_41_07.tar.lzo 499
如果在新家並不需要 499 號機, 也可省略這步。
事實上可以還原成其他任意 vmid (例如 401 或 402 等等),
所以這同時也是複製指令。
二、 整齊畫一的大量生產
接下來要用 499 號機的備份檔來大量複製產生 401 到 406 共六部虛擬機。
行前提醒: 開著 ssh 服務掛在網路上是很危險的。 建議先確認 499 號機已做好 ssh 基本防護, 別像我一樣等到每小時被企圖入侵上千次才驚醒。
先產生一個文字檔 ids.txt, 內含 01 到 06:
perl -e 'for $i (1..6) { printf "%02d\n", $i; }' > ids.txt
然後一口氣 「還原」 (其實是 「複製」) 產生這六部虛擬機:
for i in $(cat ids.txt) ; do vzrestore
/var/lib/vz/dump/vzdump-openvz-499-2015_07_05-15_41_07.tar.lzo 4$i ; done
三、 初步個性化
複製完之後, 每一部機器的主機名稱跟 ip 位址應該要改過來。 尤其是如果換了 host node, 網段可能會不一樣。
但是依據虛擬機所採用的網路介面不同, /etc/vz/conf/*.conf 會有不同的設法:
- 如果你採用的是比較簡單/安全/高效率的 venet,
那麼設定檔裡面會有一句
IP_ADDRESS="..."
; 等一下要用 --ipdel 跟 --ipadd 來修改這個設定。 - 如果你採用的是功能較完整但較複雜的 veth,
那麼設定檔裡面會有一句
NETIF="..."
。
本節適用於第一種狀況。 看起來 官網的虛擬機複製教學 也只處理第一種狀況。 (事實上我覺得那一頁還漏了一些重要設定 -- 如果不採用備份還原而是採用手動複製根目錄, 那麼應該還要手動修改設定檔內的 VE_ROOT 跟 VE_PRIVATE。)
先手動修改一部機器做實驗 (就拿原來的 499 吧) 直到你滿意這個指令為止。 例如根據我 (自己任意規定的) 主機名稱及 IP 位址設定原則, 應該這樣修改第 499 號虛擬機:
vzctl set 499 --hostname dp499 --ipdel all --ipadd 10.167.49.91 --save
於是把這一句話貼到 fix499.sh 文字檔內, 然後下:
for i in $(cat ids.txt) ; do perl -pe
"s/49\.91/4991/; s/499/4$i/g" fix499.sh ; done
| perl -pe 's/\.(4\d)(\d1)/21.$1.$2/; s/\.0(\d)/.$1/'
這會產生如下的輸出:
vzctl set 401 --hostname dp401 --ipdel all --ipadd 10.167.40.11 --save vzctl set 402 --hostname dp402 --ipdel all --ipadd 10.167.40.21 --save vzctl set 403 --hostname dp403 --ipdel all --ipadd 10.167.40.31 --save vzctl set 404 --hostname dp404 --ipdel all --ipadd 10.167.40.41 --save vzctl set 405 --hostname dp405 --ipdel all --ipadd 10.167.40.51 --save vzctl set 406 --hostname dp406 --ipdel all --ipadd 10.167.40.61 --save
剪貼一兩句、 執行一下。 如果一切看來 OK,
就把上述結果再 pipe 給 bash (... | bash
)
完成初步個性化, 讓每部機器有別於其他複製兄弟。
以下幾點說明:
- 以上兩段底線部分是為了處理我特殊指定 ip 方式: vmid (401、 402、 ... 406) 被句點拆成兩段了, 所以先刪掉句點, 等全面代換完畢, 再把句點塞回去。 如果你指定 ip 的方式比較簡單, 可以直接省略那兩段。
- 要記得把 IP 裡面的 .05 改成 .5 等等。
- 第一段 perl 後面要用雙引號, 這樣來自 shell 的 $i 才會正確代換。
- 第二段 perl 後面要用單引號, 這樣 (來自 perl 內部、 前半句比對結果的) $1 跟 $2 才會正確代換。
然後請略過下一節, 直接跳到第五節。
四、 veth 類型虛擬網卡的 mac address
如果你的虛擬機 (一開始就採用, 或是 後來才改) 採用 veth, 那麼上一節還是要照著做, 但其中的 --ipdel 跟 --ipadd 處理 ip address 的段落可以忽略。 這一節處理 veth 的狀況。
這個直接改設定檔比較快。 請先
grep -i mac /etc/vz/conf/499.conf
查看一下原來的 mac address 設定。
我看到的類似這樣:
NETIF="ifname=eth0,mac=12:34:56:78:9A:BC,host_ifname=veth499.0,host_mac=FE:DC:BA:98:76:54,bridge=vmbr79"
所以我這樣修改 499 號機的 mac address:
perl -i.bak -pe "s/(mac=[\w:]{14}):\w\w/\$1:99/gi"
/etc/vz/conf/499.conf
這會直接把 /etc/vz/conf/499.conf 設定檔裡的兩個 mac
的尾巴都改成 99, 並且產生一個備份檔 /etc/vz/conf/499.conf.bak。
以下幾點請注意:
- 備份檔僅一次有效。 後來再產生的新備份檔會蓋掉先前的舊備份檔!
- (我的錯誤經驗) 如果閒著無聊, 你也可以 用 md5sum 產生 Mac address, 但最好不要去動 mac address 的第一個 byte, 因為根據 這個問答, 第 2 位必須是 2 或 6 或 A 或 E。
- 這裡我很偷懶。 嚴格來講, 應該要先把十進位代號轉成十六進位, 再填入最後一個 byte。
成功之後, 再包上一層 (shell 的) for 迴圈:
for i in $(cat ids.txt) ; do
perl -i.bak -pe "s/(mac=[\w:]{14}):\w\w/\$1:$i/gi"
/etc/vz/conf/4$i.conf
五、 啟動
不論你的網路介面是 venet 還是 veth, 至此, 已可啟動複製機大軍:
for i in $(cat ids.txt) ; do vzctl start 4$i ; done
六、 sshd 的金鑰
在每一部機器的 /etc/ssh 底下, 放著 ssh 連線金鑰。
就像公寓裡的每個單元長像相同、 但鎖頭不同,
這些複製機的金鑰也不應該相同。
所以我們把每一部機器的金鑰刪掉,
重新再產生一次屬於它自己的金鑰:
for i in $(cat ids.txt) ;
do vzctl exec $i rm /etc/ssh/ssh_host*key* ;
vzctl exec $i dpkg-reconfigure openssh-server ; done
當然, 前提是每部複製虛擬機都已啟動才能用 exec。
同理, 如果你採用自己認證的憑證來提供 https 服務, 那麼也應該幫每部機器重新產生它專屬的憑證。
七、 結論
當然, 你也可以試著把這些步驟寫成一個 shell script。 問題是:
- 每位 proxmox 系統管理員的命名/指定 IP 規則可能很不一樣。 不同的管理員終究還是需要去改程式碼。
- 系統管理遇到大量/批次處理的動作時, 最好先小量單獨測試比較保險。
基於這兩個理由, 我覺得還是照著本文略改、 逐步實作比較實在。 同時也會順便學到 shell 的 for 迴圈、 命令結果代換、 regexp、 以及... perl 萬歲! (暑假我想學 python, 本來想用 python 做, 不過最後還是選擇言簡意胲、 一語中的的 perl。)
沒有留言:
張貼留言
因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。