使用 LXD 的一些小技巧

稍微紀錄一下一些 LXD 環境設定的步驟

轉發某個 Port 到 LXD 上

lxc launch ubuntu:18.04 Apache

假設你的 container 叫做 Apacche,並且已經安裝好所需的東西

+--------+---------+------+-----------------------------------------------+------------+-----------+
|  NAME  |  STATE  | IPV4 |                     IPV6                      |    TYPE    | SNAPSHOTS |
+--------+---------+------+-----------------------------------------------+------------+-----------+
| Apache | RUNNING |      | fd42:d75f:90b5:e90b:216:3eff:fe88:e8ac (eth0) | PERSISTENT | 0         |
+--------+---------+------+-----------------------------------------------+------------+-----------+

透過以下指令新增一個 Proxy,取名為 myport80,把所有所有 IP(0.0.0.0)到 Port 80 的連入連線,轉發到本機(容器)的 port 80

lxc config device add Apache myport80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80

在容器外重新 curl 一次就能確認結果了

play_pc at lxd_server in ~
$ curl localhost

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <!--
    Modified from the Debian original for Ubuntu
    Last updated: 2016-11-16
    See: https://launchpad.net/bugs/1288690

...下略...

在 LXD 裡面使用 VPN

lxc launch ubuntu:18.04 OpenVPN

假設你的 container 叫做 OpenVPN

+---------+---------+---------------------+-----------------------------------------------+------------+-----------+
|  NAME   |  STATE  |        IPV4         |                     IPV6                      |    TYPE    | SNAPSHOTS |
+---------+---------+---------------------+-----------------------------------------------+------------+-----------+
| OpenVPN | RUNNING | 10.52.196.93 (eth0) | fd42:d75f:90b5:e90b:216:3eff:fe7a:b07a (eth0) | PERSISTENT | 0         |
+---------+---------+---------------------+-----------------------------------------------+------------+-----------+

加入 tun 裝置

lxc config device add OpenVPN tun unix-char path=/dev/net/tun

安裝 OpenVPN 軟體

lxc exec OpenVPN -- apt install openvpn -y

進入 Container

lxc exec OpenVPN -- bash

[Optional] 如果你的 OpenVPN Server 需要帳號密碼的話,記得存在一個檔案裡面,等一下會用到

vim /etc/openvpn/ovpn_pass.txt
chmod 600 /etc/openvpn/ovpn_pass.txt

格式如下:

帳號
密碼

