systemd-nspawn 入门笔记
介绍
systemd-nspawn
是一个类似chroot
一样的命令,用来启动一个容器,但是有比chroot
更加强大的功能,能够完全虚拟化文件系统、进程树等系统,同时对于容器的网络接口、资源占用进行限制。
systemd-nspawn
与docker类似,但又存在一些不同点,这些不同点主要是因为软件设计运行的场景不一样。Docker容器更加注重颗粒化的管理,容器作为最基本的单位,每个容器只运行单一的进程,并且由多个容器组成一个运用,比如如果要通过Docker运行WordPress
,还需要配置一个MariaDB
或是MySQL
容器,这样的架构方便进行集群和批量管理,能弹性的扩展资源,更适合在云计算平台上使用。
相对Docker而言,systemd-nspawn
的一些特点,让我觉得在一些场景上,systemd-nspawn
更适合个人/单机使用:
systemd-nspawn
启动一个容器则会完整的启动整个系统,可以把依赖的服务都集中到一个容器里面systemd-nspawn
是systemd
自带组件,而systemd
目前作为主流发行版的默认init
进程,基本上所有Linux发行版都会自带- 容器内到容器外的无缝对接,使用
systemctl
加上参数--machine
就可以控制容器内的服务,journalctl
也支持查看容器内服务的日志 systemd-nspawn
可以直接使用现在的文件系统作为容器的rootfs
启动,不同于Docker的copy-on-write
,这点看似比较傻瓜,却比较实用,特别是个人非常折腾的时候。
配置
容器的配置非常的简单,只要保证容器rootfs
存在,就可以启动容器,Debian
系容器使用工具debootstrap
下载,Arch对应使用pacstrap
安装,由于容器与主机共享内核,容器内部不需要安装内核和内核模块。
容器名称 | myContainer |
---|---|
服务单元 | [email protected] |
容器根目录 | /var/lib/machines/myContainer |
配置文件 | /etc/systemd/nspawn/myContainer.nspawn |
容器内部包括常见设定,包括root密码、时区、主机名等可以使用systemd-nspawn -D root
启动(忽略-b参数)跳过登录过程启动容器,之后进行配置。容器本身运行环境、资源限制则通过.nspawn
配置完成,主要的配置包括文件系统还有网络配置。
用户空间隔离:--private-users
这个参数用于隔离用户空间文件的uid/gid
,如果不设定这个参数,默认是打开的,即运行时候容器内和容器外,文件拥有者不一样,具体表现为容器内的uid/gid
在实际文件系统中会添加一段偏移,容器外可以控制容器内文件,但是如果直接拷贝文件到容器里面,容器内运行的进程是没有读写权限的。
如果启用了--private-users
参数,原有文件依旧会保持原有uid/gid
,只有在容器内发生读写的时候,产生新的文件才会映射到新的拥有者,通过开启--private-users-chown
参数,强行迫使原有文件全部映射到新的用户和用户组。同理,也可以反向操作,将发生偏移的容器内的文件,全部修改回正常的uid/gid
私有网络配置:--private-network
对应配置文件[Network]
下的Private
,启用这个参数之后,宿主机网络和容器网络将隔离开,只能通过NAT或是桥接方式通讯,设置--network-interface
、--network-macvlan
、--network-ipvlan
、--network-veth
都会间接开启私有网络。
--network-interface
参数指定一个网络给容器,这个参数不是共享网卡,而是直接从宿主机中移除这个网卡,并添加到容器中,在停用容器之后才会返回这个网卡。参数对应配置文件中[Network]Interface
。注意:不能直接把无线网卡分配给容器,如果要分配无线网卡给容器,无线网卡必须支持命名空间。
--network-macvlan
/--network-ipvlan
,相当于桥接,网卡的前缀是mv-
/iv-
,macvlan
是同个网卡不同MAC地址,ipvlan
是同个MAC地址不同IP
地址。这两个方法都有一个缺点,那就是无法直接于宿主机通讯,即使处于同一个网段下面。
--network-veth
,在主机和容器之间创建一个虚拟网卡,网卡前缀是ve-
,--network-bridge
把主机上的桥接网卡映射到容器里面,不能直接指定主机上的物理网卡,必须在主机端建立bridge之后,把这个bridge分配给容器,这个参数会间接启用--network-veth
。
其他的网络相关参数还有 --network-zone=
或是--port
,用于批量管理容器网络,后者用于暴露端口到主机,不过都是在开启私有网络并且配置完整的时候可以启用,具体可以去看手册。
要禁用私有网络,设定参数--network-veth=no
/--private-network=no
或是在配置文件里面添加:
[Network]
Private=no
VirtualEthernet=no
这样子容器于主机共享网络接口。
资源限定
限定容器能占用资源有时候也是非常重要的,这一部分可以参考systemd资源控制
systemctl set-property [email protected] MemoryMax=2G
systemctl set-property [email protected] CPUQuota=200%
容器管理
容器管理使用命令machinectl
,但是实际上也是等同systemctl
对应的命令
machinectl | systemctl | 说明 |
---|---|---|
machinectl list | systemctl list-machines | 列出正在运行的容器 |
machinectl login name | 连接到容器控制台 | |
machinectl status name | systemctl status systemd-nspawn@name | 查看容器运行状态 |
machinectl start name | systemctl start systemd-nspawn@name | 启动容器 |
machinectl poweroff name | systemctl stop systemd-nspawn@name | 关闭容器 |
machinectl reboot name | systemctl restart systemd-nspawn@name | 重启容器 |
machinectl terminate name | 强行停止容器,在容器没有反应的时候使用 | |
machinectl enable name | systemctl enable systemd-nspawn@name | 开机自启 |
machinectl disable name | systemctl disable systemd-nspawn@name | 禁用自启 |