LXD 2.0 系列(六):遠(yuǎn)程主機(jī)及容器遷移
這是 LXD 2.0 系列介紹文章的第六篇。
遠(yuǎn)程協(xié)議
LXD 2.0 支持兩種協(xié)議:
- LXD 1.0 API:這是在客戶端和 LXD 守護(hù)進(jìn)程之間使用的 REST API,以及在 LXD 守護(hù)進(jìn)程間復(fù)制/移動(dòng)鏡像和容器時(shí)使用的 REST API。
- Simplestreams:Simplestreams 協(xié)議是 LXD 客戶端和守護(hù)進(jìn)程使用的只讀、僅針對(duì)鏡像的協(xié)議,用于客戶端和 LXD 守護(hù)進(jìn)程獲取鏡像信息以及從一些公共鏡像服務(wù)器(如 Ubuntu 鏡像)導(dǎo)入鏡像。
以下所有內(nèi)容都將使用這兩個(gè)協(xié)議中的第一個(gè)。
安全
LXD API 的驗(yàn)證是通過(guò)客戶端證書(shū)在 TLS 1.2 上使用最近的密鑰驗(yàn)證的。 當(dāng)兩個(gè) LXD 守護(hù)進(jìn)程必須直接交換信息時(shí),源守護(hù)程序生成一個(gè)臨時(shí)令牌,并通過(guò)客戶端傳輸?shù)侥繕?biāo)守護(hù)程序。 此令牌僅可用于訪問(wèn)特定流,并且會(huì)被立即撤銷,因此不能重新使用。
為了避免中間人攻擊,客戶端工具還將源服務(wù)器的證書(shū)發(fā)送到目標(biāo)服務(wù)器。這意味著對(duì)于特定的下載操作,目標(biāo)服務(wù)器會(huì)被提供源服務(wù)器的 URL、所需資源的一次性訪問(wèn)令牌以及服務(wù)器應(yīng)該使用的證書(shū)。 這可以防止中間人攻擊,并且只允許臨時(shí)訪問(wèn)所傳輸?shù)膶?duì)象。
網(wǎng)絡(luò)需求
LXD 2.0 使用這樣一種模型,某個(gè)操作的目標(biāo)(接收端)直接連接到源以獲取數(shù)據(jù)。
這意味著你必須確保目標(biāo)服務(wù)器可以直接連接到源、可以更新任何所需的防火墻。
我們有個(gè)允許反向連接的計(jì)劃,允許通過(guò)客戶端代理本身以應(yīng)對(duì)那些嚴(yán)格的防火墻阻止兩臺(tái)主機(jī)之間通信的罕見(jiàn)情況。
與遠(yuǎn)程主機(jī)交互
LXD 使用的是“遠(yuǎn)程”的概念,而不是讓我們的用戶總是提供主機(jī)名或 IP 地址,然后在他們想要與遠(yuǎn)程主機(jī)交互時(shí)驗(yàn)證證書(shū)信息。
默認(rèn)情況下,唯一真正的 LXD 遠(yuǎn)程配置是 local:,這也是默認(rèn)的遠(yuǎn)程(所以你不必輸入它的名稱)。這個(gè)本地(local:)遠(yuǎn)程使用 LXD REST API 通過(guò) unix 套接字與本地守護(hù)進(jìn)程通信。
添加一臺(tái)遠(yuǎn)程主機(jī)
假設(shè)你已經(jīng)有兩臺(tái)裝有 LXD 的機(jī)器:你的本機(jī)以及遠(yuǎn)程那臺(tái)我們稱為“foo”的主機(jī)。
首先你需要確保“foo”正在監(jiān)聽(tīng)網(wǎng)絡(luò),并設(shè)置了一個(gè)密碼,以便得到一個(gè)遠(yuǎn)程 shell,運(yùn)行:
- lxc config set core.https_address [::]:8443
- lxc config set core.trust_password something-secure
在你本地 LXD 上,你需要使它對(duì)網(wǎng)絡(luò)可見(jiàn),這樣我們可以從它傳輸容器和鏡像:
- lxc config set core.https_address [::]:8443
現(xiàn)在已經(jīng)在兩端完成了守護(hù)進(jìn)程的配置,你可以添加“foo”到你的本地客戶端:
- lxc remote add foo 1.2.3.4
(將 1.2.3.4 替換成你的 IP 或者 FQDN)
看上去像這樣:
- stgraber@dakara:~$ lxc remote add foo 2607:f2c0:f00f:2770:216:3eff:fee1:bd67
- Certificate fingerprint: fdb06d909b77a5311d7437cabb6c203374462b907f3923cefc91dd5fce8d7b60
- ok (y/n)? y
- Admin password for foo:
- Client certificate stored at server: foo
你接著可以列出遠(yuǎn)端服務(wù)器,你可以在列表中看到“foo”:
- stgraber@dakara:~$ lxc remote list
- +-----------------+-------------------------------------------------------+---------------+--------+--------+
- | NAME | URL | PROTOCOL | PUBLIC | STATIC |
- +-----------------+-------------------------------------------------------+---------------+--------+--------+
- | foo | https://[2607:f2c0:f00f:2770:216:3eff:fee1:bd67]:8443 | lxd | NO | NO |
- +-----------------+-------------------------------------------------------+---------------+--------+--------+
- | images | https://images.linuxcontainers.org:8443 | lxd | YES | NO |
- +-----------------+-------------------------------------------------------+---------------+--------+--------+
- | local (default) | unix:// | lxd | NO | YES |
- +-----------------+-------------------------------------------------------+---------------+--------+--------+
- | ubuntu | https://cloud-images.ubuntu.com/releases | simplestreams | YES | YES |
- +-----------------+-------------------------------------------------------+---------------+--------+--------+
- | ubuntu-daily | https://cloud-images.ubuntu.com/daily | simplestreams | YES | YES |
- +-----------------+-------------------------------------------------------+---------------+--------+--------+
與它交互
好了,所以我們已經(jīng)有了一臺(tái)定義好的遠(yuǎn)程服務(wù)器,我們現(xiàn)在可以做些什么?
現(xiàn)在,就如你看到的,唯一的不同是你必須告訴 LXD 要哪臺(tái)主機(jī)運(yùn)行。
比如:
- lxc launch ubuntu:14.04 c1
它會(huì)在默認(rèn)主機(jī)(lxc remote get-default),也就是你的本機(jī)上運(yùn)行。
- lxc launch ubuntu:14.04 foo:c1
這個(gè)會(huì)在 foo 上運(yùn)行。
列出遠(yuǎn)程主機(jī)正在運(yùn)行的容器可以這么做:
- stgraber@dakara:~$ lxc list foo:
- +------+---------+---------------------+-----------------------------------------------+------------+-----------+
- | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
- +------+---------+---------------------+-----------------------------------------------+------------+-----------+
- | c1 | RUNNING | 10.245.81.95 (eth0) | 2607:f2c0:f00f:2770:216:3eff:fe43:7994 (eth0) | PERSISTENT | 0 |
- +------+---------+---------------------+-----------------------------------------------+------------+-----------+
你要記住的一件事是你需要在遠(yuǎn)程主機(jī)上同時(shí)指定鏡像和容器。因此如果你在“foo”上有一個(gè)“my-image”的鏡像,并且希望從它創(chuàng)建一個(gè)“c2”的容器,你需要運(yùn)行:
- lxc launch foo:my-image foo:c2
最后,就如你希望的那樣得到一個(gè)遠(yuǎn)程容器的 shell:
- lxc exec foo:c1 bash
復(fù)制容器
在兩臺(tái)主機(jī)間復(fù)制容器就如它聽(tīng)上去那樣簡(jiǎn)單:
- lxc copy foo:c1 c2
你會(huì)有一個(gè)新的從遠(yuǎn)程“c1”復(fù)制過(guò)來(lái)的本地“c2”容器。這需要停止“c1”容器,但是你可以在運(yùn)行的時(shí)候只復(fù)制一個(gè)快照:
- lxc snapshot foo:c1 current
- lxc copy foo:c1/current c3
移動(dòng)容器
除非你在做實(shí)時(shí)遷移(將會(huì)在之后的文章中講到),不然你需要在移動(dòng)前先停止容器,接著就會(huì)如你預(yù)料的那樣。
- lxc stop foo:c1
- lxc move foo:c1 local:
這個(gè)例子等同于:
- lxc stop foo:c1
- lxc move foo:c1 c1
是如何工作的
正如你期望的那樣, 與遠(yuǎn)程容器的交互時(shí) LXD 使用的 REST API 并不是通過(guò)本地 Unix 套接字,而是通過(guò) HTTPS 傳輸。
當(dāng)兩個(gè)守護(hù)程序之間交互時(shí)會(huì)變得有些棘手,如復(fù)制和移動(dòng)的情況。
在這種情況下會(huì)發(fā)生:
- 用戶運(yùn)行l(wèi)xc move foo:c1 c1。
- 客戶端聯(lián)系 local: 遠(yuǎn)程以檢查是否現(xiàn)有“c1”容器。
- 客戶端從“foo”獲取容器信息。
- 客戶端從源“foo”守護(hù)程序請(qǐng)求遷移令牌。
- 客戶端將遷移令牌以及源 URL 和“foo”的證書(shū)發(fā)送到本地 LXD 守護(hù)程序以及容器配置和周圍設(shè)備。
- 然后本地 LXD 守護(hù)程序使用提供的令牌直接連接到“foo” a) 它連接到第一個(gè)控制 websocket b) 它協(xié)商文件系統(tǒng)傳輸協(xié)議(zfs 發(fā)送/接收,btrfs 發(fā)送/接收或者純 rsync) c) 如果在本地可用,它會(huì)解壓用于創(chuàng)建源容器的鏡像。這是為了避免不必要的數(shù)據(jù)傳輸。 d) 然后它會(huì)將容器及其任何快照作為增量傳輸。
- 如果成功,客戶端會(huì)命令“foo”刪除源容器。
在線嘗試
沒(méi)有兩臺(tái)機(jī)器來(lái)嘗試遠(yuǎn)端交互和復(fù)制/移動(dòng)容器?
沒(méi)有問(wèn)題,你可以使用我們的 demo 服務(wù)。這里甚至還包括了一步步的指導(dǎo)!
額外信息
LXD 的主站在: https://linuxcontainers.org/lxd
LXD 的 GitHub 倉(cāng)庫(kù): https://github.com/lxc/lxd
LXD 的郵件列表: https://lists.linuxcontainers.org
LXD 的 IRC 頻道: #lxcontainers on irc.freenode.net