然後記得要在 .ovpn 檔案裡加入 auth-user-pass 選項(這邊假設叫做us_west.ovpn

echo 'auth-user-pass ovpn_pass.txt' >> us_west.ovpn

複製設定檔到 /etc/openvpn 資料夾,並把副檔名改成 .conf(本例為 us_west.ovpn

mv us_west.ovpn /etc/openvpn/us_west.conf
chmod 600 /etc/openvpn/us_west.conf

編輯設 /etc/default/openvpn 定檔,設定自動啟動,加入這一行(這邊用 us_west 舉例,請改成自己的設定檔名子)

AUTOSTART="us_west"

雖然不確定原因(我猜是因為 PID mapping),不過在 Container 裡面使用 OpenVPN Daemon 的話,請務必編輯 /lib/systemd/system/[email protected] 把下面那一行註解掉

LimitNPROC=10

完成之後記得 reload

systemctl daemon-reload

除了重新啟動 Container 之外,我們也可以透過 systemctl 手動操作

systemctl start openvpn@us_west

可以用這個指令來檢查自己的 IP 是不是有變

curl http://ipecho.net/plain

讓 LXD 存取外面的資料夾

lxc launch ubuntu:18.04 Share

假設你的 container 叫做 Share

+-------+---------+------+-----------------------------------------------+------------+-----------+
| NAME  |  STATE  | IPV4 |                     IPV6                      |    TYPE    | SNAPSHOTS |
+-------+---------+------+-----------------------------------------------+------------+-----------+
| Share | RUNNING |      | fd42:d75f:90b5:e90b:216:3eff:fe13:ba17 (eth0) | PERSISTENT | 0         |
+-------+---------+------+-----------------------------------------------+------------+-----------+

假設你要分享家目錄裡的 Share 資料夾,並掛在 /mnt

lxc config device add Share myshare disk path=/mnt source=/home/使用者/Share

我們可以看到 Share 資料夾已經被掛載進來了,不過檔案擁有者好像怪怪的(不信可以自己 df 看看)

root@Share:/mnt# ls -l
total 0
-rw-rw-r-- 1 nobody nogroup 0 Nov 24 07:06 bar
-rw-rw-r-- 1 nobody nogroup 0 Nov 24 07:06 foo

而且沒辦法新增檔案?!

root@Share:/mnt# touch foobar
touch: cannot touch 'foobar': Permission denied

這是因為 idmap 的關係,透過這樣的機制,可以讓 Container 裡面執行的程式幾乎不可能逃出來

如果沒有特別更改的話,預設的情況是 +100000,也就是說 Container 裡面的 root 其實是 uid=100000 的一般使用者

這裡有兩種解法:

  1. 更改 Share 資料夾的擁有者
sudo chown -R 100000:100000 ~/Share
  1. 手動為這個 Container 設定 idmap,這個比較複雜,請見下一章節

手動設定 idmap

假設你的 container 叫做 Share

+-------+---------+------+-----------------------------------------------+------------+-----------+
| NAME  |  STATE  | IPV4 |                     IPV6                      |    TYPE    | SNAPSHOTS |
+-------+---------+------+-----------------------------------------------+------------+-----------+
| Share | RUNNING |      | fd42:d75f:90b5:e90b:216:3eff:fe13:ba17 (eth0) | PERSISTENT | 0         |
+-------+---------+------+-----------------------------------------------+------------+-----------+

首先必須先關閉 Container,這樣才有辦法儲存設定

lxc stop Share

設定 idmap,把 Container 裡面的 ubuntu(uid=1000)對應到外面的使用者(uid=1000

lxc config set Share raw.idmap 'both 1000 1000'

還沒完,接下來還要編輯 /etc/subuid/etc/subgid 這兩個檔案,允許這樣的對應

echo "root:1000:1" | sudo tee -a /etc/subuid
echo "root:1000:1" | sudo tee -a /etc/subgid

為了套用剛才的修改,必須要重新啟動整個 LXD 服務,請先確定所有的 Container 都已經關閉

+-------+---------+------+------+------------+-----------+
| NAME  |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-------+---------+------+------+------------+-----------+
| Share | STOPPED |      |      | PERSISTENT | 0         |
+-------+---------+------+------+------------+-----------+

重新啟動 LXD

sudo systemctl restart lxd

進入 Container 看看

lxc exec Share -- su ubuntu --login

噹噹!

ubuntu@Share:/mnt$ ls -l
total 0
-rw-rw-r-- 1 ubuntu ubuntu 0 Nov 24 07:06 bar
-rw-rw-r-- 1 ubuntu ubuntu 0 Nov 24 07:06 foo

轉移現有的 container 到其他主機

lxc launch ubuntu:18.04 xenial

假設你的 container 叫做 xenial

+--------+---------+-----------------------+----------------------------------------------+------------+-----------+
|  NAME  |  STATE  |         IPV4          |                     IPV6                     |    TYPE    | SNAPSHOTS |
+--------+---------+-----------------------+----------------------------------------------+------------+-----------+
| xenial | RUNNING |                       | fd42:5f2:e4a1:2b7f:216:3eff:fe22:26c4 (eth0) | PERSISTENT | 0         |
+--------+---------+-----------------------+----------------------------------------------+------------+-----------+

兩台主機的 IP 分別是:

Host IP
VSV_1 192.168.1.31
VSV_2 192.168.1.32

首先有一件事情很重要要先講:轉移的時候是 從來源主機把現有的 Container pull 過來

[VSV_1]:允許 VSV_2(新主機)連線到 VSV_1(舊主機)

# 設定 bind 位址和 port
lxc config set core.https_address 0.0.0.0:8443
# 設定密碼
lxc config set core.trust_password myPassword
# 設定 ufw
sudo ufw allow from 192.168.1.32 to any port 8443 proto tcp

[VSV_2]:把 VSV_1(舊主機)加為遠端主機

$ lxc remote add VSV_2 192.168.1.32
Generating a client certificate. This may take a minute...
Certificate fingerprint: ????????????????????????????????????????????????????????????????
ok (y/n)? y
Admin password for VSV_2:
Client certificate stored at server:  VSV_2

$ lxc remote list
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
|      NAME       |                   URL                    |   PROTOCOL    |  AUTH TYPE  | PUBLIC | STATIC |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| images          | https://images.linuxcontainers.org       | simplestreams | none        | YES    | NO     |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| local (default) | unix://                                  | lxd           | file access | NO     | YES    |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| VSV_2           | https://192.168.1.32:8443                | lxd           | tls         | NO     | NO     |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| ubuntu          | https://cloud-images.ubuntu.com/releases | simplestreams | none        | YES    | YES    |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| ubuntu-daily    | https://cloud-images.ubuntu.com/daily    | simplestreams | none        | YES    | YES    |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+

[VSV_2]:從 VSV_1(舊主機)把 container 搬過來

lxc copy VSV_2:xenial xenial

[VSV_2]:噹噹!

+--------+---------+-----------------------+----------------------------------------------+------------+-----------+
|  NAME  |  STATE  |         IPV4          |                     IPV6                     |    TYPE    | SNAPSHOTS |
+--------+---------+-----------------------+----------------------------------------------+------------+-----------+
| xenial | RUNNING |                       | fd42:a043:df96:b02e:216:3eff:fe57:771 (eth0) | PERSISTENT | 0         |
+--------+---------+-----------------------+----------------------------------------------+------------+-----------+

參考文件

One response to “使用 LXD 的一些小技巧

  1. 謝謝你的分享,剛開始用LXC開instance一直很不清楚如何對掛載點和網路做mapping。
    你這樣解釋就清楚多了

發表迴響