如何创建一个继承主机根文件系统的 Linux 容器(可能使用 zfs)?

如何创建一个继承主机根文件系统的 Linux 容器(可能使用 zfs)?

什么

希望标题中的问题有意义。我想创建一个低开销(因此没有虚拟机)的主机操作系统副本,并在 Linux 容器中运行。

我正在考虑以某种方式使用 zfs 创建主机 rootfs 的快照,然后以某种方式将其输入到 lxc。这样,容器中的任何更改都会通过 ZFS 的写时复制功能限制在容器中,并且对主机 rootfs 的任何未来更改都不会传播到容器。

我需要考虑哪些潜在问题,例如递归目录造成的破坏或其他问题?

为什么

这样做的原因是,我可以快速使用主机作为模板并进行操作,例如,安装新的构建工具来污染 rootfs,而不必担心这会影响主机,也不必浪费大量驱动器空间来复制主机 rootfs。此外,我花了相当多的时间按照我喜欢的方式设置主机,并且不想再花几天时间创建该过程的模板(尽管我应该这样做,但把一切都写下来是个好主意,自动化就更好了)。因为这将在 Linux 容器中,所以我可以同时运行多个实例。

答案1

我起草了一个可以完成此操作的手动程序。

先决条件

这些程序做出以下假设:

  • 你的壳是/bin/bash
  • 你是 root。
  • 您已在 ZFS 池上部署了操作系统rpool,并且还希望 LXD 容器位于同一个 ZFS 池上(rpool)。
  • 您的主机 rootfs 已安装到rpool/ROOT/osZFS 数据集。
  • 您拍摄了主机 rootfs 的快照并将其命名为rpool/ROOT/os@20180516T091126CDT
  • 您正在运行SnappyLXD 包。
  • 您有一个在源上使用驱动程序lxc storage命名的。rpoolzfsrpool/lxd
  • 您想要创建一个名为 的非特权容器demo

您必须针对与上述要求的每一次偏差调整程序。

指示

  1. 使用与主机操作系统类似的图像创建 LXC 容器:

     root@node51 [~]# lxc launch images:ubuntu/18.04 demo -s rpool
     Creating demo
     Starting demo
    
  2. 停止容器:

     root@node51 [~]# lxc stop demo
    
  3. 挂载 LXC 存储卷,以便我们可以从中获取一些元数据:

     root@node51 [~]# zfs mount rpool/lxd/containers/demo
    
  4. 将元数据复制到某处(例如/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
    
  5. 删除 LXC 创建的 ZFS 数据集:

     root@node51 [~]# zfs destroy rpool/lxd/containers/demo
    
  6. 将 ZFS 数据集克隆为 LXC 期望的相同名称:

     root@node51 [~]# zfs clone rpool/ROOT/os@20180516T091126CDT rpool/lxd/containers/demo
    
  7. 将挂载点设置为原始挂载点:

     root@node51 [~]# zfs set mountpoint=/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo rpool/lxd/containers/demo
    
  8. 为新容器数据创建 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/'
    
  9. 扩展 shell 的通配符功能确保即将mv获取所有文件系统数据:

     root@node51 [~]# shopt -s extglob ; shopt -s dotglob
    
  10. 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]#
    
  11. 将所有容器的数据移动到rootfs/文件夹中:

    root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# mv !(rootfs) rootfs/
    
  12. 创建容器启动所需的一些文件夹:

    root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# mkdir rootfs/{dev,sys,proc}
    
  13. 将之前备份的元数据移动到容器的数据集中:

    root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# mv /tmp/demo/* .
    
  14. 从元数据备份中删除空的临时目录:

    root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# rm -rfv /tmp/demo
    removed directory '/tmp/demo'
    
  15. 返回到上一个目录,以便可以卸载容器的数据集:

    root@node51 [/var/snap/lxd/common/lxd/storage-pools/rpool/containers/demo]# cd -
    /root
    
  16. 卸载容器的数据集,以便 LXC 可以接管它:

    root@node51 [~]# zfs umount rpool/lxd/containers/demo
    
  17. 要告诉 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}]'
    
  18. 启动容器。
    这将需要一段时间,因为容器的 rootfs 中的每个文件都将转换为非特权。 没有进度指示器。

    root@node51 [~]# lxc start demo
    
  19. 进入容器:

    root@node51 [~]# lxc exec demo -- bash
    

    从这里,您可以配置网络、systemd 启动顺序和/或启动并运行主机的 LXC 容器克隆所需的其他内容。

相关内容