Fedora 中的容器技術:systemd-nspawn
![](https://linuxstory.org/wp-content/uploads/2024/06/165435z20bv1330q40yvfd-800x400.png)
容器是什麼?
一個容器就是一個用戶空間實例,它能夠在與託管容器的系統(叫做宿主系統)相隔離的環境中運行一個程序或者一個操作系統。這和 chroot
或 虛擬機 的思想非常類似。運行在容器中的進程是由與宿主操作系統相同的內核來管理的,但它們是與宿主文件系統以及其它進程隔離開的。
什麼是 systemd-nspawn?
systemd 項目認為應當將容器技術變成桌面的基礎部分,並且應當和用戶的其餘系統集成在一起。為此,systemd 提供了 systemd-nspawn
,這款工具能夠使用多種 Linux 技術創建容器。它也提供了一些容器管理工具。
systemd-nspawn
和 chroot
在許多方面都是類似的,但是前者更加強大。它虛擬化了文件系統、進程樹以及客戶系統中的進程間通信。它的吸引力在於它提供了很多用於管理容器的工具,例如用來管理容器的 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-analyze
和 systemctl
,都支持使用 --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
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive