Ubuntu LXD

LXD 安裝

Ubuntu 20 已預設安裝好 Snap,LXD 版本為 4.0.9,Ubuntu 16 18 需自行安裝。

Ubuntu 16 / 18 安裝 LXD,建議先安裝 Snap,再以 Snap 安裝指定的 LXD 版本。

先更新 ubuntu:
sudo apt-get update && sudo apt-get upgrade -y

再安裝 snap:
sudo apt install snapd -y

再來決定要安裝 LXD 的版本

snap info lxd

可以看到有那些 channels 可供安裝
channels:
  latest/stable:    5.8-bb9c9b1   2022-11-25 (23983) 143MB -
  latest/candidate: 5.8-bb9c9b1   2022-11-22 (23983) 143MB -
  latest/beta:      ↑
  latest/edge:      git-38127b4   2022-12-06 (24066) 143MB -
  ...
安裝 4.0 穩定版:
sudo snap install lxd --channel=4.0/stable

檢查安裝的版本:
lxd version

4.0.9

安裝最新的穩定版:
sudo snap install lxd --channel=latest/stable

Ubuntu 16 (非以 Snap) 安裝 LXD
sudo apt install lxd -y

檢查安裝的版本:
lxd --version

2.0.11
Ubuntu 18 (非以 Snap) 安裝 LXD
sudo apt install lxd -y

檢查安裝的版本:
lxd version

3.0.3

非以 Snap 安裝 LXD 後,要切換為 Snap 的環境可參閱 更新(遷移) LXD 版本

將非 root 帳戶加入到 lxd 群組

目前使用者 (除了 root) 需加入 lxd 群組,才能操作 LXD。

安裝後 lxd 群組應該存在。

$ cat /etc/group | grep lxd
lxd:x:116:user

可以看一下目前使用者是否在 lxd 群組之內,如果有則不用加入。

先檢查一下 lxc list 是否能正確執行:
sudo lxc list

目前使用者未加入 lxd 群組 應該出錯:
lxc list

Error: Get "http://unix.socket/1.0": dial unix /var/snap/lxd/common/lxd/unix.socket: connect: permission denied
錯誤訊息語意不清,以為是 socket 配置出錯。

將目前使用者加入 lxd 群組 (非 root 才需要加入):
sudo usermod -a -G lxd $(whoami)
newgrp lxd

應該能正確執行:
lxc list

LXD 初始化

sudo lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
是否使用集群
Do you want to configure a new storage pool? (yes/no) [default=yes]:
是否要配置新的儲存池

Name of the new storage pool [default=default]:
新儲存池的名稱

Name of the storage backend to use (ceph, btrfs, dir, lvm, zfs) [default=zfs]:
要使用儲存後端的類型

Create a new ZFS pool? (yes/no) [default=yes]:
創建一個新的 ZFS 池

Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:

Size in GB of the new loop device (1GB minimum) [default=30GB]:
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
是否在本機建立一個名為 lxdbr0 的 NAT 橋接網卡

What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
lxdbr0 是否使用 IPv4 地址

What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
lxdbr0 是否使用 IPv6 地址
Would you like to create a new local network bridge? (yes/no) [default=yes]: no
不自動建立本機橋接網卡

Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes
你想將 LXD 配置為使用現有的橋接網卡嗎? 是的

Name of the existing bridge or host interface: br0
現有橋接網卡名稱 br0
Would you like the LXD server to be available over the network? (yes/no) [default=no]:
是否 (現在) 啟動 LXD 服務器,如遠端複製。
Would you like the LXD server to be available over the network? (yes/no) [default=no]: yes
現在啟動 LXD 服務器

Address to bind LXD to (not including port) [default=all]:
Port to bind LXD to [default=8443]:

Trust password for new clients:
輸入遠端使用者連線密碼

Again:
再輸入一次
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]
是否自動更新影像檔快取

Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

LXD 建立容器

列示影像檔:
lxc image list images: ubuntu -c ld (1)

list images 結果:
+-------------------------------------+-----------------------------------------+
|                ALIAS                |               DESCRIPTION               |
+-------------------------------------+-----------------------------------------+
| ubuntu/16.04 (7 more)               | Ubuntu xenial amd64 (20230118_07:42)    |
+-------------------------------------+-----------------------------------------+
| ubuntu/18.04 (7 more)               | Ubuntu bionic amd64 (20230118_07:42)    |
+-------------------------------------+-----------------------------------------+
| ubuntu/22.10 (7 more)               | Ubuntu kinetic amd64 (20230118_07:42)   |
+-------------------------------------+-----------------------------------------+
| ubuntu/focal (7 more)               | Ubuntu focal amd64 (20230118_07:43)     |
+-------------------------------------+-----------------------------------------+
1 -c ld 參閱 lxc image list images -h
Flags:
  -c, --columns   Columns (default "lfpdasu")

