Ubuntu LXC

建立 LXC 容器

安裝 LXC
sudo apt install lxc -y
lxc-create 看嘸的語法
lxc-create --help
lxc-create --name=NAME --template=TEMPLATE [OPTION...]
Options :
  -n, --name=NAME               NAME of the container
  -t, --template=TEMPLATE       Template to use to setup container

實在是看不懂,只好上網找,消化一下整理並簡化。

lxc-create 消化後的語法
lxc-create -t download -n $lxcname -- -d ubuntu -r $release -a amd64
-t download 快取資料夾 (1)
--name (新建的) 容器名稱 $lxcname (2)
--dist 作業系統 ubuntu
--release 作業系統版本 (release) (3)
--arch 指定架構 amd64。
1 下載的 lxc 儲存在 /var/cache/lxc/download
2 容器檔案會放在 /var/lib/lxc/$lxcname
3 $release 是什麼? 這裡的參數 bionic 是 ub18,xenial 是 ub16,那其他版本呢? Releases - Ubuntu Wiki
Version     Code name       $releae
Ubuntu 20   Focal Fossa     focal
Ubuntu 18   Bionic Beaver   bionic
Ubuntu 16   Xenial Xerus    xenial
Ubuntu 14   Trusty Tahr     trusty

先別急著建立容器,建議您看一下 設置 LXC 採用 br0 橋接網路

建立 base18 容器
# 容器命名為 base18, 先建立基本容器, 安裝基本功能後再複製至新容器
lxcname=base18
sudo lxc-create -t download -n $lxcname -- -d ubuntu -r bionic -a amd64 (1)
1 若出現下列錯誤,等一段時間再試一次。
ERROR: Unable to fetch GPG key from keyserver.
啟動容器
lxcname=base18

# 啟動容器
sudo lxc-start -n $lxcname (1)

# 登入容器,帳戶為 root 帳戶
sudo lxc-attach -n $lxcname

# 設定 root 帳戶密碼
passwd

# 設定 ubuntu 帳戶密碼 (已有 ubuntu 及 www-data 帳戶)
# ubuntu 帳戶密碼預設值為 ubuntu
passwd ubuntu

# 採用 dist-upgrade 更新
apt update && apt dist-upgrade -y

# lxc 可安裝常用套件 nano
apt install nano -y

# 可接續安裝其他套件或調整 (2)

# 離開容器
exit
1 依據版本不同可能不需要 -n 參數,如 sudo lxc-start $lxcname
2 可依據 Ubuntu 安裝手冊 安裝必要套件。

LXC 設置

LXC 全局設置 /etc/default/lxc-net
USE_LXC_BRIDGE="true"(1)
1 "true" 表示啟用 lxcbr0 (LXC 內建的 NAT) 介面,"false" 則為取消。
編輯容器組態
lxcname=base18
nano /var/lib/lxc/$lxcname/config
/var/lib/lxc/$lxcname/config
# 可加入 LXC 自動開機
lxc.start.auto = 1

# Container specific configuration
lxc.uts.name = base18 (1)

# Network configuration
# Ubuntu 18
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0 (2)
# lxc.net.0.link = br0 (3)
# lxc.net.0.ipv4 = 192.168.1.102/24 (4)
# lxc.net.0.ipv4.gateway = 192.168.1.254

# Ubuntu 16
lxc.network.type = veth
lxc.network.link = lxcbr0 (2)
# lxc.network.link = br0 (3)
# lxc.network.ipv4 = 192.168.1.102/24 (4)
# lxc.network.ipv4.gateway = 192.168.1.254
1 指定容器的名稱,一般會指定成容器目錄名稱,但該值似乎無作用。
2 lxcbr0:LXC 預設的 NAT 網路介面。
3 自行建立的 br0 橋接網路介面。
4 如果容器採用固定 IP 按實際修改。

前續的步驟完成,再複製 LXC 容器。

lxcname=base18
newlxc=new18
lxc-stop -n $lxcname

# lxc-copy [-n] <container-name> -N <new-container-name>
lxc-copy -n $lxcname -N $newlxc (1)
1 $newlxc 是 容器名稱容器主機名稱 沒有關係,記得要去改新容器內的主機名稱。

LXC 常用指令

#檢查版本
lxc-info --version

# 判斷 linux 核心是否支援 LXC
lxc-checkconfig

lxc-ls --help

# 列出容器
lxc-ls -f

lxcname=base18

# 修改組態
nano /var/lib/lxc/$lxcname/config

# 啟動容器
lxc-start -n $lxcname
# 註: 在舊版的 lxc 需要前置 -n,如 lxc-start -n $lxcname

# 停止容器
lxc-stop -n $lxcname

# 登入容器,帳戶為 root 帳戶
lxc-attac -n $lxcname

# 登入容器 (需要輸入使用者名和密碼)
lxc-console -n $lxcname

