我正在运行一个具有ctr
的容器,然后使用用户名称空间将容器内的用户(根)映射到主机上的另一个用户,我想使主机网络可用于容器。为此,我使用--net-host
选项。基于一个非常简单的测试容器
$ cat Dockerfile
FROM alpine
ENTRYPOINT ["/bin/sh"]
我试着用
sudo ctr run -rm --uidmap "0:1000:999" --gidmap "0:1000:999" --net-host docker.io/library/test:latest test
给出如下错误
ctr: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused "rootfs_linux.go:58: mounting \"sysfs\" to rootfs \"/run/containerd/io.containerd.runtime.v2.task/default/test/rootfs\" at \"/sys\" caused \"operation not permitted\""": unknown
如果我
- 删除
--net-host
标志或 - 删除
--uidmap
/--gidmap
参数
我尝试将主机为uid=1000
的用户添加到netdev
组,但仍然出现相同的错误。我可能需要使用网络名称空间吗?
编辑:
同时发现这是runc
内部的问题。如果我通过向config.json
"linux": {
"uidMappings": [
{
"containerID": 0,
"hostID": 1000,
"size": 999
}
],
"gidMappings": [
{
"containerID": 0,
"hostID": 1000,
"size": 999
}
],
和not使用网络命名空间,这意味着省略进入
{
"type": "network"
},
在"namespaces"
部分,我从runc
得到以下错误:
$ sudo runc run test
WARN[0000] exit status 1
ERRO[0000] container_linux.go:349: starting container process caused "process_linux.go:449: container init caused "rootfs_linux.go:58: mounting \"sysfs\" to rootfs \"/vagrant/test/rootfs\" at \"/sys\" caused \"operation not permitted\"""
container_linux.go:349: starting container process caused "process_linux.go:449: container init caused "rootfs_linux.go:58: mounting \"sysfs\" to rootfs \"/vagrant/test/rootfs\" at \"/sys\" caused \"operation not permitted\"""
终于在runc
中找到了这个问题的答案。它基本上是内核中的一个限制,即不拥有网络名称空间的用户没有CAP_SYS_ADMIN
功能,没有sysfs
功能就不能挂载CC_14。由于容器中的根用户映射到的主机上的用户没有创建主机网络命名空间,因此那里没有CAP_SYS_ADMIN
。
从runc
问题的讨论中,我现在确实看到了以下选项:
-
移除
sysfs
的安装。在
runc
使用的config.json
中,删除"mounts"
中的以下部分:{ "destination": "/sys", "type": "sysfs", "source": "sysfs", "options": [ "nosuid", "noexec", "nodev", "ro" ] },
在我的情况下,我也无法挂载
/etc/resolv.conf
。通过删除这两个,容器运行良好,并具有主机网络访问。 -
设置从主机网络命名空间到容器网络空间的桥接(参见这里和slirp4netns)。
-
使用docker或podman,如果可能的话,它们似乎使用slirp4netns来实现此目的。有一个老的moby问题也可能会很有趣。