預設格式為 lfpdasu,如下對應
l:ALIAS
f:FINGERPRINT
p:PUBLIC
d:DESCRIPTION
a:ARCH
s:SIZE
u:UPLOAD DATE

得知 Image ALIAS Name: ubuntu/18.04,實際上的影像檔名稱為 ubuntu:18.04 可以使用代號 ubuntu:bionic (代號參閱: Releases - Ubuntu Wiki ),不過就算把影像檔輸入 ubuntu/18.04 它會自動修正。

由影像檔建立 (初始化) c1 容器:
lxc init ubuntu/18.04 c1

Creating c1
The local image 'ubuntu/18.04' couldn't be found, trying 'ubuntu:18.04' instead.

LXD 會自動出找出正確的影像檔。
第一次會自動下載影像檔,第二次則會使用已下載的影像檔。

lxc init 換成 lxc launch,所有的參數都是相同的,唯一的差別在於建立容器後會自動啟動。

由影像檔建立 c1 容器後自動啟動:
lxc launch ubuntu:18.04 c1
顯示容器列表:
lxc list

+------+---------+------+------+------------+-----------+
| NAME |  STATE  | IPV4 | IPV6 |    TYPE    | SnapSHOTS |
+------+---------+------+------+------------+-----------+
| c1   | STOPPED |      |      | PERSISTENT | 0         |
+------+---------+------+------+------------+-----------+

啟動 c1 容器:
lxc start c1

顯示容器列表:
lxc list -c ns4 (1)

lxc list 結果:
+------+---------+----------------------+
| NAME |  STATE  |         IPV4         |
+------+---------+----------------------+
| c1   | RUNNING | 10.43.172.214 (eth0) |
+------+---------+----------------------+
1 ns4 參閱 lxc list -h
Flags:
  -c, --columns   Columns (default "ns46tSL")
      --fast      Fast mode (same as --columns=nsacPt)

LXD 橋接 br0 網卡

LXD 在預設的情況下使用 NAT 的方式,容器只能被 Host 存取,如果其他主機要能存取,必須使用 Host 的橋接網卡。

查詢主機是否使用 br0 橋接網卡:
ip route show default

default via 192.168.1.254 dev br0 proto dhcp src 192.168.1.31 metric 100

將容器的網路橋接至 br0,以 profile pf-br0 來實現。

建立 pf-br0 profile:
lxc profile create pf-br0
lxc profile device add pf-br0 eth0 nic nictype=bridged parent=br0 name=eth0

顯示 pf-br0 的內容:
lxc profile show pf-br0

config: {}
description: ""
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic
name: pf-br0
used_by: []

建立一個新容器 c2 profile 為 defaultpf-br0:

lxc launch ubuntu:18.04 c2 --profile default --profile pf-br0
顯示容器列表:
lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 10.43.172.214 (eth0) | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
|      |         |                      | pf-br0   |
+------+---------+----------------------+----------+

現有容器 c1 的 profile 為 default 加入 pf-br0

lxc profile add c1 pf-br0
lxc profile assign c1 default,pf-br0

上述為等效指令,上方為加入,下方 (全) 指定。

顯示容器列表:
lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 192.168.1.101 (eth0) | default  |
|      |         |                      | pf-br0   |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
|      |         |                      | pf-br0   |
+------+---------+----------------------+----------+

容器 c1 刪除 profile pf-br0

lxc profile remove c1 pf-br0
lxc profile assign c1 default

上述為等效指令,上方為移除,下方 (全) 指定。

修改 profile default 橋接至 br0

列出 default 的組態:
lxc profile show default

devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: lxdbr0
    type: nic
將 default 的 parent 的 lxdbr0 修改成 br0
lxc profile device set default eth0 parent br0
列出 default 的組態:
lxc profile show default

devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic
顯示容器列表:
lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 192.168.1.101 (eth0) | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
|      |         |                      | pf-br0   |
+------+---------+----------------------+----------+

Ubuntu 20 在預設安裝的 Snap LXD 4.0.9,將 parent 修改成 br0 時出錯。

執行同樣的指令:
lxc profile device set default eth0 parent br0

Error: Device validation failed for "eth0": Cannot use "nictype" property in conjunction with "network" property
顯示 profile default:
lxc profile show default

devices:
  eth0:
    name: eth0
    network: lxdbr0
    type: nic

缺少 nictype: bridged
default (profile) 移除 eth0 設備:
lxc profile device remove default eth0

