====== 安裝 Ubuntu + LXD 移轉 PVE 內的舊 CT ======
* 主要是因為在 Proxmox 內有一些 CentOS 7 的 CT 導致無法升級 PVE 到 9.x (參考 [[tech/pve6_and_pve7|讓_pve_6_內的_centos7_的_ct_移轉至_pve_7_的妥協做法]]
* 因為這些 CentOS 7 的 CT 內服務不易移轉到其他新版的 OS, 所以嘗試將這些 CT 由 Proxmox 移轉到 Ubuntu 24.04 (VM) 內使用 LXD 來管理
===== 0. 建立 Ubuntu 24.04 VM =====
* 安裝標準 Ubuntu 24.04 (4Core, 4G RAM 60G SSD)
* Network :
* IP : 192.168.1.210/24
* GW : 192.168.1.1
* 建立給 lxd 使用 bridge ens18 網路
apt update && apt install -y bridge-utils
mkdir -p /root/netplan-backup
mv /etc/netplan/*.yaml /root/netplan-backup/
cat > /etc/netplan/01-netcfg.yaml << 'EOF'
network:
version: 2
renderer: networkd
ethernets:
ens18:
dhcp4: no
dhcp6: no
bridges:
br0:
interfaces: [ens18]
addresses: [192.168.1.210/24]
routes:
- to: default
via: 192.168.1.1
metric: 100 # 明確 metric,避免衝突
nameservers:
addresses: [1.1.1.1, 8.8.8.8]
parameters:
stp: false
forward-delay: 0
EOF
netplan generate # 應無錯誤/警告
netplan apply # 套用(暫斷網幾秒;用 console 執行以防 SSH 斷)
===== 1. 使用 Snap 安裝 LXD 與相關配置 =====
==== 安裝 LXD ====
*
# 安裝 snapd
apt update
apt install snapd -y
# 安裝 LXD
snap install lxd
# 初始化 LXD
lxd init --auto
==== 設定讓 cgroupv1 可以使用的 systemd 服務 ====
* /usr/local/bin/mount-cgroup-v1.sh
# 建立 systemd 服務來自動 mount v1 控制器(持久化,重啟後生效):
# 建立啟動腳本(mount)
cat > /usr/local/bin/mount-cgroup-v1.sh << 'EOF'
#!/bin/bash
set -e
# 建立目錄(新增 systemd)
mkdir -p /sys/fs/cgroup/{cpu,cpuacct,cpuset,memory,devices,freezer,blkio,net_cls,net_prio,pids,perf_event,systemd}
# Mount v1 控制器(新增 systemd)
mount -t cgroup -o none,name=cpu cpu /sys/fs/cgroup/cpu || true
mount -t cgroup -o none,name=cpuacct cpuacct /sys/fs/cgroup/cpuacct || true
mount -t cgroup -o none,name=cpuset cpuset /sys/fs/cgroup/cpuset || true
mount -t cgroup -o none,name=memory memory /sys/fs/cgroup/memory || true
mount -t cgroup -o none,name=devices devices /sys/fs/cgroup/devices || true
mount -t cgroup -o none,name=freezer freezer /sys/fs/cgroup/freezer || true
mount -t cgroup -o none,name=blkio blkio /sys/fs/cgroup/blkio || true
mount -t cgroup -o none,name=net_cls net_cls /sys/fs/cgroup/net_cls || true
mount -t cgroup -o none,name=net_prio net_prio /sys/fs/cgroup/net_prio || true
mount -t cgroup -o none,name=pids pids /sys/fs/cgroup/pids || true
mount -t cgroup -o none,name=perf_event perf_event /sys/fs/cgroup/perf_event || true
mount -t cgroup -o none,name=systemd systemd /sys/fs/cgroup/systemd || true
echo "cgroup v1 controllers (incl. systemd) mounted successfully."
EOF
* /usr/local/bin/umount-cgroup-v1.sh
# 更新 umount 腳本(新增 systemd)
cat > /usr/local/bin/umount-cgroup-v1.sh << 'EOF'
#!/bin/bash
set -e
umount /sys/fs/cgroup/systemd 2>/dev/null || true
umount /sys/fs/cgroup/perf_event 2>/dev/null || true
umount /sys/fs/cgroup/pids 2>/dev/null || true
umount /sys/fs/cgroup/net_prio 2>/dev/null || true
umount /sys/fs/cgroup/net_cls 2>/dev/null || true
umount /sys/fs/cgroup/blkio 2>/dev/null || true
umount /sys/fs/cgroup/freezer 2>/dev/null || true
umount /sys/fs/cgroup/devices 2>/dev/null || true
umount /sys/fs/cgroup/memory 2>/dev/null || true
umount /sys/fs/cgroup/cpuset 2>/dev/null || true
umount /sys/fs/cgroup/cpuacct 2>/dev/null || true
umount /sys/fs/cgroup/cpu 2>/dev/null || true
echo "cgroup v1 controllers unmounted."
EOF
# 設定權限
chmod +x /usr/local/bin/mount-cgroup-v1.sh /usr/local/bin/umount-cgroup-v1.sh
* /etc/systemd/system/cgroup-v1-legacy.service
# 建立單位檔案
cat > /etc/systemd/system/cgroup-v1-legacy.service << 'EOF'
[Unit]
Description=Mount legacy cgroup v1 controllers for LXC containers
After=systemd-remount-fs.service
Before=lxd.service
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/bin/mount-cgroup-v1.sh
ExecStop=/usr/local/bin/umount-cgroup-v1.sh
[Install]
WantedBy=multi-user.target
EOF
* 啟用服務:
systemctl daemon-reload
systemctl enable --now cgroup-v1-legacy.service
systemctl restart cgroup-v1-legacy.service
systemctl status cgroup-v1-legacy.service
* 驗證 mount(檢查主機):
mount | grep cgroup # 應看到多個 v1 mount 如 /sys/fs/cgroup/cpu 等
cat /proc/cgroups # 應顯示 v1 控制器可用
===== 2. 將 proxmox 的 ct 匯出 =====
* Exp. 將 proxmox 的 ct-118 使用 vzdump 產生的 vzdump-lxc-118-2025_11_13-14_03_41.tar 複製到 Ubuntu VM 內
vzdump 118 --dumpdir /tmp
scp /tmp/vzdump-lxc-118-2025_11_13-14_03_41.tar jonathan@192.168.1.210:/tmp
===== 3. 建立 LXD image =====
* 使用 root 權限執行
sudo -i
mkdir test
mv /tmp/vzdump-lxc-118-2025_11_13-14_03_41.tar test/
cd test
tar -xvf vzdump-lxc-118-2025_11_13-14_03_41.tar
ls -la
# (會看到一堆檔案)
# 查看系統版本
cat etc/os-release
* 將當前目錄的所有系統檔案打包成 rootfs
# 排除原始備份檔
tar --numeric-owner -czf rootfs.tar.gz \
--exclude='vzdump-lxc-118-2025_11_13-14_03_41.tar' \
--exclude='rootfs.tar.gz' \
.
# 檢查打包結果
ls -lh rootfs.tar.gz
* LXD 需要 metadata 檔案來識別映像
cat > metadata.yaml << 'EOF'
architecture: x86_64
creation_date: 1699862400
properties:
description: CentOS 7 from Proxmox CT-118
os: centos
release: "7"
EOF
# 打包 metadata
tar -czf metadata.tar.gz metadata.yaml
# 確認兩個檔案都存在
ls -lh metadata.tar.gz rootfs.tar.gz
===== 4. 建立與啟動 LXD 容器 =====
* 導入為 LXD 映像 Exp. ct-linsport
lxc image import metadata.tar.gz rootfs.tar.gz --alias ct-linsport
* 查看導入的映像
lxc image list
root@lin-web-210:~/test# lxc image list
+-------------+--------------+--------+------------------------------+--------------+-----------+------------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+-------------+--------------+--------+------------------------------+--------------+-----------+------------+------------------------------+
| ct-linsport | 62085b012d6b | no | CentOS 7 from Proxmox CT-118 | x86_64 | CONTAINER | 1633.91MiB | Nov 13, 2025 at 6:20am (UTC) |
+-------------+--------------+--------+------------------------------+--------------+-----------+------------+------------------------------+
* 從映像創建容器 Exp. ct-118
lxc init ct-linsport ct-118
* 設定權限配置參數檔 ct-118-raw.conf 與相關權限設定
cat > ct-118-raw.conf << 'EOF'
# 放寬安全限制
lxc.apparmor.profile=unconfined
lxc.cap.drop=
# 自動 mount:proc rw、sys mixed、cgroup mixed(關鍵:自動處理 v1)
lxc.mount.auto=proc:rw sys:mixed cgroup:mixed
# 手動 bind v1 控制器(僅 systemd 作為補充,optional)
lxc.mount.entry=/sys/fs/cgroup/systemd /sys/fs/cgroup/systemd none bind,create=dir,optional 0 0
EOF
# 讀取並設定
lxc config set ct-118 raw.lxc "$(cat ct-118-raw.conf)"
# 設定特權模式
lxc config set ct-118 security.privileged true
lxc config set ct-118 security.nesting true
* 設定容器可以對外連結虛擬網卡
# Override eth0 為獨立 nic type(移除 profile 影響)
lxc config device override ct-118 eth0 type=nic
# 移除 eth0(現在可移除,因為已 override)
lxc config device remove ct-118 eth0
# 新增全新 eth0 nic:macvlan 模式,綁 ens18
lxc config device add ct-118 eth0 nic nictype=bridged parent=br0 name=eth0
* 啟動容器
# 啟動容器
lxc start ct-118
# 查看容器狀態
lxc list
===== 5. 進入容器測試 =====
*
# 進入容器
lxc exec ct-118 -- bash
# 檢查系統
cat /etc/redhat-release
hostname
ip addr
systemctl status
# 退出
exit
===== FAQ =====
==== 1. 發現無法自動啟動服務 (systemctl 權限問題) ====
* Ubuntu 24.04 host 要先設定好 mount-cgroup-v1.sh / umount-cgroup-v1.sh / cgroup-v1-legacy.service 這些環境配置
* 重建容器與設定正確權限
# 停止容器(如果卡住)
lxc stop ct-118 --force || true
# 刪除容器 (保留映像)
lxc delete ct-118
# 重新創建
lxc init ct-linsport ct-118
# 創建設定檔案(完整的 systemd 支援配置)
cat > ct-118-raw.conf << 'EOF'
# 放寬安全限制
lxc.apparmor.profile=unconfined
lxc.cap.drop=
# 自動 mount:proc rw、sys mixed、cgroup mixed(關鍵:自動處理 v1)
lxc.mount.auto=proc:rw sys:mixed cgroup:mixed
# 手動 bind v1 控制器(僅 systemd 作為補充,optional)
lxc.mount.entry=/sys/fs/cgroup/systemd /sys/fs/cgroup/systemd none bind,create=dir,optional 0 0
EOF
# 讀取並設定
lxc config set ct-118 raw.lxc "$(cat ct-118-raw.conf)"
# 設定特權模式
lxc config set ct-118 security.privileged true
lxc config set ct-118 security.nesting true
# 啟動容器
lxc start ct-118
# 檢查容器狀態
lxc info ct-118
# 查看啟動日誌
lxc info ct-118 --show-log | tail -50
# 等待幾秒讓系統啟動
sleep 5
# 檢查狀態
lxc info ct-118 | grep Processes
# 查看容器狀態
lxc list
==== 2. 發現容器無法對外連結 =====
* 要在 Ubuntu 24.04 Host 建立可以對外網卡的 Bridge Exp. br0
* 將原本容器的網卡刪除更換成這 br0 Exp.
# Override eth0 為獨立 nic type(移除 profile 影響)
lxc config device override ct-118 eth0 type=nic
# 移除 eth0(現在可移除,因為已 override)
lxc config device remove ct-118 eth0
# 新增全新 eth0 nic:macvlan 模式,綁 ens18
lxc config device add ct-118 eth0 nic nictype=bridged parent=br0 name=eth0
==== 3. 如何啟動 Web UI =====
* 設定 config
root@lin-web-210:~# lxd --version
5.21.4 LTS
root@lin-web-210:~# lxc config set core.https_address [::]
root@lin-web-210:~# lxc config set core.https_address 0.0.0.0:8443
root@lin-web-210:~# lxc config show
config:
core.https_address: 0.0.0.0:8443
root@lin-web-210:~# lxc config trust list
+------+------+-------------+-------------+------------+-------------+
| TYPE | NAME | COMMON NAME | FINGERPRINT | ISSUE DATE | EXPIRY DATE |
+------+------+-------------+-------------+------------+-------------+
* 因為 LXD Web UI 是採用雙向 SSL 認證方式, 所以第一次進入網址要產生與下載憑證 Exp. https://192.168.1.210:8443
- 瀏覽器會彈出選擇憑證, 如果沒有憑證或取消就會進入 Step 1. TLS login 設定畫面 \\ {{:tech:螢幕擷取畫面_2025-11-14_103428.png?1000|}}
- 下載憑證( Exp. lxd-ui-192.168.1.210.pfx )後匯入讓瀏覽器可以使用
- 開啟瀏覽器無痕模式, 彈出選擇憑證時, 選擇剛剛匯入的憑證 Exp. \\ {{:tech:螢幕擷取畫面_2025-11-14_104711.png|}}
- 看到網頁 Step 2. 設定畫面
- 回到 LXD Server 執行 lxc auth identity create tls/lxd-ui --group admins產生 identity token Exp.
root@lin-web-210:~# lxc auth identity create tls/lxd-ui --group admins
TLS identity "tls/lxd-ui" (4fd2xxxx-xxxx-xxxx-xxxx-xxxxxxxx88bc) pending identity token:
eyJjbGllbnxxxxxxxxxxxxxxxxxxxxIsImZpbmdlcnByaW5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmI2NSIsImFkZHJlc3NlcyI6WyIxOTIuMTY4LjExLxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0aWZpY2F0ZSJ9
- 將產生的 identity token 貼上 Step 2. \\ {{:tech:螢幕擷取畫面_2025-11-14_104936.png?1000|}}
- 點下 Connet 後就會進入 Web UI \\ {{:tech:螢幕擷取畫面_2025-11-14_105240.png?1000|}} \\ {{:tech:螢幕擷取畫面_2025-11-14_105422.png?1000|}}
* 如果需要設定透過反向代理 Exp. NPM 原本雙向 SSL 認證就無法順利傳遞, 必須要增加設定 OIDC (Exp. Google oAuth 認證) 方式來達成, 可參考 - [[tech/ubuntu_lxd/oidc]]
{{tag>pve ct lxd}}