如何備份/轉移 LXD 容器
在先前我們簡單介紹過如何轉移 LXD 容器到另一台主機上,這次要來詳細的解釋個各種方法並且實際演練一次!
測試環境
測試環境:
- OS: Ubuntu 20.04.2 LTS
- Kernel: 5.4.0-70-generic
- lxd: 4.12 (snap)
容器搬移方向:vsv_1
(192.168.1.55) –> vsv_2
(192.168.1.56)
為了示範接下來的操作,我們需要先建立一個容器,這邊命名為 bionic
$ lxc launch ubuntu:focal focal Creating focal Starting focal $ lxc list +-------+---------+-----------------------+-------------+-----------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +-------+---------+-----------------------+-------------+-----------+-----------+ | focal | RUNNING | 10.106.147.152 (eth0) | fd42: ...略 | CONTAINER | 0 | +-------+---------+-----------------------+-------------+-----------+-----------+
為了方便區別,我們在 /hi
這個檔案寫入 hello world
字串
$ lxc exec focal -- sh -c 'echo "hello world" | tee /hi' hello world $ lxc exec focal -- sh -c 'cat /hi' hello world
然後再加上一個 snapshot
,取名 snap01
$ lxc snapshot focal snap01 $ lxc info focal Name: focal ...略 Snapshots: snap01 (taken at 2021/04/02 13:14 UTC) (stateless)
方法一、使用 lxc export
匯出
在新版的 LXD 之中(3.1 以後),新增了 export
指令,方便大家進行匯出的動作
$ lxc export focal focal.tar.gz Backup exported successfully!
也可以使用 --compression
指定壓縮格式(支援 bz2
、gz
、xz
、lzma
、tar
/無壓縮)
$ lxc export focal focal.tar.bz2 --compression bzip2 Backup exported successfully!
另外,還有 --optimized-storage
選項,可以進一步縮小檔案容量。
根據 help
訊息,會限制可以還原的目標(can only be restored on a similar pool)
$ lxc export focal focal-optimized-storage.tar.gz --optimized-storage Backup exported successfully!
比較一下各種組合的檔案大小:
$ du -h focal* 385M focal-optimized-storage.tar.bz2 414M focal-optimized-storage.tar.gz 755M focal.tar.bz2 812M focal.tar.gz
先想辦法把檔案複製到另一部 lxd
主機:
$ scp focal.tar.gz 192.168.1.56:/home/play_pc/ [email protected]'s password: focal.tar.gz 42% 341MB 89.6MB/s 00:05 ETA
然後在目標機器上執行 lxc import
指令匯入 bionic
play_pc at vsv-2 in ~ $ lxc import focal.tar.gz
確認一下有沒有成功:
play_pc at vsv-2 in ~ $ lxc list +-------+---------+------+------+-----------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +-------+---------+------+------+-----------+-----------+ | focal | STOPPED | | | CONTAINER | 1 | +-------+---------+------+------+-----------+-----------+ $ lxc start focal $ lxc exec focal -- sh -c 'cat /hi' hello world $ lxc info focal Name: focal ...略 Snapshots: snap01 (taken at 2021/04/02 13:14 UTC) (stateless)
可以看到原本的修改(/hi
)還在,而且快照(Snapshot)也一起複製過來了!
方法二、使用 lxc image
匯出
要使用 lxc image
匯出我們的 container 之前,需要先把目前的容器發佈成 image,指令格式如下:
lxc publish 容器名稱[/快照名稱] [選項]
選項的部份:
--compression
: 前面lxc export
有測試過了,這裡不贅述--alias
: 設定映像檔別名,非常好用(等一下會講)
更多詳細資訊請下 lxc publish --help
指令查訊最新版的說明
這裡我們做兩個測試,先試試不加 alias
的 image:
$ lxc publish focal Instance published with fingerprint: 312bbf53b914cb84968d9c04f47ec0ba0380985345529602d7005acb55ffc394 $ lxc image list +-------+--------------+--------+---------------------------------------------+--------------+-----------+----------+-----------------------------+ | ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE | +-------+--------------+--------+---------------------------------------------+--------------+-----------+----------+-----------------------------+ | | 312bbf53b914 | no | Ubuntu 20.04 LTS server (20210325) | x86_64 | CONTAINER | 405.63MB | Apr 2, 2021 at 1:48pm (UTC) | +-------+--------------+--------+---------------------------------------------+--------------+-----------+----------+-----------------------------+
在 publish
之前,請先停止容器 lxc stop
,否則會出現以下的錯誤訊息:
$ lxc publish focal Error: The instance is currently running. Use --force to have it stopped and restarted
另一個一個命名為 my_bionic
:
$ lxc publish focal --alias my_focal Instance published with fingerprint: 312bbf53b914cb84968d9c04f47ec0ba0380985345529602d7005acb55ffc394 $ lxc image list +----------+--------------+--------+---------------------------------------------+--------------+-----------+----------+-----------------------------+ | ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE | +----------+--------------+--------+---------------------------------------------+--------------+-----------+----------+-----------------------------+ | my_focal | 312bbf53b914 | no | Ubuntu 20.04 LTS server (20210325) | x86_64 | CONTAINER | 405.63MB | Apr 2, 2021 at 1:52pm (UTC) | +----------+--------------+--------+---------------------------------------------+--------------+-----------+----------+-----------------------------+
匯出的時候傳統上使用 fingerprint,但也可以使用別名(alias)來指定要匯出的 image:
lxc image export 312bbf53b914 . Image exported successfully! # 或 $ lxc image export my_focal . Image exported successfully!
匯出的檔名長這樣(fingerprint):
$ ls 312bbf53b914cb84968d9c04f47ec0ba0380985345529602d7005acb55ffc394.tar.gz
複製到目標主機:
$ scp 312bbf53b914cb84968d9c04f47ec0ba0380985345529602d7005acb55ffc394.tar.gz \ 192.168.1.56:/home/play_pc/ 312bbf53b914cb84968d9c04f47ec0ba0380985345529602d7005acb55ffc394.tar.gz 100% 406MB 86.2MB/s 00:04
匯入 image(當然也是能加上別名 --alias
):
play_pc at vsv-2 in ~ $ lxc image import --alias my_focal \ 312bbf53b914cb84968d9c04f47ec0ba0380985345529602d7005acb55ffc394.tar.gz Image imported with fingerprint: 312bbf53b914cb84968d9c04f47ec0ba0380985345529602d7005acb55ffc394
用剛才匯入的 image 建立(初始化)一個容器:
play_pc at vsv-2 in ~ $ lxc launch 312bbf53b914 focal Creating focal Starting focal # 或 $ lxc launch my_focal focal Creating focal Starting focal
最後測試一下:
play_pc at vsv-2 in ~ $ lxc exec focal -- sh -c 'cat /hi' hello world $ lxc info focal Name: focal ...略
一樣保留了檔案的修改(/hi
),不過快照(snapshot)不意外的沒有保存下來(畢竟我們是以 OS/Container 映像檔的方式匯入)
方法三、使用 lxc copy
直接轉移
這個作法主要是新增一個遠端(remote
)的 LXD Server 進來管理,也就是可以直接操控的狀態。
這就是為什麼你在 lxc
下 --help
選項之後會一直出現 [<remote>:]
的原因(這邊用 lxc export
舉例):
Usage: lxc image export [<remote>:]<image> [<target>] [flags]
首先使用 ip
指令確認遷移的目的地(vsv-2)的 IP 位址:
play_pc at vsv-2 in ~ ~ » ip a ...略 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:fc:84:75 brd ff:ff:ff:ff:ff:ff inet 192.168.1.56/24 brd 192.168.1.255 scope global dynamic enp0s3 valid_lft 86351sec preferred_lft 86351sec inet6 fe80::a00:27ff:fefc:8475/64 scope link valid_lft forever preferred_lft forever ...略
然後在 vsv-2 上設定要監聽(Listen
)的 IP / 網路介面:
# 綁定單一界面 lxc config set core.https_address 192.168.1.56 # 綁定單一界面 + Port lxc config set core.https_address 0.0.0.0:8443
在 vsv-1 也是一樣:
lxc config set core.https_address 192.168.1.55
如果有設定防火牆的話,請記得打開
sudo ufw allow from 192.168.1.56 to any port 8443 proto tcp
被連線的(遠端)伺服器 vsv-2 上需要設定連線密碼:
lxc config set core.trust_password myPassword
在連線之前,先用 lxc info
指令確認一下 Server 2 的 certificate_fingerprint
,等一下新增主機的時候會用到:
play_pc at vsv-2 in ~ $ lxc info ...略 5EaVIYTe3Dp3MYAyuExXPqspU5/mpcomi0Y09sW5bSTvTAIwA22u8L1d+jnGuZHt YEY+hOJ0nVHs/NVdRAfANsYlHgefp1+2X3nZ2DjZtsO8fEWN -----END CERTIFICATE----- certificate_fingerprint: d155bc9e71dec2a3a520c5b13e0a77567baa23858f9f291ebf8637e7afca0c31 driver: lxc | qemu ...略
使用 lxc remote
指令新增遠端主機(記得確認 fingerprint
的正確性):
$ lxc remote add VSV_2 192.168.1.56 Generating a client certificate. This may take a minute... Certificate fingerprint: d155bc9e71dec2a3a520c5b13e0a77567baa23858f9f291ebf8637e7afca0c31 ok (y/n)? y Admin password for VSV_2: Client certificate stored at server: VSV_2
新增的遠端連線採用 TLS + 密碼 的方式來進行驗證,相關的憑證會在初次連線時自動產生,可以透過以下指令進行管理(詳細資訊)
play_pc at vsv-2 in ~ $ lxc config trust list +--------------+--------------+------------------------------+-------------------------------+ | FINGERPRINT | COMMON NAME | ISSUE DATE | EXPIRY DATE | +--------------+--------------+------------------------------+-------------------------------+ | f8fce44cbb8d | play_pc@from | Apr 2, 2021 at 10:49am (UTC) | Mar 31, 2031 at 10:49am (UTC) | +--------------+--------------+------------------------------+-------------------------------+
在 vsv-1 這邊我們可以看到新增的 VSV_2
$ lxc remote list +-----------------+------------------------------------------+---------------+-------------+--------+--------+ | NAME | URL | PROTOCOL | AUTH TYPE | PUBLIC | STATIC | +-----------------+------------------------------------------+---------------+-------------+--------+--------+ | VSV_2 | https://192.168.1.56:8443 | lxd | tls | NO | NO | +-----------------+------------------------------------------+---------------+-------------+--------+--------+ | images | https://images.linuxcontainers.org | simplestreams | none | YES | NO | +-----------------+------------------------------------------+---------------+-------------+--------+--------+ | local (current) | unix:// | lxd | file access | NO | YES | +-----------------+------------------------------------------+---------------+-------------+--------+--------+ | ubuntu | https://cloud-images.ubuntu.com/releases | simplestreams | none | YES | YES | +-----------------+------------------------------------------+---------------+-------------+--------+--------+ | ubuntu-daily | https://cloud-images.ubuntu.com/daily | simplestreams | none | YES | YES | +-----------------+------------------------------------------+---------------+-------------+--------+--------+
如果需要即時遷移(live migration / 不用先停止容器)的話,請先啟用 CRIU:
play_pc at vsv-1 in ~ $ sudo snap set lxd criu.enable=true $ sudo snap restart lxd Restarted. play_pc at vsv-2 in ~ $ sudo snap set lxd criu.enable=true $ sudo snap restart lxd Restarted.
轉移的時候非常方便,只要一行指令就能搞定!!
lxc copy focal VSV_2:focal
不幸的是,在本文寫作當下(2021/04/02),這項功能(CRIU / live migration)仍然不穩定…
$ lxc copy focal VSV_2:focal Error: Failed instance creation: Error transferring instance data: migration pre-dump failed (00.058076) Warn (compel/arch/x86/src/lib/infect.c:281): Will restore 3948 with interrupted system call (00.065034) Warn (compel/arch/x86/src/lib/infect.c:281): Will restore 3951 with interrupted system call (00.079336) Warn (compel/arch/x86/src/lib/infect.c:281): Will restore 3956 with interrupted system call (00.089166) Error (criu/proc_parse.c:460): Can't open map_files: Permission denied (00.089170) Error (criu/proc_parse.c:661): Can't open 3960's mapfile link 556b1eb51000: Permission denied (00.089175) Error (criu/cr-dump.c:1166): Collect mappings (pid: 3960) failed with -1 (00.089822) Error (criu/cr-dump.c:1570): Pre-dumping FAILED.
如果你也遇到相同的問題,加上 --stateless
選項,取消 CRIU / live migration 功能,應該就能正常使用了:
lxc copy focal VSV_2:focal --stateless
最後測試一下:
play_pc at vsv-2 in ~ $ lxc exec focal -- sh -c 'cat /hi' hello world $ lxc info focal Name: focal ...略 Snapshots: snap01 (taken at 2021/04/02 13:14 UTC) (stateless)
東西都在,沒問題!
其他(純筆記)
發現 file
指令可以用來判斷壓縮檔格式(無視副檔名)
~ » mv bionic.tar.gz bionic.tar ~ » file bionic.tar bionic.tar: gzip compressed data, from Unix, original size modulo 2^32 1363521024 gzip compressed data, ...略
參考資料
- Setting up LXD on Ubuntu 16.04 | Ubuntu
- 官方的 lxd 安裝教學(已過時/被
snap
取代),內容安排非常友善,相當推薦 - Linux Containers – LXD – Getting started – command line
- 取代上面的安裝說明,最新,資訊豐富,對新手相對比較不友善
- Image handling – LXD – system container manager
- 在 Supported compression 這一項有列出支援的壓縮格式
- Backing up a LXD server – LXD – system container manager
- 官方說明文件,提到
lxc export
但是沒有給範例,也是我寫這篇文章的主因 - Backup the container and install it on another server – LXD – Linux Containers Forum
- 官方論壇,感謝前人分享舊版
lxd
的備份方法 - How to move/migrate LXD VM to another host on Linux – nixCraft
- 果然有人先發過了這個主題了嗎?可惡~
- FAQ – LXD – system container manager
- How to enable LXD server for remote access?
- When I do a
lxc remote add
over https, it asks for a password? - Security – LXD – system container manager
- Adding a remote with TLS client certificate authentication
- LXD 3.1 has been released – LXD – News
- 確切指出
lxc export
和lxc import
兩個指令從哪個版本開始導入 - Error doing a lxc copy – General – Linux Containers Forum
- 提到 CRIU / Live Migration 還不穩定的問題