default (profile) 加入完整的 eth0 設備描述:
lxc profile device add default eth0 nic nictype=bridged parent=br0 name=eth0

容器設定設備

建議不要在容器設定設備,應使用 profile,在維護時才不會混淆。

在執行之前先檢查一下 c1 組態:
lxc config show c1

...
devices: {}
...

容器設定設備有多種方式

lxc config device add 語法:
lxc config device add -h

lxc config device add [<remote>:]<container|profile> <device> <type> [key=value...] [flags]

將容器 c1 設定為 lxdbr0 網卡:
lxc config device add c1 eth0 nic nictype=bridged parent=lxdbr0 name=eth0
lxc network attach 語法:
lxc network attach -h

lxc network attach [<remote>:]<network> <container> [<device name>] [<interface name>] [flags]

將容器 c1 設定為 lxdbr0 網卡:
lxc network attach lxdbr0 c1 eth0 eth0 (1)
1 第一個 eth0 是 device name,第二個 eth0 是 interface name
顯示 c1 組態:
lxc config show c1

devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: lxdbr0
    type: nic
lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 10.43.172.214 (eth0) | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
|      |         |                      | pf-br0   |
+------+---------+----------------------+----------+

容器移除設備

lxc config device remove c1 eth0
lxc network detach lxdbr0 c1

上述為等效指令

lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 192.168.1.101 (eth0) | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
|      |         |                      | pf-br0   |
+------+---------+----------------------+----------+

測試容器設備錯誤

lxc config device add c1 eth0 nic nictype=bridged parent=lxdbr0 (1)
lxc network attach lxdbr0 c1 eth0 (2)
1 缺少 name=eth0
2 少一個 eth0
顯示 c1 組態:
lxc config show c1

devices:
  eth0:
    nictype: bridged
    parent: lxdbr0
    type: nic

當 devices 的 eth0 缺少 name 的描述時,容器將無 IP 位置。

lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING |                      | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
|      |         |                      | pf-br0   |
+------+---------+----------------------+----------+
補上 name 的描述:
lxc config device set c1 eth0 name eth0

容器正常執行(不再示例 lxc list)

一律使用 default (profile) 並移除容器設備

lxc config device remove c1 eth0
lxc config device remove c2 eth0
lxc profile assign c1 default
lxc profile assign c2 default

確定 profile 列表無 pf-br0:
lxc profile list

+---------+---------+
|  NAME   | USED BY |
+---------+---------+
| default | 2       |
+---------+---------+

刪除 pf-br0 profile:
lxc profile delete pf-br0
lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 192.168.1.101 (eth0) | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
+------+---------+----------------------+----------+
顯示 profile default:
lxc profile show default

config: {}
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: default
used_by:
- /1.0/instances/c1
- /1.0/instances/c2
顯示 br0 網卡:
lxc network show br0

config: {}
description: ""
name: br0
type: bridge
used_by:
- /1.0/instances/c1
- /1.0/instances/c2
- /1.0/profiles/default
managed: false
status: ""
locations: []

容器固定(靜態) IP

不知道如何以 LXD 的組態來配置,以下是以單一個容器設定靜態 IP 的步驟。

執行容器 (進入容器):
lxc exec c1 bash
查詢 netplan 網路設定檔案:
ls /etc/netplan

得知是
50-cloud-init.yaml
/etc/netplan/50-cloud-init.yaml 的內容
network:
    version: 2
    ethernets:
        eth0:
            dhcp4: true
修改 /etc/netplan/50-cloud-init.yaml 的內容為固定 IP。
network:
    version: 2
    ethernets:
        eth0:
            # dhcp4: true
            addresses: [192.168.1.101/24]
            gateway4: 192.168.1.254
            nameservers:
              addresses: [192.168.1.254]
以 netplan apply 直接變更:
netplan apply
檢查一下 IP 是否合乎預期
ip -c a

LXD 遠端服務

LXD 增加遠端服務的功能要設定要監聽(Listen)的 IP 位置及連接埠。

lxc config set core.https_address :8443
查看 8443 監聽情況:
netstat -nltp | grep 8443

tcp6       0      0 :::8443                 :::*                    LISTEN      823/lxd

雖然只有 tcp6,但在其他只有 IPv4 的主機,連線並無問題。

LXD 遠端服務需要設定連線密碼:

lxc config set core.trust_password myPassword

LXD 4.0 (含以上) 本地端新增遠端主機,可能會出錯。

lxc remote add myServer
Error: Get "https://myServer:8443": lookup myServer: Temporary failure in name resolution

無法加入 myServer,但 ping myServer 是正確的。
LXD 4.0 (含以上) 是用 lookup,它忽略了 /etc/nsswitch.confhost 協定設置如 wins

參閱 DNS 解析服務 設置正確的 DNS 服務器。


本地端新增遠端主機

新增遠端主機(遠端主機即為遠端名稱):
lxc remote add myServer

設定遠端名稱及主機實際 IP(或名稱):
lxc remote add myServer 192.168.1.21

Ubuntu 16 (LXD 2.0.11) 需要指明兩者:
lxc remote add myServer myServer

連線時,可確認 fingerprint 的正確性,fingerprint 可在遠端服務器執行 lxc info 得知。

Generating a client certificate. This may take a minute...
Certificate fingerprint: 512a711cc2618105624d09525ce997823e895de6d5f7b775316dbc51d1aa728b
ok (y/n)? y
Admin password for myServer:
Client certificate stored at server:  myServer
移除遠端主機:
lxc remote remove myServer

再次加入相同的遠端主機:
lxc remote add myServer

第二次沒有要求輸入密碼

遠端服務主機在(被)用戶端連線時,憑證會在初次連接時產生,可透過下列命令管理:

列出受信任的用戶端:
lxc config trust ls

+--------------+--------------+------------------------------+------------------------------+
| FINGERPRINT  | COMMON NAME  |          ISSUE DATE          |         EXPIRY DATE          |
+--------------+--------------+------------------------------+------------------------------+
| d08f211a7849 | user@host1   | Dec 9, 2022 at 12:25am (UTC) | Dec 6, 2032 at 12:25am (UTC) |
+--------------+--------------+------------------------------+------------------------------+
移除用戶端憑證:
lxc config trust remove d08f211a7849

移除憑證後,該用戶端操作遠端服務的功能時會顯示錯誤

$ lxc list myServer:

Error: not authorized

用戶端需移除遠端主機,再新增遠端主機,新增遠端主機時則會要求輸入密碼。


服務器要設定為 IPv4 可以採用本機的 IPv4 的 IP 位置來監聽:

lxc config set core.https_address 192.168.1.21:8443

如果要以本機名稱監聽 IPv4,先把 /etc/hosts 內的本機位置註掉或刪除 (否則監聽的位置為 127.0.1.1):

127.0.0.1       localhost
#127.0.1.1       myServer (1)

# The following lines are desirable for IPv6 capable hosts
...
1 註掉該行
再來以本機名稱監聽:
lxc config set core.https_address myServer:8443
查看 8443 監聽情況:
netstat -nltp | grep 8443

tcp        0      0 192.168.1.21:8443      0.0.0.0:*               LISTEN      2737/lxd
檢查一下 LXD 的設定:
lxc config show

config:
  core.https_address: myServer:8443
  core.trust_password: true

要取消 LXD 的服務器功能,執行下列:

lxc config unset core.https_address

如果連線密碼也要取消,執行下列:

lxc config unset core.trust_password

在不同版本的 LXD 如 4.0 5.0,遠端連線時會有些狀況:

Error: Get "https://myServer:8443": tls: server selected unsupported protocol version 303
Error: Get https://myServer:8443/1.0: remote error: tls: protocol version not supported

遠端連線的 LXD 版本應該要一致,如果無法一致以複製檔案 (如匯出容器檔案、容器影像檔) 方式來解決 。

LXD 3.0.3 4.0.9

本地端 LXD 版本 3.0.3 (myhost),遠端 4.0.9 (myServer),可正確執行 lxc list myServer: (列示遠端容器)、lxc copy myServer:c1 c1 (複製遠端容器至本機),但奇怪的是由本機「傳送」容器至遠端出現下列錯誤:

複製容器至遠端:
lxc copy c1 myServer:c1

Error: Failed container creation: Error transferring instance data: lookup : no such host

改由 4.0.9 「接收」 3.0.3, lxc copy myhost:c1 c1 則正確,再測試 4.0.9 「傳送」至 3.0.3 lxc copy c1 myhost:c1 也正確。

LXD 3.0.3 採用 IP 位置
本地端新增遠端主機:
lxc remote add 192.168.1.21

本地端列出遠端容器:
lxc list 192.168.1.21:

(無錯誤)

複製容器至遠端:
lxc copy c1 192.168.1.21:c1

Error: Failed container creation: Error transferring instance data: lookup : no such host

LXD 快照

讓容器變成不同:

在容器內建立一個檔案:
lxc exec c1 -- touch snap0File

列出建立的檔案:
lxc exec c1 -- ls

snap0File

建立快照:

建立 snap0 快照:
lxc snapshot c1

