Fedora 中的容器技術:systemd-nspawn

John M. Harris, Jr.發表於2016-07-28

歡迎來到“Fedora 中的容器技術”系列!本文是該系列文章中的第一篇,它將說明你可以怎樣使用 Fedora 中各種可用的容器技術。本文將學習 systemd-nspawn 的相關知識。

容器是什麼?

一個容器就是一個使用者空間例項,它能夠在與託管容器的系統(叫做宿主系統)相隔離的環境中執行一個程式或者一個作業系統。這和 chroot虛擬機器 的思想非常類似。執行在容器中的程式是由與宿主作業系統相同的核心來管理的,但它們是與宿主檔案系統以及其它程式隔離開的。

什麼是 systemd-nspawn?

systemd 專案認為應當將容器技術變成桌面的基礎部分,並且應當和使用者的其餘系統整合在一起。為此,systemd 提供了 systemd-nspawn,這款工具能夠使用多種 Linux 技術建立容器。它也提供了一些容器管理工具。

systemd-nspawnchroot 在許多方面都是類似的,但是前者更加強大。它虛擬化了檔案系統、程式樹以及客戶系統中的程式間通訊。它的吸引力在於它提供了很多用於管理容器的工具,例如用來管理容器的 machinectl。由 systemd-nspawn 執行的容器將會與 systemd 元件一同執行在宿主系統上。舉例來說,一個容器的日誌可以輸出到宿主系統的日誌中。

在 Fedora 24 上,systemd-nspawn 已經從 systemd 軟體包分離出來了,所以你需要安裝 systemd-container 軟體包。一如往常,你可以使用 dnf install systemd-container 進行安裝。

建立容器

使用 systemd-nspawn 建立一個容器是很容易的。假設你有一個專門為 Debian 創造的應用,並且無法在其它發行版中正常執行。那並不是一個問題,我們可以創造一個容器!為了設定容器使用最新版本的 Debian(現在是 Jessie),你需要挑選一個目錄來放置你的系統。我暫時將使用目錄 ~/DebianJessie

一旦你建立完目錄,你需要執行 debootstrap,你可以從 Fedora 倉庫中安裝它。對於 Debian Jessie,你執行下面的命令來初始化一個 Debian 檔案系統。

$ debootstrap --arch=amd64 stable ~/DebianJessie

以上預設你的架構是 x86_64。如果不是的話,你必須將架構的名稱改為 amd64。你可以使用 uname -m 得知你的機器架構。

一旦設定好你的根目錄,你就可以使用下面的命令來啟動你的容器。

$ systemd-nspawn -bD ~/DebianJessie

容器將會在數秒後準備好並執行,當你試圖登入時就會注意到:你無法使用你的系統上任何賬戶。這是因為 systemd-nspawn 虛擬化了使用者。修復的方法很簡單:將之前的命令中的 -b 移除即可。你將直接進入容器的 root 使用者的 shell。此時,你只能使用 passwd 命令為 root 設定密碼,或者使用 adduser 命令新增一個新使用者。一旦設定好密碼或新增好使用者,你就可以把 -b 標誌新增回去然後繼續了。你會進入到熟悉的登入控制檯,然後你使用設定好的認證資訊登入進去。

以上對於任意你想在容器中執行的發行版都適用,但前提是你需要使用正確的包管理器建立系統。對於 Fedora,你應使用 DNF 而非 debootstrap。想要設定一個最小化的 Fedora 系統,你可以執行下面的命令,要將“/absolute/path/”替換成任何你希望容器存放的位置。

$ sudo dnf --releasever=24 --installroot=/absolute/path/ install systemd passwd dnf fedora-release

設定網路

如果你嘗試啟動一個服務,但它繫結了你宿主機正在使用的埠,你將會注意到這個問題:你的容器正在使用和宿主機相同的網路介面。幸運的是,systemd-nspawn 提供了幾種可以將網路從宿主機分開的方法。

本地網路

第一種方法是使用 --private-network 標誌,它預設僅建立一個迴環裝置。這對於你不需要使用網路的環境是非常理想的,例如構建系統和其它持續整合系統。

多個網路介面

如果你有多個網路介面裝置,你可以使用 --network-interface 標誌給容器分配一個介面。想要給我的容器分配 eno1,我會新增選項 --network-interface=eno1。當某個介面分配給一個容器後,宿主機就不能同時使用那個介面了。只有當容器徹底關閉後,宿主機才可以使用那個介面。

共享網路介面

對於我們中那些並沒有額外的網路裝置的人來說,還有其它方法可以訪問容器。一種就是使用 --port 選項。這會將容器中的一個埠定向到宿主機。使用格式是 協議:宿主機埠:容器埠,這裡的協議可以是 tcp 或者 udp宿主機埠 是宿主機的一個合法埠,容器埠 則是容器中的一個合法埠。你可以省略協議,只指定 宿主機埠:容器埠。我通常的用法類似 --port=2222:22

你可以使用 --network-veth 啟用完全的、僅宿主機模式的網路,這會在宿主機和容器之間建立一個虛擬的網路介面。你也可以使用 --network-bridge 橋接二者的連線。

使用 systemd 元件

如果你容器中的系統含有 D-Bus,你可以使用 systemd 提供的實用工具來控制並監視你的容器。基礎安裝的 Debian 並不包含 dbus。如果你想在 Debian Jessie 中使用 dbus,你需要執行命令 apt install dbus

machinectl

為了能夠輕鬆地管理容器,systemd 提供了 machinectl 實用工具。使用 machinectl,你可以使用 machinectl login name 登入到一個容器中、使用 machinectl status name檢查狀態、使用 machinectl reboot name 啟動容器或者使用 machinectl poweroff name 關閉容器。

其它 systemd 命令

多數 systemd 命令,例如 journalctl, systemd-analyzesystemctl,都支援使用 --machine 選項來指定容器。例如,如果你想檢視一個名為 “foobar” 的容器的日誌,你可以使用 journalctl --machine=foobar。你也可以使用 systemctl --machine=foobar status service 來檢視執行在這個容器中的服務狀態。

和 SELinux 一起工作

如果你要使用 SELinux 強制模式(Fedora 預設模式),你需要為你的容器設定 SELinux 環境。想要那樣的話,你需要在宿主系統上執行下面兩行命令。

$ semanage fcontext -a -t svirt_sandbox_file_t "/path/to/container(/.*)?"
$ restorecon -R /path/to/container/

確保使用你的容器路徑替換 “/path/to/container”。對於我的容器 "DebianJessie",我會執行下面的命令:

$ semanage fcontext -a -t svirt_sandbox_file_t "/home/johnmh/DebianJessie(/.*)?"
$ restorecon -R /home/johnmh/DebianJessie/

via: https://fedoramagazine.org/container-technologies-fedora-systemd-nspawn/

作者:John M. Harris, Jr. 譯者:ChrisLeeGit 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

相關文章