如何构建一个特权 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
不过,在引用的模板中使用LXC_MAPPED_GID
和后,似乎没有什么特别的地方。事实上,它所做的只是调整文件所有权 ( + )。但模板中的扩展属性可能已经经过微调,以实现所需的任何“魔法”。LXC_MAPPED_UID
lxc-download
chgrp
chown
download
在评论中Stéphane Graber 的这篇博文斯蒂芬告诉一位评论者
不幸的是,没有简单的方法可以做到这一点,您需要更新容器配置以匹配非特权容器的配置,将容器的目录移动到您希望其运行的非特权用户,然后使用 Serge 的 uidshift 程序来更改所有文件的所有权。
... 并:
- 看一下https://jenkins.linuxcontainers.org/
download
对于为模板构建的包 - 签
uidmapshift
出自这里- 该程序似乎大致
lxc-usernsexec -m b:0:1000:1 -m b:1:190000:1 -- /bin/chown 1:1 $file
按照中的解释进行lxc-usernsexec(1)
- 该程序似乎大致
但没有进一步的指示。
所以我的问题是:我如何才能将我自己构建的普通(特权)LXC 容器(拥有root
和全部)迁移到非特权容器?即使您无法提供脚本等,如果知道要考虑哪些要点以及它们如何影响运行非特权 LXC 容器的能力,那就太好了。我可以自己想出一个脚本,并保证如果能找到解决方案,我会将其作为该问题的答案发布:)
笔记:虽然我使用的是 Ubuntu 14.04,但这是一个通用的问题。
答案1
我只是做了一些非常类似的事情,将 KVM 虚拟机移动到非特权 LXC 中。
我为此使用了系统容器(因此它们可以在启动时自动启动),但使用映射的 UID/GID(用户命名空间)。
- 编辑 /etc/subuid,subgid (我将 uid/gids 10M-100M 映射到 root 并每个容器使用 100K)
- 对于第一个容器,在 /var/lib/lxc/CTNAME/config 中使用 u/gids 10000000-10099999
- 将容器存储安装在 /var/lib/lxc/CTNAME/rootfs 上(或者,如果每个容器不使用单独的卷/数据集/任何内容,则不执行任何操作)
- chown 10000000:10000000 /var/lib/lxc/CTNAME/rootfs
- setfacl -mu:10000000:x /var/lib/lxc (或简单地 chmod o+x /var/lib/lxc)
- lxc-usernsexec -mb:0:10000000:100000 --/bin/bash
现在您位于第一个容器用户命名空间中。一切都一样,但您的进程认为它的 uid 是 0,而实际上在主机命名空间中它的 uid 是 10000000。检查 /proc/self/uid_map 以查看您的 uid 是否已映射。您会注意到您无法再从 /root 读取内容,并且它似乎由无人/无组拥有。
在用户命名空间中,我从原始主机进行 rsync。
在用户命名空间之外,您将看到 /var/lib/lxc/CTNAME/rootfs 中的文件现在不属于与原始安装相同的预期 uid,而是 10000000+remote_uid。这就是你想要的。
就是这样。当你同步数据时,从容器的 /etc/fstab 中删除所有内容,这样它就不会尝试挂载东西,并且它应该启动。可能还有其他事情需要更改,请检查容器化发行版的 LXC 模板的作用。您绝对可以删除容器中的内核、grub、ntp 和任何硬件探测包(您甚至不必运行它,您可以从用户命名空间 chroot 到容器)
如果您没有正在运行的远程虚拟机,您还可以将原始虚拟机存储挂载到主机命名空间中,并通过 rsync/SSH 返回到本地主机。效果是一样的。
如果您(看起来)只是想将特权容器更改为非特权容器,您不妨添加 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
这应该是所有需要做的事情,现在您应该能够以非特权方式运行容器。上面的例子效率极低,uidshift 可能会做得更好(但我还没有使用它)。
HTH。
答案2
我想警告一下,当符号链接指向容器中的这些文件时,Borut Mrak 的示例代码也会更改主机系统上文件的所有权!根本不是你想要的!
如果您有专用的文件系统,您应该使用 -h 标志进行 chown/chgrp 和/或使用 -mount 进行查找。
这是我的更快更智能的版本:
find "/var/lib/lxc/$name/rootfs" -mount -uid '-65536' -printf '%U\n'|sort -n|uniq|while read i; do
find "/var/lib/lxc/$name/rootfs" -mount -uid "$i" -exec chown -h "$((200000+i))" \{\} \;
done
find "/var/lib/lxc/$name/rootfs" -mount -gid '-65536' -printf '%G\n'|sort -n|uniq|while read i; do
find "/var/lib/lxc/$name/rootfs" -mount -gid "$i" -exec chgrp -h "$((200000+i))" \{\} \;
done
答案3
阿尔卑斯Linux现在使用uidmapshift
转换成lua
到将特权容器转换为非特权容器。看看initd
脚本查看设置/创建的其他文件夹权限和要求。 ( /etc/subuid
& /etc/subgid
)
答案4
用于小丑容器
SUBUID_OFFSET=-65536
SUBGID_OFFSET=-65536
cd rootfs || exit 1
find .|while read i; do SUBUID=$(stat --format=%u $i); SUBGID=$(stat --format=%g $i); NEW_SUBUID=$((SUBUID+SUBUID_OFFSET)); NEW_SUBGID=$((SUBGID+SUBGID_OFFSET)); echo "chown -h $NEW_SUBUID.$NEW_SUBGID $i"; done
用于迁移linux系统
SUBUID=100000
SUBGID=100000
cd rootfs || exit 1
find .|while read i; do CURRENT_UID=$(stat --format=%u $i); CURRENT_GID=$(stat --format=%g $i); NEW_SUBUID=$((CURRENT_UID+SUBUID)); NEW_SUBGID=$((CURRENT_GID+SUBGID)); echo "chown -h $NEW_SUBUID.$NEW_SUBGID $i"; done