會建立一個名稱為 snapN 的快照,其中 N 是一個遞增的數字。
建立命名為 mySnapshot1 的快照:
lxc snapshot c1 mySnapshot1

查詢快照:

$lxc info c1

...
Snapshots:
  snap0 (taken at 2022/12/08 16:13 CST) (stateless)
  mySnapshot1 (taken at 2022/12/08 16:16 CST) (stateless)

刪除自訂命名的 mySnapshot1 快照:

lxc delete c1/mySnapshot1

讓容器變成不同:

在容器內,刪除 snap0File, 再建立另一個檔案:
lxc exec c1 -- rm snap0File
lxc exec c1 -- touch NewFile

列示檔案:
lxc exec c1 -- ls

NewFile

恢復快照:

恢復 snap0 快照:
lxc restore c1 snap0

列示檔案:
lxc exec c1 -- ls

snap0File

LXD 容器 轉移/備份

lxc copy

容器複製,命令格式如下:

lxc copy [遠端:]來源容器[/快照名稱] [[遠端:]目標容器] [選項]

lxc copy 選項

--instance-only

只備份實例(無快照)。

容器複製 (預設含快照)

本機複製容器:
lxc copy c1 c3

複製本機容器至遠端:
lxc copy c1 myServer:c1

複製遠端容器至本機:
lxc copy myServer:c1 c1

容器快照複製 (由於已指明快照,將不複製其他快照)。

當容器快照有多個時,如快照順序為 snap0 → mySnapshot1,恢復前一個快照,將會錯誤。

查詢快照:
lxc info c1

...
Snapshots:
  snap0 (taken at 2022/12/08 16:13 CST) (stateless)
  mySnapshot1 (taken at 2022/12/08 16:16 CST) (stateless)

恢復 snap0 快照:
lxc restore c1 snap0

Error: Snapshot "snap0" cannot be restored due to subsequent snapshot(s). Set zfs.remove_snapshots to override

採用容器複製來處理

將容器 c1 的快照 snap0 複製至容器 c1-s0:
lxc copy c1/snap0 c1-s0

lxc export

在 LXD 4.0 (含以後),增加 export / import 指令,能執行匯出、匯入的動作。
容器名稱是由匯出的內容來決定,因此,在匯出時其檔案名稱應為容器名稱作為辨識。

容器匯出,命令格式如下:
lxc export [遠端:]容器 [目標] [選項]
lxc export 選項

--compression

指定壓縮格式支援 bzip2、gz、xz、lzma。

--instance-only

只備份實例(無快照)。

--optimized-storage

根據 help 說明: Use storage driver optimized format (can only be restored on a similar pool), 使用儲存驅動程序優化格式(只能在類似的池上恢復)。

匯出容器 (預設含快照)
$ lxc export c1 c1.tar
Backup exported successfully!
可採用 --compression 指定壓縮格式。
$ lxc export c1 c1.bz2 --compression bzip2
Backup exported successfully!

匯入容器
其容器名稱由檔案的內容來決定,無法變更,如果跟現有容器的名稱相同則會出錯。

lxc import c1.tar

比較一下 LXD Version 4.0.9 在不同的選項、壓縮格式的大小及時間。
註:LXD Version 5.8 的大小及時間合乎預期。

time lxc export c1 c1.tar
time lxc export c1 c1.bz2 --compression bzip2
time lxc export c1 c1.gz --compression gzip
time lxc export c1 c1.lzma --compression lzma
time lxc export c1 c1.xz --compression xz

time lxc export c1 c1-os.tar --optimized-storage
time lxc export c1 c1-os.bz2 --compression bzip2 --optimized-storage
time lxc export c1 c1-os.gz --compression gzip --optimized-storage
time lxc export c1 c1-os.lzma --compression lzma --optimized-storage
time lxc export c1 c1-os.xz --compression xz --optimized-storage
檔案 大小 時間

c1.lzma

206M

9m37.185s

c1.xz

206M

10m2.886s

c1.bz2

285M

2m11.167s

c1.gz

321M

1m0.046s

c1.tar

321M

0m59.767s

檔案 大小 時間

c1-os.lzma

206M

9m37.185s

c1-os.xz

206M

9m50.637s

c1-os.bz2

285M

2m2.900s

c1-os.gz

321M

1m1.752s

c1-os.tar

321M

1m1.419s

lxc publish

將目前的容器發佈成影像檔,命令格式如下:
lxc publish 容器名稱[/快照名稱] [遠端] [選項]
lxc publish 選項

--alias

指定影像檔別名。

--compression

指定壓縮格式支援 bzip2、gz、xz、lzma。

-f, --force