# 檢查佔用多少記憶體及其他狀態
lxc-info -n $lxcname

# 複製容器
# lxc-copy [-n] <container-name> -N <new-container-name>
lxc-stop -n $lxcname
lxc-copy -n $lxcname -N <new-container-name>

# 刪除容器
lxc-destroy -n <container-name>

設置 LXC 採用 br0 橋接網路

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

先完成下列,再取消 LXC 預設 NAT 橋接。

/etc/default/lxc-net
# USE_LXC_BRIDGE="true"
USE_LXC_BRIDGE="false"(1)
1 取消 LXC 的橋接。

修改 LXC 建立容器的預設值,將網路介面指向橋接介面。

/etc/lxc/default.conf
lxc.net.0.type = veth
#lxc.net.0.link = lxcbr0
lxc.net.0.link = br0(1)

lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
1 LXC 的網路介面指向橋接 br0 介面

調整容器組態,檔案在 Host 主機上

/var/lib/lxc/$lxcname/config
# Network configuration
lxc.net.0.type = veth
# lxc.net.0.link = lxcbr0
lxc.net.0.link = br0(1)

lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:77:ee:2c

# lxc.net.0.ipv4 = 192.168.1.102/24(2)
# lxc.net.0.ipv4.gateway = 192.168.1.254

lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:77:ee:2c
1 LXC 的網路介面指向橋接 br0 介面
2 如果容器採用固定 IP 按實際修改。

LXC 容器橋接測試

進入容器,檢查一下位置是否為 LAN (別忘了,如果是在設置之前已啟動容器,應該重啟它)

lxcname=base18
lxc-start -n $lxcname
lxc-attach -n $lxcname
ifconfig (1)
ip a
ip -c a
1 出錯 bash: ifconfig: command not found,可參考: command line - ifconfig missing after Ubuntu 18.04 install - Ask Ubuntu , 改用 ip 吧!如果要用 ifconfig,則安裝 sudo apt install net-tools,或者查看 sudo apt-cache search ifconfig 看是要裝那一個。

LXC 容器備份

容器以 tar 壓縮或解壓縮只有一個重點,採用 --numeric-owner 保留容器檔案權限。

關於 --numeric-owner

LXC 容器檔案的 uid/gid (User Identifier/Group Identifier) 為容器專屬, 但執行 tar 的 Host 系統會嘗試解析容器檔案的 uid/gid,解決檔案擁有權問題。 採用 --numeric-owner 保留容器檔案的 uid/gid, 不要讓 Host 去做一些跟自己毫無關係的解析動作,若將其解析為其他值則會發生不良情況。

參考: ubuntu - How do I Backup / Move LXC containers? - Stack Overflow

The --numeric-owner flag is very important! Without it, the container may not boot because the uid/gids get mangled in the extracted file system.

容器備份及傳送

停止容器
lxcname=base18
cd /var/lib/lxc/$lxcname
lxc-stop -n $lxcname
壓縮時直接在共享目錄建立 tar 檔案 (Windows shared folder)
tar --numeric-owner -czvf /mnt/share/$lxcname.tar.gz ./*
壓縮時直接將壓縮檔以 ssh 傳送至目標主機
# 切換目錄至來源容器
# cd /var/lib/lxc/$lxcname

# 設定目標主機的 root 帳戶及主機位置
UserHost='root@192.168.1.1'

# LXC 的容器名稱,這時要決定。
# 先檢查目標主機
ssh $UserHost ls /var/lib/lxc/
# 新容器名稱
newlxc=base18

# 建立目標主機資料夾
ssh $UserHost mkdir /var/lib/lxc/$newlxc
tar --numeric-owner -czvf - ./* | ssh $UserHost "cat > /var/lib/lxc/$newlxc/clone.tar.gz"
目標主機解壓
# ssh $UserHost

newlxc=base18

# 直接解壓 Windows shared folder 內的 tar
mkdir /var/lib/lxc/$newlxc/
cd /var/lib/lxc/$newlxc/
tar --numeric-owner -xzvf /mnt/share/base18.tar.gz .

# 目標主機已有, 直接解壓即可
cd /var/lib/lxc/$newlxc/
tar --numeric-owner -xzvf clone.tar.gz .
調整目標主機內容器名稱
newlxc=base18

# 若需要產生 MAC
OID="00:16:3e"
RAND=$(echo $newlxc | md5sum | sed 's/\(..\)\(..\)\(..\).*/\1:\2:\3/')
echo "$OID:$RAND"

# 修改容器組態
nano /var/lib/lxc/$newlxc/config

# 啟動容器
lxc-start -n $newlxc
lxc-attach -n $newlxc

# 修改容器內的主機名稱
nano /etc/hostname
nano /etc/hosts

# 離開容器
exit

# 重啟容器, 以便更新容器入的主機名稱
lxc-stop -n $newlxc
lxc-start -n $newlxc