container的分類
目前container可以分為兩大類,一類是Privileged container,一類是Unprivileged container。
Privileged container內部的root跟container外部的root是同一個用戶(也就是UID都是0),如果在Privileged container中創建文件(比如在--bind
的目錄中創建文件),那么該文件在Host中的UID跟Container中的UID一樣。這樣可以做到與Host權限一一對應,某些情況下比較方便。
Unprivileged container內部的UID 0用戶其實是被映射到了container外部的某個unprivileged用戶,這是通過user namespace來實現的,如果在Unprivileged container中創建文件,那么該文件在Host中的UID跟Container中的不一樣,而是沒有對應用戶的一串數字(實際上Host可以指定一個有用戶的UID來作為Container的指定UID)。這樣可以保證當container被攻破時,Host仍然安全。
systemd-nspawn的默認情況
systemd-nspawn分兩種情況。
- 用
systemd-nspawn
直接啟動 - 通過
systemd-nspawn@.service
模板啟動,即machinectl
兩種方式啟動時默認選項不同。
通過systemd-nspawn@.service
模板啟動:
- 默認使用
-b,--boot
方式啟動。 - 默認使用 Unprivileged container 選項
-U
。 - 默認使用
-n,--network-veth
網絡配置。 - 默認使用
-j,--link-journal=try-guest
日志配置。
systemd-nspawn@.service
模板默認設置可以通過.nspawn
配置文件覆蓋掉。
machinectl
嘗試了一下machinectl
命令,差點以為把好不容易裝好的centos7容器給搞壞了。注意:machinectl
都是基於 systemd-nspawn@.service 模版啟動的。
常用命令:
machinectl start <machine_name>
:啟動容器machinectl stop <machine_name>
:關閉容器machinectl login <machine_name>
:顯示登錄界面machinectl enable/diable <machine_name>
:是否以systemd-nspawn@.service方式開機啟動
優先在 /var/lib/machines/
目錄中搜索, 但是也會在 /usr/local/lib/machines/
與 /usr/lib/machines/
目錄中搜索鏡像, 出於兼容性原因,還會在 /var/lib/container/
中搜索鏡像。
模板文件搜索規則
模板文件xxx.nspawn
:
- 如果在
/etc/systemd/nspawn/
與/run/systemd/nspawn/
目錄中找到了對應的配置文件, 那么將會應用其中的全部配置(但依然有可能會被命令行上的設置所覆蓋), 同時將會停止進一步的搜索。 - 如果沒有找到對應的配置文件, 那么將會進一步在容器鏡像文件的所在目錄、或容器根目錄的所在父目錄中搜索。 如果找到了對應的配置文件,那么將會僅應用其中的非特權指令, 所有特權指令, 也就是有可能造成權限提升或者要求訪問主機資源(例如主機的文件或目錄)的配置指令, 都將被忽略。
.nspawn
文件語法可以參考man
。
systemd-nspawn容器網絡配置
-n,--network-veth
配置方法:
- Host運行
systemd-networkd.service
,此時Host端無ip。之后和container運行,此時Host端會自動配置ip。 - container端配置ip地址,可以使用任何方式配置,比如
ip addr add
或者nmtui
或者使用systemd-networkd
。 - 確定Host內核開啟ip轉發功能。
- 確定Host端FORWARD鏈規則是否默認DROP。如果是,添加ACCEPT規則,可以參考Archwiki。
- 確定Host端iptables為ve-enth網卡開啟dhcp端口(67,68),否則Host無法為container自動分配地址。
systemd-networkd.service(8)
默認包含 /usr/lib/systemd/network/80-container-ve.network
, 此文件匹配所有通過該選項創建的虛擬以太網連接的宿主端接口, 此文件不但為這些接口啟用了 DHCP 功能,而且還為這些接口設置了通向宿主機外部網絡的路由(從而可以連通外網)。 該服務還默認包含 /usr/lib/systemd/network/80-container-host0.network
, 此文件匹配所有通過該選項創建的虛擬以太網連接的容器端接口,並且為這些接口啟用了 DHCP 功能。 如果在宿主與容器內同時運行了 systemd-networkd 服務, 那么無須額外的配置,即可自動實現在容器與宿主之間進行 IP 通信, 並且可以連接到外部網絡。
撤銷Unprivileged container造成的權限問題
撤銷 --private-users-chown
(或 -U
) 造成的影響,可以通過將容器的 UID/GIU 起點重置為"0"來實現:
systemd-nspawn … --private-users=0 --private-users-chown