containers - 如何使用 --uidmap/gidmap 和 --net-host 选项正确运行具有 containerd 的 ctr 的容器
问题描述
我正在运行一个容器,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
}
],
另外不要使用网络命名空间,这意味着省略条目
{
"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
。由于容器内的 root 用户映射到的主机上的用户没有创建主机网络命名空间,因此它没有CAP_SYS_ADMIN
。
删除安装
sysfs
。在
config.json
thatrunc
使用中,删除以下部分"mounts"
:{ "destination": "/sys", "type": "sysfs", "source": "sysfs", "options": [ "nosuid", "noexec", "nodev", "ro" ] },
就我而言,我也无法 mount
/etc/resolv.conf
。通过删除这 2 个,容器确实运行良好并具有主机网络访问权限。不过,这不起作用ctr
。设置从主机网络命名空间到容器网络空间的桥接(参见此处和slirp4netns)。
如果可能的话,使用 docker 或 podman 似乎为此目的使用slirp4netns 。有一个老白鲸问题也可能很有趣。
推荐阅读
- c# - 使用带有独立 C# exe 的配置文件
- android - 如果空闲则关闭活动
- jenkins - Jenkins 使用 Gradle “构建参数”
- javascript - 如何使用数据表中的单元格值读取下拉选择?
- sql - VBA 访问 - 根据用户输入在表中添加新记录并自动完成其余记录
- javascript - jQuery 没有在 HTMLInputElement.onclick 中定义
- mysql - 计算工作时间的两行之间的时间差
- benchmarking - 基准测试多个难度ComparatorClass?
- android - 如何在 Kotlin 中创建具有不同布局的 ViewPager?
- google-sheets - Excel if 公式表达式