通过将特权容器迁移到非特权容器,从头开始构建非特权(用户)LXC 容器

0xC*_*22L 5 linux lxc userns

如何构建特权 LXC (1.0.3) 容器(我知道的那部分)然后成功迁移它以在非特权状态下运行?也就是说,我想debootstrap自己做或调整lxc-ubuntu模板(通常在 下/usr/share/lxc/templates)以使其正常工作。

这就是我问这个问题的原因。如果您查看lxc-ubuntu模板,您会注意到:

# Detect use under userns (unsupported)
for arg in "$@"; do
    [ "$arg" = "--" ] && break
    if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
        echo "This template can't be used for unprivileged containers." 1>&2
        echo "You may want to try the \"download\" template instead." 1>&2
        exit 1
    fi
done
Run Code Online (Sandbox Code Playgroud)

但是,在引用模板中使用LXC_MAPPED_GID和之后,似乎没有什么特别的。事实上,它所做的只是调整文件所有权(+ )。但是模板中的扩展属性可能已经进行了微调,以完成任何需要的“魔法”。LXC_MAPPED_UIDlxc-downloadchgrpchowndownload

Stéphane Graber这篇博文的评论中,Stéphane 告诉一位评论者,

不幸的是,没有简单的方法可以做到这一点,您需要更新您的容器配置以匹配来自非特权容器的配置,将容器的目录移动到您希望它运行的非特权用户,然后使用 Serge 的 uidshift 程序更改所有文件的所有权。

... 并:

但没有进一步的指示。

所以我的问题是:如何将我自己(拥有root和全部)构建的普通(特权)LXC 容器迁移到非特权容器?即使您不能提供一个脚本左右,知道要考虑哪些点以及它们如何影响运行非特权 LXC 容器的能力也是很好的。如果可以找到解决方案,我可以自己想出一个脚本,并保证将其发布为这个问题的答案:)

注意:虽然我使用的是 Ubuntu 14.04,但这是一个通用问题。

小智 6

我只是在做一些非常相似的事情,将 KVM 虚拟机移动到非特权 LXC 中。

我为此使用了系统容器(因此它们可以在启动时自动启动),但使用映射的 UID/GID(用户命名空间)。

  1. 编辑 /etc/subuid,subgid(我将 uid/gids 10M-100M 映射到 root,每个容器使用 100K)
  2. 对于第一个容器,在 /var/lib/lxc/CTNAME/config 中使用 u/gids 10000000-10099999
  3. 将容器存储挂载到 /var/lib/lxc/CTNAME/rootfs (或者,如果您不使用单独的卷/数据集/每个容器的任何内容,则什么都不做)
  4. chown 10000000:10000000 /var/lib/lxc/CTNAME/rootfs
  5. setfacl -mu:10000000:x /var/lib/lxc (或简单地 chmod o+x /var/lib/lxc)
  6. lxc-usernsexec -mb:0:10000000:100000 -- /bin/bash

现在您位于第一个容器用户命名空间中。一切都一样,但您的进程认为它的 uid 是 0,而实际上在主机命名空间中它是 uid 10000000。检查 /proc/self/uid_map 以查看您的 uid 是否已映射。您会注意到您无法再从 /root 读取,并且它似乎归 nobody/nogroup 所有。

在用户命名空间中,我从原始主机同步。

在用户命名空间之外,您将看到 /var/lib/lxc/CTNAME/rootfs 中的文件现在不属于与原始安装相同的预期 uid,而是 10000000+remote_uid。这就是你想要的。

就是这样。同步数据后,从容器的 /etc/fstab 中删除所有内容,这样它就不会尝试挂载东西,它应该会启动。可能还有其他需要更改的地方,请检查容器化发行版的 LXC 模板的作用。你绝对可以删除容器中的内核、grub、ntp 和任何硬件探测包(你甚至不必运行它,你可以从用户命名空间 chroot 到容器)

如果您没有正在运行的远程 VM,您还可以将原始 VM 存储挂载到主机命名空间中,并将 rsync/SSH 重新加载到 localhost。效果是一样的。

如果您(看起来)只是想将您的特权容器更改为非特权容器,您不妨添加 uid/gid 映射,将上述映射添加到您的容器配置中,然后执行以下操作:

for i in `seq 0 65535`; do
  find /var/lib/lxc/CTNAME/rootfs -uid $i -exec chown $((10000000+i)) \{\} \;
  find /var/lib/lxc/CTNAME/rootfs -gid $i -exec chgrp $((10000000+i)) \{\} \;
done
Run Code Online (Sandbox Code Playgroud)

这应该就是所有需要做的事情,现在您应该能够以无特权的方式运行容器。上面的这个例子效率极低,uidshift 可能会在这方面做得更好(但我还没有使用它)。

哈。