如果容器正在執行,自動停止。

將容器發佈成影像檔

將容器 c1 發佈成 my_c1 影像檔:
lxc publish c1 --alias my_c1

Instance published with fingerprint: fca9356c123004273d9673df8188321da84020df164d09fe257ed727cb310a44

列示影像檔:
lxc image list -c lfda

+-------+--------------+------------------------------------+--------------+
| ALIAS | FINGERPRINT  |            DESCRIPTION             | ARCHITECTURE |
+-------+--------------+------------------------------------+--------------+
| my_c1 | fca9356c1230 | Ubuntu 18.04 LTS server (20221201) | x86_64       |
+-------+--------------+------------------------------------+--------------+

容器以影像檔傳送至遠端

lxc publish c1 --alias my_c1 myServer:

由影像檔建立(初始化)容器:

由別名建立容器 c3:
lxc init my_c1 c3

由 fingerprint 建立容器 c4:
lxc init fca9356c1230 c4

將影像檔匯出成檔案

影像檔 my_c1 匯出檔案:
lxc image export my_c1

Image exported successfully!

輸出的檔案為
fca9356c123004273d9673df8188321da84020df164d09fe257ed727cb310a44.tar.gz

影像檔匯出指定檔名:
lxc image export my_c1 my_c1

輸出的檔案為
my_c1.tar.gz

刪除影像檔

lxc image delete my_c1

LXD 其他命令 (exec、file)

lxc exec 執行容器

執行容器命令格式:
lxc exec [遠端:]容器 [--] 命令列

執行容器:
lxc exec c1 bash

容器執行指令:
lxc exec c1 -- cat /etc/hosts

lxc file 可執行如下命令

delete 刪除容器內的檔案
edit   編輯容器內的檔案
pull   取出容器內的檔案
push   將檔案寫入到容器

取出容器檔案

取出容器檔案的命令格式:
lxc file pull [遠端:]容器/<路徑> [[遠端:]容器/<路徑>...] 目標路徑

容器內的檔案輸出至標準輸出:
lxc file pull c1/etc/hosts -

容器內的檔案寫入至目前路徑:
lxc file pull c1/etc/hosts .

取出遠端容器的檔案輸出至標準輸出:
lxc file pull myServer/etc/hosts -

寫入容器檔案的命令格式如下(不再示例):

lxc file push <來源路徑> [遠端:]容器/<路徑> [[遠端:]容器/<路徑>...]

(以常用的編輯器) 編輯容器內檔案

編輯容器內檔案的命令格式:
lxc file edit [遠端:]容器/<路徑>

編輯 c1 容器的 /etc/hosts
lxc file edit c1/etc/hosts

更新(遷移) LXD 版本

Ubuntu 16 / 18 (非以 Snap) 安裝 LXD,遷移至 Snap LXD。

在遷移 LXD 版本前最好先備份容器。
以 root 帳戶執行 (不想每次輸入 sudo):
su

檢查目前的版本:
lxd --version

確定容器儲存路徑是否包含 c1 c2 (註:「lXD 建立容器」範例中建立兩個容器):
ls /var/lib/lxd/containers

c1  c2
安裝 Snap
apt install snapd -y

查詢 Snap 版本:
snap version

snap    2.57.5+18.04ubuntu0.1
snapd   2.57.5+18.04ubuntu0.1
series  16
ubuntu  18.04
kernel  4.15.0-118-generic
安裝 LXD 4.0 穩定版
snap install lxd --channel=4.0/stable

檢查目前的版本:
lxd --version

還沒有遷移,版本沒變。
執行遷移
lxd.migrate

Are you ready to proceed (yes/no) [default=no]? yes
你準備好繼續了嗎? 當然要輸入 yes。

在遷移的過程中,會停止原始 (舊) 的 LXD:
=> Shutting down the source LXD
=> Stopping the source LXD units
=> Stopping the destination LXD unit
=> Unmounting source LXD paths
=> Unmounting destination LXD paths
=> Wiping destination LXD clean
=> Backing up the database
=> Moving the data
=> Updating the storage backends
=> Starting the destination LXD
=> Waiting for LXD to come online


Do you want to uninstall the old LXD (yes/no) [default=yes]?
你要解除安裝舊有的 LXD 嗎?  按下 Enter (預設值為 yes)

遷移完成後如下訊息:
All done. You may need to close your current shell and open a new one to have the "lxc" command work.
To migrate your existing client configuration, move ~/.config/lxc to ~/snap/lxd/common/config
遷移後,LXD 程式路徑已變更
遷移後,執行 LXD 會出錯,因為 LXD 程式路徑已改變成 Snap 的路徑:
lxd version

-bash: /usr/bin/lxd: No such file or directory

重置 bash 記憶程式的路徑:
hash -r

再執行 lxd 應該正確:
lxd version

4.0.9

檢查容器是否遷移:
lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 192.168.1.101 (eth0) | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
+------+---------+----------------------+----------+
LXD 容器的儲存位置已變更
LXD 容器的儲存位置已變更, 錯誤是正常的:
ls /var/lib/lxd/containers

ls: cannot access '/var/lib/lxd/containers': No such file or directory

Snap 的 LXD 位置 /var/snap/lxd/common/lxd 同等於 /var/lib/lxd:
ls /var/snap/lxd/common/lxd/containers

c1  c2

Snap LXD 更新版本

更新版本後可能無法降級,更新版本前應先備份容器。
以 root 帳戶執行 (不想每次輸入 sudo):
su

檢查目前的版本:
lxd version

4.0.9
安裝最新穩定版:
snap install lxd --channel=latest/stable

snap "lxd" is already installed, see 'snap help refresh'
install 出錯,要採用 refresh。

昇級為最新穩定版:
snap refresh lxd --channel=latest/stable

檢查一下版本:
lxd version

5.8

檢查容器是否存在:
lxc list -c ns4P

+------+---------+----------------------+----------+
| NAME |  STATE  |         IPV4         | PROFILES |
+------+---------+----------------------+----------+
| c1   | RUNNING | 192.168.1.101 (eth0) | default  |
+------+---------+----------------------+----------+
| c2   | RUNNING | 192.168.1.102 (eth0) | default  |
+------+---------+----------------------+----------+

Snap LXD 版本降級測試,實測會出錯。可能有解決方式,但需要時間研究。

由 LXD 5.8 降級成 4.0 穩定版, 執行出錯:
snap refresh lxd --channel=4.0/stable

2022-12-08T04:10:01+08:00 INFO Waiting for "snap.lxd.daemon.service" to stop.
error: cannot perform the following tasks:
- Start snap "lxd" (24061) services (systemctl command [start snap.lxd.activate.service] failed with exit status 1: Job for snap.lxd.activate.service failed because the control process exited with error code.
See "systemctl status snap.lxd.activate.service" and "journalctl -xe" for details.
)

版本未變更:
lxd version

5.8

降級成 LXD 3.0 穩定版, 執行後並未顯示錯誤 (註:由 4.0 降級 3.0 也未顯示錯誤):
snap refresh lxd --channel=3.0/stable

2022-12-10T21:48:12Z INFO Waiting for "snap.lxd.daemon.service" to stop.
lxd (3.0/stable) 3.0.4 from Canonical✓ refreshed

檢查版本:
lxd version

3.0.4

但事實上已經出錯:
lxc list

If this is your first time running LXD on this machine, you should also run: lxd init
To start your first container, try: lxc launch ubuntu:18.04

Error: Get http://unix.socket/1.0: dial unix /var/snap/lxd/common/lxd/unix.socket: connect: connection refused

錯誤說明中提到 lxd init (已經執行過了), 那就試試看:
lxd init

Error: Failed to connect to local LXD: Get http://unix.socket/1.0: dial unix /var/snap/lxd/common/lxd/unix.socket: connect: connection refused

LXD 沒有監聽:
netstat -lnp | grep lxd

已知 LXD 服務未啟動:
snap start lxd

error: cannot perform the following tasks:
- Run service command "start" for services ["activate" "daemon"] of snap "lxd" (systemctl command [start snap.lxd.activate.service] failed with exit status 1: Job for snap.lxd.activate.service failed because the control process exited with error code.
See "systemctl status snap.lxd.activate.service" and "journalctl -xe" for details.
)

試著更新成 LXD 4.0 穩定版, 掛掉:
snap refresh lxd --channel=4.0/stable

Start snap "lxd" (24061) services
Start snap "lxd" (24061) services
Start snap "lxd" (24061) services
...

在另一個終端機檢查 Snap LXD 版本:
snap list

Name    Version        Rev    Tracking       Publisher   Notes
core    16-2.57.6      14399  latest/stable  canonical✓  core
core20  20221123       1738   latest/stable  canonical✓  base
lxd     4.0.9-a29c6f1  24061  4.0/stable     canonical✓  -
snapd   2.57.6         17883  latest/stable  canonical✓  snapd

重開機後啟動 LXD:
lxd

