centos7下docker配置user-namespace后启动容器失败

运行环境:

os: CentOS Linux release 7.6.1810 (Core)
docker: 19.03.4

错误提示

1
2
3
[root@localhost ~]# docker run -it --rm centos:8 /bin/bash --login
docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "process_linux.go:319: getting the final child's pid from pipe caused \"EOF\"": unknown.
[root@localhost ~]#

原因

redhat7.4版本的release notes中说明7.4版本已经支持了user namespace特性,但是 user.max_user_namespace 的默认值是0。如果要使用user namespace功能需要修改该默认值。

同时7.4版本中将非特权用户的user namespace功能设置为了技术预览。可以通过配置内核启动参数 namespace.unpriv_enable=1 来打开该功能。设置了该功能后,非特权用户通过传递CLONE_NEWNS选项来调用 clone() 时不再返回错误而是允许该操作。

However, to enable the unprivileged access to name spaces, the CAP_SYS_ADMIN flag has to be set in some user name space to create a mount name space

解决方法

设置max_user_namespace

1
2
3
4
5
6
7
8
9
#方法一
echo 15000 > /proc/sys/user/max_user_namespace

#方法二
sysctl -w 15000 user.max_user_namespace

#方法三
echo "user.max_user_namespaces=15000" >> /etc/sysctl.conf
reboot

方法一和方法二重启后配置会丢失

设置namespace.unpriv_enable

1
2
3
# 打开namespace.unpriv_enable
sudo grubby --args="namespace.unpriv_enable=1 user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
reboot

执行该命令前 /boot/grub2/grub.cfg 部分内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
menuentry 'CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-957.el7.x86_64-advanced-76bc0bdb-c41f-47f8-aae1-72561c04faa5' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_msdos
insmod xfs
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6904b786-8e67-448b-9eac-2c768f1f9aa6
else
search --no-floppy --fs-uuid --set=root 6904b786-8e67-448b-9eac-2c768f1f9aa6
fi
linux16 /vmlinuz-3.10.0-957.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=zh_CN.UTF-8
initrd16 /initramfs-3.10.0-957.el7.x86_64.img
}

执行该命令后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
menuentry 'CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-957.el7.x86_64-advanced-76bc0bdb-c41f-47f8-aae1-72561c04faa5' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_msdos
insmod xfs
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6904b786-8e67-448b-9eac-2c768f1f9aa6
else
search --no-floppy --fs-uuid --set=root 6904b786-8e67-448b-9eac-2c768f1f9aa6
fi
linux16 /vmlinuz-3.10.0-957.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=zh_CN.UTF-8 namespace.unpriv_enable=1 user_namespace.enable=1
initrd16 /initramfs-3.10.0-957.el7.x86_64.img
}
1
2
3
# 关闭namespace.unpriv_enable
sudo grubby --remove-args="namespace.unpriv_enable=1 user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
reboot