systemd-nspawn以及container的学习
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