WARN[12-10|22:19:54]  - Couldn't find the CGroup blkio.weight, disk priority will be ignored
WARN[12-10|22:19:54]  - Couldn't find the CGroup memory swap accounting, swap limits will be ignored
WARN[12-10|22:19:54] Instance type not operational            type=virtual-machine driver=qemu err="KVM support is missing"
EROR[12-10|22:19:54] Failed to start the daemon               err="Error creating database: schema version '43' is more recent than expected '42'"
Error: Error creating database: schema version '43' is more recent than expected '42'

LXD 錯誤訊息

下列的問題及解答(或原因),其「解答(或原因)」並非唯一答案,會有其他操作而有相同錯誤訊息的情況。

  1. Error: Get "http://unix.socket/1.0": dial unix /var/snap/lxd/common/lxd/unix.socket: connect: permission denied

    目前使用者不在 lxd 群組。

  2. Error: Get http://unix.socket/1.0: dial unix /var/snap/lxd/common/lxd/unix.socket: connect: connection refused

    昇降級 LXD 後執行 lxc list 出錯,LXD 服務未啟動。

  3. Error: Get https://myServer:8443/1.0: x509: certificate signed by unknown authority (possibly because of "x509: ECDSA verification failure" while trying to verify candidate authority certificate "root@myServer")

    遠端主機憑證不正確,可能是重新安裝 LXD 造成。

    重新加入遠端主機可解決
    lxc remote remove myServer
    lxc remote add myServer
  4. Error: not authorized

    遠端主機移除用戶端憑證,如遠端主機執行 lxc config trust remove <hostname|fingerprint>
    重新加入遠端主機可解決。

  5. Unable to connect to: myServer:8443

    遠端主機 myServer 未啟用遠端服務。

  6. lookup myServer: Temporary failure in name resolution

    本機 DNS 解析服務不正確。

  7. lookup myServer: device or resource busy

    本機對遠端主機 myServer 操作,本機 DNS 解析服務不正確。

  8. Error transferring instance data: lookup myhost: device or resource busy

    本機 myhost 複製容器至遠端主機,錯誤訊息是 myhost,遠端主機 DNS 解析服務設置不正確。

LXD 命令示例

影像檔類
lxc image list
lxc image export myContainer myContainer

lxc publish 容器名稱[/快照名稱] [遠端] [選項]
lxc publish myContainer --alias myImage
lxc profile
lxc profile list
lxc profile create myProfile
lxc profile show myProfile
lxc profile rename myProfile MyProfile
lxc profile add myContainer myProfile
lxc profile remove myContainer myProfile
lxc profile assign myContainer default,myProfile
容器類
lxc list -c ns4P
lxc init ubuntu:18.04 myContainer -p default -p myProfile
lxc launch ubuntu:18.04 myContainer -p default -p myProfile
lxc start myContainer
lxc restart myContainer
lxc pause myContainer
lxc stop myContainer
lxc delete myContainer
lxc rename myContainer MyContainer

lxc copy [遠端:]來源[/快照] [[遠端:]目標] [選項]
lxc copy myContainer MyContainer
執行容器
lxc exec [遠端:]容器 [--] 命令列
lxc exec myContainer bash
lxc exec myContainer -- cat /etc/hosts
容器檔案處理
lxc file pull [遠端:]容器/<路徑> [[遠端:]容器/<路徑>...] 目標路徑
lxc file pull myContainer/etc/hosts -
lxc file pull myServer/etc/hosts -

lxc file push <來源路徑> [遠端:]容器/<路徑> [[遠端:]容器/<路徑>...]

lxc file edit [遠端:]容器/<路徑>
lxc file edit myContainer/etc/hosts
lxc remote
lxc remote list
lxc remote add myServer
lxc remote remove myServer
lxc config
lxc config set core.https_address :8443
lxc config set core.trust_password myPassword
lxc config unset core.trust_password
lxc config show
lxc config show myContainer
其他
lxc info
lxc info myContainer

設備設置

lxc network
lxc network list
lxc network show lxdbr0
lxc network attach lxdbr0 myContainer eth0 eth0
lxc network detach lxdbr0 myContainer
lxc network set lxdbr0 ipv4.firewall false
lxc network set lxdbr0 ipv6.nat false
lxc config device
lxc config device add myContainer eth0 nic nictype=bridged parent=lxdbr0 name=eth0
lxc config device remove myContainer eth0
lxc config device unset myContainer eth0 name
lxc config device set myContainer eth0 name eth0
lxc config device list myContainer
lxc profile device
lxc profile device add myProfile eth0 nic nictype=bridged parent=br0 name=eth0
lxc profile device unset myProfile eth0 name
lxc profile device set myProfile eth0 name eth0
lxc profile device set myProfile eth0 parent br0
lxc profile device set myProfile eth0 nictype bridged
lxc profile device remove myProfile eth0