什么
希望标题中的问题有意义。我想创建一个低开销(因此没有虚拟机)的主机操作系统副本,并在 Linux 容器中运行。
我正在考虑以某种方式使用 zfs 创建主机 rootfs 的快照,然后以某种方式将其输入到 lxc。这样,容器中的任何更改都会通过 ZFS 的写时复制功能限制在容器中,并且对主机 rootfs 的任何未来更改都不会传播到容器。
我需要考虑哪些潜在问题,例如递归目录造成的破坏或其他问题?
为什么
这样做的原因是,我可以快速使用主机作为模板并进行操作,例如,安装新的构建工具来污染 rootfs,而不必担心这会影响主机,也不必浪费大量驱动器空间来复制主机 rootfs。此外,我花了相当多的时间按照我喜欢的方式设置主机,并且不想再花几天时间创建该过程的模板(尽管我应该这样做,但把一切都写下来是个好主意,自动化就更好了)。因为这将在 Linux 容器中,所以我可以同时运行多个实例。
答案1
我起草了一个可以完成此操作的手动程序。
先决条件
这些程序做出以下假设:
- 你的壳是
/bin/bash
。 - 你是 root。
- 您已在 ZFS 池上部署了操作系统
rpool
,并且还希望 LXD 容器位于同一个 ZFS 池上(rpool
)。 - 您的主机 rootfs 已安装到
rpool/ROOT/os
ZFS 数据集。 - 您拍摄了主机 rootfs 的快照并将其命名为
rpool/ROOT/os@20180516T091126CDT
。 - 您正在运行SnappyLXD 包。
- 您有一个在源上使用驱动程序
lxc storage
命名的。rpool
zfs
rpool/lxd
- 您想要创建一个名为 的非特权容器
demo
。
您必须针对与上述要求的每一次偏差调整程序。
指示
使用与主机操作系统类似的图像创建 LXC 容器:
root@node51 [~]# lxc launch images:ubuntu/18.04 demo -s rpool Creating demo Starting demo
停止容器:
root@node51 [~]# lxc stop demo
挂载 LXC 存储卷,以便我们可以从中获取一些元数据:
root@node51 [~]# zfs mount rpool/lxd/containers/demo
将元数据复制到某处(例如
/tmp/demo/
):root@node51 [~]# rsync -avHXShPs --exclude rootfs/ /var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo/ /tmp/demo/ sending incremental file list created directory /tmp/demo ./ backup.yaml 2.05K 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=4/6) metadata.yaml 529 100% 516.60kB/s 0:00:00 (xfr#2, to-chk=3/6) templates/ templates/hostname.tpl 21 100% 20.51kB/s 0:00:00 (xfr#3, to-chk=1/6) templates/hosts.tpl 140 100% 136.72kB/s 0:00:00 (xfr#4, to-chk=0/6) sent 3.12K bytes received 135 bytes 6.50K bytes/sec total size is 2.74K speedup is 0.84
删除 LXC 创建的 ZFS 数据集:
root@node51 [~]# zfs destroy rpool/lxd/containers/demo
将 ZFS 数据集克隆为 LXC 期望的相同名称:
root@node51 [~]# zfs clone rpool/ROOT/os@20180516T091126CDT rpool/lxd/containers/demo
将挂载点设置为原始挂载点:
root@node51 [~]# zfs set mountpoint=/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo rpool/lxd/containers/demo
为新容器数据创建 rootfs 目录:
root@node51 [~]# mkdir -v /var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo/rootfs/ mkdir: created directory '/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo/rootfs/'
扩展 shell 的通配符功能确保即将
mv
获取所有文件系统数据:root@node51 [~]# shopt -s extglob ; shopt -s dotglob
cd
通过进入容器的数据集合来缩短即将到来的命令:root@node51 [~]# cd /var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo/ root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]#
将所有容器的数据移动到
rootfs/
文件夹中:root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# mv !(rootfs) rootfs/
创建容器启动所需的一些文件夹:
root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# mkdir rootfs/{dev,sys,proc}
将之前备份的元数据移动到容器的数据集中:
root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# mv /tmp/demo/* .
从元数据备份中删除空的临时目录:
root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# rm -rfv /tmp/demo removed directory '/tmp/demo'
返回到上一个目录,以便可以卸载容器的数据集:
root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# cd - /root
卸载容器的数据集,以便 LXC 可以接管它:
root@node51 [~]# zfs umount rpool/lxd/containers/demo
要告诉 LXC 在下次启动时将容器的文件转换为非特权,请运行
lxc config edit demo
并修改以下行
volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
到
volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":0,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":0,"Nsid":0,"Maprange":1000000000}]'
启动容器。
这将需要一段时间,因为容器的 rootfs 中的每个文件都将转换为非特权。 没有进度指示器。root@node51 [~]# lxc start demo
进入容器:
root@node51 [~]# lxc exec demo -- bash
从这里,您可以配置网络、systemd 启动顺序和/或启动并运行主机的 LXC 容器克隆所需的其他内容。